Merge branch 'master' of https://github.com/Microsoft/TypeScript into fixingTypeParameters

This commit is contained in:
Jason Freeman
2015-07-14 15:07:59 -07:00
84 changed files with 1482 additions and 422 deletions
+89 -39
View File
@@ -3943,7 +3943,7 @@ namespace ts {
let id = getTypeListId(elementTypes);
let type = tupleTypes[id];
if (!type) {
type = tupleTypes[id] = <TupleType>createObjectType(TypeFlags.Tuple);
type = tupleTypes[id] = <TupleType>createObjectType(TypeFlags.Tuple | getWideningFlagsOfTypes(elementTypes));
type.elementTypes = elementTypes;
}
return type;
@@ -4906,9 +4906,38 @@ namespace ts {
let targetSignatures = getSignaturesOfType(target, kind);
let result = Ternary.True;
let saveErrorInfo = errorInfo;
// Because the "abstractness" of a class is the same across all construct signatures
// (internally we are checking the corresponding declaration), it is enough to perform
// the check and report an error once over all pairs of source and target construct signatures.
let sourceSig = sourceSignatures[0];
// Note that in an extends-clause, targetSignatures is stripped, so the check never proceeds.
let targetSig = targetSignatures[0];
if (sourceSig && targetSig) {
let sourceErasedSignature = getErasedSignature(sourceSig);
let targetErasedSignature = getErasedSignature(targetSig);
let sourceReturnType = sourceErasedSignature && getReturnTypeOfSignature(sourceErasedSignature);
let targetReturnType = targetErasedSignature && getReturnTypeOfSignature(targetErasedSignature);
let sourceReturnDecl = sourceReturnType && sourceReturnType.symbol && getDeclarationOfKind(sourceReturnType.symbol, SyntaxKind.ClassDeclaration);
let targetReturnDecl = targetReturnType && targetReturnType.symbol && getDeclarationOfKind(targetReturnType.symbol, SyntaxKind.ClassDeclaration);
let sourceIsAbstract = sourceReturnDecl && sourceReturnDecl.flags & NodeFlags.Abstract;
let targetIsAbstract = targetReturnDecl && targetReturnDecl.flags & NodeFlags.Abstract;
if (sourceIsAbstract && !targetIsAbstract) {
if (reportErrors) {
reportError(Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type);
}
return Ternary.False;
}
}
outer: for (let t of targetSignatures) {
if (!t.hasStringLiterals || target.flags & TypeFlags.FromSignature) {
let localErrors = reportErrors;
let checkedAbstractAssignability = false;
for (let s of sourceSignatures) {
if (!s.hasStringLiterals || source.flags & TypeFlags.FromSignature) {
let related = signatureRelatedTo(s, t, localErrors);
@@ -5015,10 +5044,11 @@ namespace ts {
return Ternary.False;
}
let t = getReturnTypeOfSignature(target);
if (t === voidType) return result;
let s = getReturnTypeOfSignature(source);
return result & isRelatedTo(s, t, reportErrors);
let targetReturnType = getReturnTypeOfSignature(target);
if (targetReturnType === voidType) return result;
let sourceReturnType = getReturnTypeOfSignature(source);
return result & isRelatedTo(sourceReturnType, targetReturnType, reportErrors);
}
function signaturesIdenticalTo(source: Type, target: Type, kind: SignatureKind): Ternary {
@@ -5272,8 +5302,8 @@ namespace ts {
* Check if a Type was written as a tuple type literal.
* Prefer using isTupleLikeType() unless the use of `elementTypes` is required.
*/
function isTupleType(type: Type): boolean {
return (type.flags & TypeFlags.Tuple) && !!(<TupleType>type).elementTypes;
function isTupleType(type: Type): type is TupleType {
return !!(type.flags & TypeFlags.Tuple);
}
function getWidenedTypeOfObjectLiteral(type: Type): Type {
@@ -5314,26 +5344,45 @@ namespace ts {
if (isArrayType(type)) {
return createArrayType(getWidenedType((<TypeReference>type).typeArguments[0]));
}
if (isTupleType(type)) {
return createTupleType(map(type.elementTypes, getWidenedType));
}
}
return type;
}
/**
* Reports implicit any errors that occur as a result of widening 'null' and 'undefined'
* to 'any'. A call to reportWideningErrorsInType is normally accompanied by a call to
* getWidenedType. But in some cases getWidenedType is called without reporting errors
* (type argument inference is an example).
*
* The return value indicates whether an error was in fact reported. The particular circumstances
* are on a best effort basis. Currently, if the null or undefined that causes widening is inside
* an object literal property (arbitrarily deeply), this function reports an error. If no error is
* reported, reportImplicitAnyError is a suitable fallback to report a general error.
*/
function reportWideningErrorsInType(type: Type): boolean {
let errorReported = false;
if (type.flags & TypeFlags.Union) {
let errorReported = false;
forEach((<UnionType>type).types, t => {
for (let t of (<UnionType>type).types) {
if (reportWideningErrorsInType(t)) {
errorReported = true;
}
});
return errorReported;
}
}
if (isArrayType(type)) {
return reportWideningErrorsInType((<TypeReference>type).typeArguments[0]);
}
if (isTupleType(type)) {
for (let t of type.elementTypes) {
if (reportWideningErrorsInType(t)) {
errorReported = true;
}
}
}
if (type.flags & TypeFlags.ObjectLiteral) {
let errorReported = false;
forEach(getPropertiesOfObjectType(type), p => {
for (let p of getPropertiesOfObjectType(type)) {
let t = getTypeOfSymbol(p);
if (t.flags & TypeFlags.ContainsUndefinedOrNull) {
if (!reportWideningErrorsInType(t)) {
@@ -5341,10 +5390,9 @@ namespace ts {
}
errorReported = true;
}
});
return errorReported;
}
}
return false;
return errorReported;
}
function reportImplicitAnyError(declaration: Declaration, type: Type) {
@@ -5513,30 +5561,33 @@ namespace ts {
inferFromTypes(sourceType, target);
}
}
else if (source.flags & TypeFlags.ObjectType && (target.flags & (TypeFlags.Reference | TypeFlags.Tuple) ||
(target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
// If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members
if (isInProcess(source, target)) {
return;
}
if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) {
return;
}
else {
source = getApparentType(source);
if (source.flags & TypeFlags.ObjectType && (target.flags & (TypeFlags.Reference | TypeFlags.Tuple) ||
(target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
// If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members
if (isInProcess(source, target)) {
return;
}
if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) {
return;
}
if (depth === 0) {
sourceStack = [];
targetStack = [];
if (depth === 0) {
sourceStack = [];
targetStack = [];
}
sourceStack[depth] = source;
targetStack[depth] = target;
depth++;
inferFromProperties(source, target);
inferFromSignatures(source, target, SignatureKind.Call);
inferFromSignatures(source, target, SignatureKind.Construct);
inferFromIndexTypes(source, target, IndexKind.String, IndexKind.String);
inferFromIndexTypes(source, target, IndexKind.Number, IndexKind.Number);
inferFromIndexTypes(source, target, IndexKind.String, IndexKind.Number);
depth--;
}
sourceStack[depth] = source;
targetStack[depth] = target;
depth++;
inferFromProperties(source, target);
inferFromSignatures(source, target, SignatureKind.Call);
inferFromSignatures(source, target, SignatureKind.Construct);
inferFromIndexTypes(source, target, IndexKind.String, IndexKind.String);
inferFromIndexTypes(source, target, IndexKind.Number, IndexKind.Number);
inferFromIndexTypes(source, target, IndexKind.String, IndexKind.Number);
depth--;
}
}
@@ -6949,7 +7000,6 @@ namespace ts {
}
}
function checkJsxSelfClosingElement(node: JsxSelfClosingElement) {
checkJsxOpeningLikeElement(node);
return jsxElementType || anyType;
@@ -407,7 +407,7 @@ namespace ts {
Classes_containing_abstract_methods_must_be_marked_abstract: { code: 2514, category: DiagnosticCategory.Error, key: "Classes containing abstract methods must be marked abstract." },
Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2: { code: 2515, category: DiagnosticCategory.Error, key: "Non-abstract class '{0}' does not implement inherited abstract member '{1}' from class '{2}'." },
All_declarations_of_an_abstract_method_must_be_consecutive: { code: 2516, category: DiagnosticCategory.Error, key: "All declarations of an abstract method must be consecutive." },
Constructor_objects_of_abstract_type_cannot_be_assigned_to_constructor_objects_of_non_abstract_type: { code: 2517, category: DiagnosticCategory.Error, key: "Constructor objects of abstract type cannot be assigned to constructor objects of non-abstract type" },
Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type: { code: 2517, category: DiagnosticCategory.Error, key: "Cannot assign an abstract constructor type to a non-abstract constructor type." },
Only_an_ambient_class_can_be_merged_with_an_interface: { code: 2518, category: DiagnosticCategory.Error, key: "Only an ambient class can be merged with an interface." },
Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions: { code: 2520, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions." },
Expression_resolves_to_variable_declaration_0_that_compiler_uses_to_support_async_functions: { code: 2521, category: DiagnosticCategory.Error, key: "Expression resolves to variable declaration '{0}' that compiler uses to support async functions." },
+1 -1
View File
@@ -1617,7 +1617,7 @@
"category": "Error",
"code": 2516
},
"Constructor objects of abstract type cannot be assigned to constructor objects of non-abstract type": {
"Cannot assign an abstract constructor type to a non-abstract constructor type.": {
"category": "Error",
"code":2517
},
+13 -3
View File
@@ -29,6 +29,9 @@ namespace ts {
declare var process: any;
declare var global: any;
declare var __filename: string;
declare var Buffer: {
new (str: string, encoding ?: string): any;
}
declare class Enumerator {
public atEnd(): boolean;
@@ -267,10 +270,17 @@ namespace ts {
args: process.argv.slice(2),
newLine: _os.EOL,
useCaseSensitiveFileNames: useCaseSensitiveFileNames,
write(s: string): void {
write(s: string): void {
var buffer = new Buffer(s, 'utf8');
var offset: number = 0;
var toWrite: number = buffer.length;
var written = 0;
// 1 is a standard descriptor for stdout
_fs.writeSync(1, s);
},
while ((written = _fs.writeSync(1, buffer, offset, toWrite)) < toWrite) {
offset += written;
toWrite -= written;
}
},
readFile,
writeFile,
watchFile: (fileName, callback) => {
+30 -26
View File
@@ -10,6 +10,7 @@ const enum CompilerTestType {
class CompilerBaselineRunner extends RunnerBase {
private basePath = 'tests/cases';
private testSuiteName: string;
private errors: boolean;
private emit: boolean;
private decl: boolean;
@@ -24,16 +25,17 @@ class CompilerBaselineRunner extends RunnerBase {
this.decl = true;
this.output = true;
if (testType === CompilerTestType.Conformance) {
this.basePath += '/conformance';
this.testSuiteName = 'conformance';
}
else if (testType === CompilerTestType.Regressions) {
this.basePath += '/compiler';
this.testSuiteName = 'compiler';
}
else if (testType === CompilerTestType.Test262) {
this.basePath += '/test262';
this.testSuiteName = 'test262';
} else {
this.basePath += '/compiler'; // default to this for historical reasons
this.testSuiteName = 'compiler'; // default to this for historical reasons
}
this.basePath += '/' + this.testSuiteName;
}
public checkTestCodeOutput(fileName: string) {
@@ -100,7 +102,7 @@ class CompilerBaselineRunner extends RunnerBase {
});
beforeEach(() => {
/* The compiler doesn't handle certain flags flipping during a single compilation setting. Tests on these flags will need
/* The compiler doesn't handle certain flags flipping during a single compilation setting. Tests on these flags will need
a fresh compiler instance for themselves and then create a fresh one for the next test. Would be nice to get dev fixes
eventually to remove this limitation. */
for (var i = 0; i < tcSettings.length; ++i) {
@@ -261,19 +263,19 @@ class CompilerBaselineRunner extends RunnerBase {
// NEWTODO: Type baselines
if (result.errors.length === 0) {
// The full walker simulates the types that you would get from doing a full
// The full walker simulates the types that you would get from doing a full
// compile. The pull walker simulates the types you get when you just do
// a type query for a random node (like how the LS would do it). Most of the
// time, these will be the same. However, occasionally, they can be different.
// Specifically, when the compiler internally depends on symbol IDs to order
// things, then we may see different results because symbols can be created in a
// things, then we may see different results because symbols can be created in a
// different order with 'pull' operations, and thus can produce slightly differing
// output.
//
// For example, with a full type check, we may see a type outputed as: number | string
// But with a pull type check, we may see it as: string | number
//
// These types are equivalent, but depend on what order the compiler observed
// These types are equivalent, but depend on what order the compiler observed
// certain parts of the program.
let allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName));
@@ -384,25 +386,27 @@ class CompilerBaselineRunner extends RunnerBase {
}
public initializeTests() {
describe("Setup compiler for compiler baselines", () => {
var harnessCompiler = Harness.Compiler.getCompiler();
this.parseOptions();
});
// this will set up a series of describe/it blocks to run between the setup and cleanup phases
if (this.tests.length === 0) {
var testFiles = this.enumerateFiles(this.basePath, /\.tsx?$/, { recursive: true });
testFiles.forEach(fn => {
fn = fn.replace(/\\/g, "/");
this.checkTestCodeOutput(fn);
describe(this.testSuiteName + ' tests', () => {
describe("Setup compiler for compiler baselines", () => {
var harnessCompiler = Harness.Compiler.getCompiler();
this.parseOptions();
});
}
else {
this.tests.forEach(test => this.checkTestCodeOutput(test));
}
describe("Cleanup after compiler baselines", () => {
var harnessCompiler = Harness.Compiler.getCompiler();
// this will set up a series of describe/it blocks to run between the setup and cleanup phases
if (this.tests.length === 0) {
var testFiles = this.enumerateFiles(this.basePath, /\.tsx?$/, { recursive: true });
testFiles.forEach(fn => {
fn = fn.replace(/\\/g, "/");
this.checkTestCodeOutput(fn);
});
}
else {
this.tests.forEach(test => this.checkTestCodeOutput(test));
}
describe("Cleanup after compiler baselines", () => {
var harnessCompiler = Harness.Compiler.getCompiler();
});
});
}
@@ -434,4 +438,4 @@ class CompilerBaselineRunner extends RunnerBase {
}
}
}
}
}
+63 -61
View File
@@ -2,7 +2,7 @@
///<reference path='harness.ts'/>
///<reference path='runnerbase.ts' />
const enum FourSlashTestType {
const enum FourSlashTestType {
Native,
Shims,
Server
@@ -35,70 +35,72 @@ class FourSlashRunner extends RunnerBase {
this.tests = this.enumerateFiles(this.basePath, /\.ts/i, { recursive: false });
}
this.tests.forEach((fn: string) => {
describe(fn, () => {
fn = ts.normalizeSlashes(fn);
var justName = fn.replace(/^.*[\\\/]/, '');
describe(this.testSuiteName + ' tests', () => {
this.tests.forEach((fn: string) => {
describe(fn, () => {
fn = ts.normalizeSlashes(fn);
var justName = fn.replace(/^.*[\\\/]/, '');
// Convert to relative path
var testIndex = fn.indexOf('tests/');
if (testIndex >= 0) fn = fn.substr(testIndex);
// Convert to relative path
var testIndex = fn.indexOf('tests/');
if (testIndex >= 0) fn = fn.substr(testIndex);
if (justName && !justName.match(/fourslash\.ts$/i) && !justName.match(/\.d\.ts$/i)) {
it(this.testSuiteName + ' test ' + justName + ' runs correctly',() => {
FourSlash.runFourSlashTest(this.basePath, this.testType, fn);
});
}
});
});
if (justName && !justName.match(/fourslash\.ts$/i) && !justName.match(/\.d\.ts$/i)) {
it(this.testSuiteName + ' test ' + justName + ' runs correctly', () => {
FourSlash.runFourSlashTest(this.basePath, this.testType, fn);
});
describe('Generate Tao XML', () => {
var invalidReasons: any = {};
FourSlash.xmlData.forEach(xml => {
if (xml.invalidReason !== null) {
invalidReasons[xml.invalidReason] = (invalidReasons[xml.invalidReason] || 0) + 1;
}
});
var invalidReport: { reason: string; count: number }[] = [];
for (var reason in invalidReasons) {
if (invalidReasons.hasOwnProperty(reason)) {
invalidReport.push({ reason: reason, count: invalidReasons[reason] });
}
}
});
});
invalidReport.sort((lhs, rhs) => lhs.count > rhs.count ? -1 : lhs.count === rhs.count ? 0 : 1);
describe('Generate Tao XML', () => {
var invalidReasons: any = {};
FourSlash.xmlData.forEach(xml => {
if (xml.invalidReason !== null) {
invalidReasons[xml.invalidReason] = (invalidReasons[xml.invalidReason] || 0) + 1;
}
var lines: string[] = [];
lines.push('<!-- Blocked Test Report');
invalidReport.forEach((reasonAndCount) => {
lines.push(reasonAndCount.count + ' tests blocked by ' + reasonAndCount.reason);
});
lines.push('-->');
lines.push('<TaoTest xmlns="http://microsoft.com/schemas/VSLanguages/TAO">');
lines.push(' <InitTest>');
lines.push(' <StartTarget />');
lines.push(' </InitTest>');
lines.push(' <ScenarioList>');
FourSlash.xmlData.forEach(xml => {
if (xml.invalidReason !== null) {
lines.push('<!-- Skipped ' + xml.originalName + ', reason: ' + xml.invalidReason + ' -->');
} else {
lines.push(' <Scenario Name="' + xml.originalName + '">');
xml.actions.forEach(action => {
lines.push(' ' + action);
});
lines.push(' </Scenario>');
}
});
lines.push(' </ScenarioList>');
lines.push(' <CleanupScenario>');
lines.push(' <CloseAllDocuments />');
lines.push(' <CleanupCreatedFiles />');
lines.push(' </CleanupScenario>');
lines.push(' <CleanupTest>');
lines.push(' <CloseTarget />');
lines.push(' </CleanupTest>');
lines.push('</TaoTest>');
Harness.IO.writeFile('built/local/fourslash.xml', lines.join('\r\n'));
});
var invalidReport: { reason: string; count: number }[] = [];
for (var reason in invalidReasons) {
if (invalidReasons.hasOwnProperty(reason)) {
invalidReport.push({ reason: reason, count: invalidReasons[reason] });
}
}
invalidReport.sort((lhs, rhs) => lhs.count > rhs.count ? -1 : lhs.count === rhs.count ? 0 : 1);
var lines: string[] = [];
lines.push('<!-- Blocked Test Report');
invalidReport.forEach((reasonAndCount) => {
lines.push(reasonAndCount.count + ' tests blocked by ' + reasonAndCount.reason);
});
lines.push('-->');
lines.push('<TaoTest xmlns="http://microsoft.com/schemas/VSLanguages/TAO">');
lines.push(' <InitTest>');
lines.push(' <StartTarget />');
lines.push(' </InitTest>');
lines.push(' <ScenarioList>');
FourSlash.xmlData.forEach(xml => {
if (xml.invalidReason !== null) {
lines.push('<!-- Skipped ' + xml.originalName + ', reason: ' + xml.invalidReason + ' -->');
} else {
lines.push(' <Scenario Name="' + xml.originalName + '">');
xml.actions.forEach(action => {
lines.push(' ' + action);
});
lines.push(' </Scenario>');
}
});
lines.push(' </ScenarioList>');
lines.push(' <CleanupScenario>');
lines.push(' <CloseAllDocuments />');
lines.push(' <CleanupCreatedFiles />');
lines.push(' </CleanupScenario>');
lines.push(' <CleanupTest>');
lines.push(' <CloseTarget />');
lines.push(' </CleanupTest>');
lines.push('</TaoTest>');
Harness.IO.writeFile('built/local/fourslash.xml', lines.join('\r\n'));
});
}
}
@@ -108,4 +110,4 @@ class GeneratedFourslashRunner extends FourSlashRunner {
super(testType);
this.basePath += '/generated/';
}
}
}
+95 -93
View File
@@ -89,7 +89,7 @@ class ProjectRunner extends RunnerBase {
}
// When test case output goes to tests/baselines/local/projectOutput/testCaseName/moduleKind/
// We have these two separate locations because when comparing baselines the baseline verifier will delete the existing file
// We have these two separate locations because when comparing baselines the baseline verifier will delete the existing file
// so even if it was created by compiler in that location, the file will be deleted by verified before we can read it
// so lets keep these two locations separate
function getProjectOutputFolder(fileName: string, moduleKind: ts.ModuleKind) {
@@ -194,7 +194,7 @@ class ProjectRunner extends RunnerBase {
};
}
}
function batchCompilerProjectTestCase(moduleKind: ts.ModuleKind): BatchCompileProjectTestCaseResult{
var nonSubfolderDiskFiles = 0;
@@ -230,7 +230,7 @@ class ProjectRunner extends RunnerBase {
var diskRelativeName = ts.getRelativePathToDirectoryOrUrl(testCase.projectRoot, diskFileName,
getCurrentDirectory(), Harness.Compiler.getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
if (ts.isRootedDiskPath(diskRelativeName) || diskRelativeName.substr(0, 3) === "../") {
// If the generated output file resides in the parent folder or is rooted path,
// If the generated output file resides in the parent folder or is rooted path,
// we need to instead create files that can live in the project reference folder
// but make sure extension of these files matches with the fileName the compiler asked to write
diskRelativeName = "diskFile" + nonSubfolderDiskFiles++ +
@@ -330,108 +330,110 @@ class ProjectRunner extends RunnerBase {
var name = 'Compiling project for ' + testCase.scenario + ': testcase ' + testCaseFileName;
describe(name, () => {
function verifyCompilerResults(moduleKind: ts.ModuleKind) {
function getCompilerResolutionInfo() {
var resolutionInfo: ProjectRunnerTestCaseResolutionInfo = {
scenario: testCase.scenario,
projectRoot: testCase.projectRoot,
inputFiles: testCase.inputFiles,
out: testCase.out,
outDir: testCase.outDir,
sourceMap: testCase.sourceMap,
mapRoot: testCase.mapRoot,
resolveMapRoot: testCase.resolveMapRoot,
sourceRoot: testCase.sourceRoot,
resolveSourceRoot: testCase.resolveSourceRoot,
declaration: testCase.declaration,
baselineCheck: testCase.baselineCheck,
runTest: testCase.runTest,
bug: testCase.bug,
rootDir: testCase.rootDir,
resolvedInputFiles: ts.map(compilerResult.program.getSourceFiles(), inputFile => inputFile.fileName),
emittedFiles: ts.map(compilerResult.outputFiles, outputFile => outputFile.emittedFileName)
};
describe('Projects tests', () => {
describe(name, () => {
function verifyCompilerResults(moduleKind: ts.ModuleKind) {
function getCompilerResolutionInfo() {
var resolutionInfo: ProjectRunnerTestCaseResolutionInfo = {
scenario: testCase.scenario,
projectRoot: testCase.projectRoot,
inputFiles: testCase.inputFiles,
out: testCase.out,
outDir: testCase.outDir,
sourceMap: testCase.sourceMap,
mapRoot: testCase.mapRoot,
resolveMapRoot: testCase.resolveMapRoot,
sourceRoot: testCase.sourceRoot,
resolveSourceRoot: testCase.resolveSourceRoot,
declaration: testCase.declaration,
baselineCheck: testCase.baselineCheck,
runTest: testCase.runTest,
bug: testCase.bug,
rootDir: testCase.rootDir,
resolvedInputFiles: ts.map(compilerResult.program.getSourceFiles(), inputFile => inputFile.fileName),
emittedFiles: ts.map(compilerResult.outputFiles, outputFile => outputFile.emittedFileName)
};
return resolutionInfo;
}
return resolutionInfo;
}
var compilerResult: BatchCompileProjectTestCaseResult;
var compilerResult: BatchCompileProjectTestCaseResult;
it(name + ": " + moduleNameToString(moduleKind) , () => {
// Compile using node
compilerResult = batchCompilerProjectTestCase(moduleKind);
});
it('Resolution information of (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => {
Harness.Baseline.runBaseline('Resolution information of (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.json', () => {
return JSON.stringify(getCompilerResolutionInfo(), undefined, " ");
it(name + ": " + moduleNameToString(moduleKind) , () => {
// Compile using node
compilerResult = batchCompilerProjectTestCase(moduleKind);
});
});
it('Errors for (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => {
if (compilerResult.errors.length) {
Harness.Baseline.runBaseline('Errors for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.errors.txt', () => {
return getErrorsBaseline(compilerResult);
it('Resolution information of (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => {
Harness.Baseline.runBaseline('Resolution information of (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.json', () => {
return JSON.stringify(getCompilerResolutionInfo(), undefined, " ");
});
}
});
});
it('Baseline of emitted result (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => {
if (testCase.baselineCheck) {
ts.forEach(compilerResult.outputFiles, outputFile => {
Harness.Baseline.runBaseline('Baseline of emitted result (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + outputFile.fileName, () => {
try {
return ts.sys.readFile(getProjectOutputFolder(outputFile.fileName, compilerResult.moduleKind));
}
catch (e) {
return undefined;
}
});
});
}
});
it('SourceMapRecord for (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => {
if (compilerResult.sourceMapData) {
Harness.Baseline.runBaseline('SourceMapRecord for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.sourcemap.txt', () => {
return Harness.SourceMapRecoder.getSourceMapRecord(compilerResult.sourceMapData, compilerResult.program,
ts.filter(compilerResult.outputFiles, outputFile => Harness.Compiler.isJS(outputFile.emittedFileName)));
});
}
});
// Verify that all the generated .d.ts files compile
it('Errors in generated Dts files for (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => {
if (!compilerResult.errors.length && testCase.declaration) {
var dTsCompileResult = compileCompileDTsFiles(compilerResult);
if (dTsCompileResult.errors.length) {
Harness.Baseline.runBaseline('Errors in generated Dts files for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.dts.errors.txt', () => {
return getErrorsBaseline(dTsCompileResult);
it('Errors for (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => {
if (compilerResult.errors.length) {
Harness.Baseline.runBaseline('Errors for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.errors.txt', () => {
return getErrorsBaseline(compilerResult);
});
}
}
});
});
it('Baseline of emitted result (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => {
if (testCase.baselineCheck) {
ts.forEach(compilerResult.outputFiles, outputFile => {
Harness.Baseline.runBaseline('Baseline of emitted result (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + outputFile.fileName, () => {
try {
return ts.sys.readFile(getProjectOutputFolder(outputFile.fileName, compilerResult.moduleKind));
}
catch (e) {
return undefined;
}
});
});
}
});
it('SourceMapRecord for (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => {
if (compilerResult.sourceMapData) {
Harness.Baseline.runBaseline('SourceMapRecord for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.sourcemap.txt', () => {
return Harness.SourceMapRecoder.getSourceMapRecord(compilerResult.sourceMapData, compilerResult.program,
ts.filter(compilerResult.outputFiles, outputFile => Harness.Compiler.isJS(outputFile.emittedFileName)));
});
}
});
// Verify that all the generated .d.ts files compile
it('Errors in generated Dts files for (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => {
if (!compilerResult.errors.length && testCase.declaration) {
var dTsCompileResult = compileCompileDTsFiles(compilerResult);
if (dTsCompileResult.errors.length) {
Harness.Baseline.runBaseline('Errors in generated Dts files for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.dts.errors.txt', () => {
return getErrorsBaseline(dTsCompileResult);
});
}
}
});
after(() => {
compilerResult = undefined;
});
}
verifyCompilerResults(ts.ModuleKind.CommonJS);
verifyCompilerResults(ts.ModuleKind.AMD);
after(() => {
compilerResult = undefined;
// Mocha holds onto the closure environment of the describe callback even after the test is done.
// Therefore we have to clean out large objects after the test is done.
testCase = undefined;
testFileText = undefined;
testCaseJustName = undefined;
});
}
verifyCompilerResults(ts.ModuleKind.CommonJS);
verifyCompilerResults(ts.ModuleKind.AMD);
after(() => {
// Mocha holds onto the closure environment of the describe callback even after the test is done.
// Therefore we have to clean out large objects after the test is done.
testCase = undefined;
testFileText = undefined;
testCaseJustName = undefined;
});
});
}
}
}
+122 -136
View File
@@ -839,6 +839,127 @@ namespace ts.server {
exit() {
}
private handlers : Map<(request: protocol.Request) => {response?: any, responseRequired?: boolean}> = {
[CommandNames.Exit]: () => {
this.exit();
return {};
},
[CommandNames.Definition]: (request: protocol.Request) => {
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getDefinition(defArgs.line, defArgs.offset, defArgs.file)};
},
[CommandNames.TypeDefinition]: (request: protocol.Request) => {
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file)};
},
[CommandNames.References]: (request: protocol.Request) => {
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getReferences(defArgs.line, defArgs.offset, defArgs.file)};
},
[CommandNames.Rename]: (request: protocol.Request) => {
var renameArgs = <protocol.RenameRequestArgs>request.arguments;
return {response: this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings)}
},
[CommandNames.Open]: (request: protocol.Request) => {
var openArgs = <protocol.OpenRequestArgs>request.arguments;
this.openClientFile(openArgs.file);
return {}
},
[CommandNames.Quickinfo]: (request: protocol.Request) => {
var quickinfoArgs = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.offset, quickinfoArgs.file)};
},
[CommandNames.Format]: (request: protocol.Request) => {
var formatArgs = <protocol.FormatRequestArgs>request.arguments;
return {response: this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file)};
},
[CommandNames.Formatonkey]: (request: protocol.Request) => {
var formatOnKeyArgs = <protocol.FormatOnKeyRequestArgs>request.arguments;
return {response: this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file)};
},
[CommandNames.Completions]: (request: protocol.Request) => {
var completionsArgs = <protocol.CompletionsRequestArgs>request.arguments;
return {response: this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file)}
},
[CommandNames.CompletionDetails]: (request: protocol.Request) => {
var completionDetailsArgs = <protocol.CompletionDetailsRequestArgs>request.arguments;
return {response: this.getCompletionEntryDetails(completionDetailsArgs.line,completionDetailsArgs.offset,
completionDetailsArgs.entryNames,completionDetailsArgs.file)}
},
[CommandNames.SignatureHelp]: (request: protocol.Request) => {
var signatureHelpArgs = <protocol.SignatureHelpRequestArgs>request.arguments;
return {response: this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file)}
},
[CommandNames.Geterr]: (request: protocol.Request) => {
var geterrArgs = <protocol.GeterrRequestArgs>request.arguments;
return {response: this.getDiagnostics(geterrArgs.delay, geterrArgs.files), responseRequired: false};
},
[CommandNames.Change]: (request: protocol.Request) => {
var changeArgs = <protocol.ChangeRequestArgs>request.arguments;
this.change(changeArgs.line, changeArgs.offset, changeArgs.endLine, changeArgs.endOffset,
changeArgs.insertString, changeArgs.file);
return {responseRequired: false}
},
[CommandNames.Configure]: (request: protocol.Request) => {
var configureArgs = <protocol.ConfigureRequestArguments>request.arguments;
this.projectService.setHostConfiguration(configureArgs);
this.output(undefined, CommandNames.Configure, request.seq);
return {responseRequired: false}
},
[CommandNames.Reload]: (request: protocol.Request) => {
var reloadArgs = <protocol.ReloadRequestArgs>request.arguments;
this.reload(reloadArgs.file, reloadArgs.tmpfile, request.seq);
return {responseRequired: false}
},
[CommandNames.Saveto]: (request: protocol.Request) => {
var savetoArgs = <protocol.SavetoRequestArgs>request.arguments;
this.saveToTmp(savetoArgs.file, savetoArgs.tmpfile);
return {responseRequired: false}
},
[CommandNames.Close]: (request: protocol.Request) => {
var closeArgs = <protocol.FileRequestArgs>request.arguments;
this.closeClientFile(closeArgs.file);
return {responseRequired: false};
},
[CommandNames.Navto]: (request: protocol.Request) => {
var navtoArgs = <protocol.NavtoRequestArgs>request.arguments;
return {response: this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount)};
},
[CommandNames.Brace]: (request: protocol.Request) => {
var braceArguments = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file)};
},
[CommandNames.NavBar]: (request: protocol.Request) => {
var navBarArgs = <protocol.FileRequestArgs>request.arguments;
return {response: this.getNavigationBarItems(navBarArgs.file)};
},
[CommandNames.Occurrences]: (request: protocol.Request) => {
var { line, offset, file: fileName } = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getOccurrences(line, offset, fileName)};
},
[CommandNames.ProjectInfo]: (request: protocol.Request) => {
var { file, needFileNameList } = <protocol.ProjectInfoRequestArgs>request.arguments;
return {response: this.getProjectInfo(file, needFileNameList)};
},
};
addProtocolHandler(command: string, handler: (request: protocol.Request) => {response?: any, responseRequired: boolean}) {
if (this.handlers[command]) {
throw new Error(`Protocol handler already exists for command "${command}"`);
}
this.handlers[command] = handler;
}
executeCommand(request: protocol.Request) : {response?: any, responseRequired?: boolean} {
var handler = this.handlers[request.command];
if (handler) {
return handler(request);
} else {
this.projectService.log("Unrecognized JSON command: " + JSON.stringify(request));
this.output(undefined, CommandNames.Unknown, request.seq, "Unrecognized JSON command: " + request.command);
return {responseRequired: false};
}
}
onMessage(message: string) {
if (this.logger.isVerbose()) {
this.logger.info("request: " + message);
@@ -846,142 +967,7 @@ namespace ts.server {
}
try {
var request = <protocol.Request>JSON.parse(message);
var response: any;
var errorMessage: string;
var responseRequired = true;
switch (request.command) {
case CommandNames.Exit: {
this.exit();
responseRequired = false;
break;
}
case CommandNames.Definition: {
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
response = this.getDefinition(defArgs.line, defArgs.offset, defArgs.file);
break;
}
case CommandNames.TypeDefinition: {
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
response = this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file);
break;
}
case CommandNames.References: {
var refArgs = <protocol.FileLocationRequestArgs>request.arguments;
response = this.getReferences(refArgs.line, refArgs.offset, refArgs.file);
break;
}
case CommandNames.Rename: {
var renameArgs = <protocol.RenameRequestArgs>request.arguments;
response = this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings);
break;
}
case CommandNames.Open: {
var openArgs = <protocol.OpenRequestArgs>request.arguments;
this.openClientFile(openArgs.file);
responseRequired = false;
break;
}
case CommandNames.Quickinfo: {
var quickinfoArgs = <protocol.FileLocationRequestArgs>request.arguments;
response = this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.offset, quickinfoArgs.file);
break;
}
case CommandNames.Format: {
var formatArgs = <protocol.FormatRequestArgs>request.arguments;
response = this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file);
break;
}
case CommandNames.Formatonkey: {
var formatOnKeyArgs = <protocol.FormatOnKeyRequestArgs>request.arguments;
response = this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file);
break;
}
case CommandNames.Completions: {
var completionsArgs = <protocol.CompletionsRequestArgs>request.arguments;
response = this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file);
break;
}
case CommandNames.CompletionDetails: {
var completionDetailsArgs = <protocol.CompletionDetailsRequestArgs>request.arguments;
response =
this.getCompletionEntryDetails(completionDetailsArgs.line,completionDetailsArgs.offset,
completionDetailsArgs.entryNames,completionDetailsArgs.file);
break;
}
case CommandNames.SignatureHelp: {
var signatureHelpArgs = <protocol.SignatureHelpRequestArgs>request.arguments;
response = this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file);
break;
}
case CommandNames.Geterr: {
var geterrArgs = <protocol.GeterrRequestArgs>request.arguments;
response = this.getDiagnostics(geterrArgs.delay, geterrArgs.files);
responseRequired = false;
break;
}
case CommandNames.Change: {
var changeArgs = <protocol.ChangeRequestArgs>request.arguments;
this.change(changeArgs.line, changeArgs.offset, changeArgs.endLine, changeArgs.endOffset,
changeArgs.insertString, changeArgs.file);
responseRequired = false;
break;
}
case CommandNames.Configure: {
var configureArgs = <protocol.ConfigureRequestArguments>request.arguments;
this.projectService.setHostConfiguration(configureArgs);
this.output(undefined, CommandNames.Configure, request.seq);
responseRequired = false;
break;
}
case CommandNames.Reload: {
var reloadArgs = <protocol.ReloadRequestArgs>request.arguments;
this.reload(reloadArgs.file, reloadArgs.tmpfile, request.seq);
responseRequired = false;
break;
}
case CommandNames.Saveto: {
var savetoArgs = <protocol.SavetoRequestArgs>request.arguments;
this.saveToTmp(savetoArgs.file, savetoArgs.tmpfile);
responseRequired = false;
break;
}
case CommandNames.Close: {
var closeArgs = <protocol.FileRequestArgs>request.arguments;
this.closeClientFile(closeArgs.file);
responseRequired = false;
break;
}
case CommandNames.Navto: {
var navtoArgs = <protocol.NavtoRequestArgs>request.arguments;
response = this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount);
break;
}
case CommandNames.Brace: {
var braceArguments = <protocol.FileLocationRequestArgs>request.arguments;
response = this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file);
break;
}
case CommandNames.NavBar: {
var navBarArgs = <protocol.FileRequestArgs>request.arguments;
response = this.getNavigationBarItems(navBarArgs.file);
break;
}
case CommandNames.Occurrences: {
var { line, offset, file: fileName } = <protocol.FileLocationRequestArgs>request.arguments;
response = this.getOccurrences(line, offset, fileName);
break;
}
case CommandNames.ProjectInfo: {
var { file, needFileNameList } = <protocol.ProjectInfoRequestArgs>request.arguments;
response = this.getProjectInfo(file, needFileNameList);
break;
}
default: {
this.projectService.log("Unrecognized JSON command: " + message);
this.output(undefined, CommandNames.Unknown, request.seq, "Unrecognized JSON command: " + request.command);
break;
}
}
var {response, responseRequired} = this.executeCommand(request);
if (this.logger.isVerbose()) {
var elapsed = this.hrtime(start);
+19 -2
View File
@@ -4546,6 +4546,7 @@ namespace ts {
if (hasKind(node.parent, SyntaxKind.GetAccessor) || hasKind(node.parent, SyntaxKind.SetAccessor)) {
return getGetAndSetOccurrences(<AccessorDeclaration>node.parent);
}
break;
default:
if (isModifier(node.kind) && node.parent &&
(isDeclaration(node.parent) || node.parent.kind === SyntaxKind.VariableStatement)) {
@@ -4695,6 +4696,11 @@ namespace ts {
return undefined;
}
}
else if (modifier === SyntaxKind.AbstractKeyword) {
if (!(container.kind === SyntaxKind.ClassDeclaration || declaration.kind === SyntaxKind.ClassDeclaration)) {
return undefined;
}
}
else {
// unsupported modifier
return undefined;
@@ -4707,7 +4713,13 @@ namespace ts {
switch (container.kind) {
case SyntaxKind.ModuleBlock:
case SyntaxKind.SourceFile:
nodes = (<Block>container).statements;
// Container is either a class declaration or the declaration is a classDeclaration
if (modifierFlag & NodeFlags.Abstract) {
nodes = (<Node[]>(<ClassDeclaration>declaration).members).concat(declaration);
}
else {
nodes = (<Block>container).statements;
}
break;
case SyntaxKind.Constructor:
nodes = (<Node[]>(<ConstructorDeclaration>container).parameters).concat(
@@ -4727,6 +4739,9 @@ namespace ts {
nodes = nodes.concat(constructor.parameters);
}
}
else if (modifierFlag & NodeFlags.Abstract) {
nodes = nodes.concat(container);
}
break;
default:
Debug.fail("Invalid container kind.")
@@ -4754,6 +4769,8 @@ namespace ts {
return NodeFlags.Export;
case SyntaxKind.DeclareKeyword:
return NodeFlags.Ambient;
case SyntaxKind.AbstractKeyword:
return NodeFlags.Abstract;
default:
Debug.fail();
}
@@ -6574,7 +6591,7 @@ namespace ts {
}
}
return ClassificationType.text;
return ClassificationType.identifier;
}
}