From c4b0302acf7517e7955bcc7d9f2c43b9bd51af8c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 13 Mar 2015 14:49:32 -0700 Subject: [PATCH 01/23] Clean up diagnostic timers and -diagnostic output --- src/compiler/program.ts | 52 +++++++++++++++++++++++------------------ src/compiler/tsc.ts | 39 ++++++++++++------------------- 2 files changed, 44 insertions(+), 47 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 9b933cacf74..eda6833e771 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2,8 +2,10 @@ /// module ts { + /* @internal */ export var programTime = 0; /* @internal */ export var emitTime = 0; /* @internal */ export var ioReadTime = 0; + /* @internal */ export var ioWriteTime = 0; /** The version of the TypeScript compiler release */ export var version = "1.5.0.0"; @@ -35,33 +37,34 @@ module ts { } text = ""; } - return text !== undefined ? createSourceFile(fileName, text, languageVersion) : undefined; } + function directoryExists(directoryPath: string): boolean { + if (hasProperty(existingDirectories, directoryPath)) { + return true; + } + if (sys.directoryExists(directoryPath)) { + existingDirectories[directoryPath] = true; + return true; + } + return false; + } + + function ensureDirectoriesExist(directoryPath: string) { + if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) { + var parentDirectory = getDirectoryPath(directoryPath); + ensureDirectoriesExist(parentDirectory); + sys.createDirectory(directoryPath); + } + } + function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) { - function directoryExists(directoryPath: string): boolean { - if (hasProperty(existingDirectories, directoryPath)) { - return true; - } - if (sys.directoryExists(directoryPath)) { - existingDirectories[directoryPath] = true; - return true; - } - return false; - } - - function ensureDirectoriesExist(directoryPath: string) { - if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) { - var parentDirectory = getDirectoryPath(directoryPath); - ensureDirectoriesExist(parentDirectory); - sys.createDirectory(directoryPath); - } - } - try { + var start = new Date().getTime(); ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName))); sys.writeFile(fileName, data, writeByteOrderMark); + ioWriteTime += new Date().getTime() - start; } catch (e) { if (onError) { @@ -119,16 +122,19 @@ module ts { var diagnostics = createDiagnosticCollection(); var seenNoDefaultLib = options.noLib; var commonSourceDirectory: string; + var diagnosticsProducingTypeChecker: TypeChecker; + var noDiagnosticsTypeChecker: TypeChecker; + host = host || createCompilerHost(options); + var start = new Date().getTime(); forEach(rootNames, name => processRootFile(name, false)); if (!seenNoDefaultLib) { processRootFile(host.getDefaultLibFileName(options), true); } - verifyCompilerOptions(); + programTime += new Date().getTime() - start; - var diagnosticsProducingTypeChecker: TypeChecker; - var noDiagnosticsTypeChecker: TypeChecker; + verifyCompilerOptions(); program = { getSourceFile: getSourceFile, diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index e9c5e17c751..3f82d6c8cf5 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -320,22 +320,16 @@ module ts { } function compile(fileNames: string[], compilerOptions: CompilerOptions, compilerHost: CompilerHost) { - ts.ioReadTime = 0; - ts.parseTime = 0; - ts.bindTime = 0; - ts.checkTime = 0; - ts.emitTime = 0; - - var start = new Date().getTime(); + ioReadTime = 0; + ioWriteTime = 0; + programTime = 0; + bindTime = 0; + checkTime = 0; + emitTime = 0; var program = createProgram(fileNames, compilerOptions, compilerHost); - var programTime = new Date().getTime() - start; - var exitStatus = compileProgram(); - var end = new Date().getTime() - start; - var compileTime = end - programTime; - if (compilerOptions.listFiles) { forEach(program.getSourceFiles(), file => { sys.write(file.fileName + sys.newLine); @@ -356,19 +350,16 @@ module ts { } // Individual component times. - // Note: we output 'programTime' as parseTime to match the tsc 1.3 behavior. tsc 1.3 - // measured parse time along with read IO as a single counter. We preserve that - // behavior so we can accurately compare times. For actual parse times (in isolation) - // is reported below. + // Note: To match the behavior of previous versions of the compiler, the reported parse time includes + // I/O read time and processing time for triple-slash references and module imports, and the reported + // emit time includes I/O write time. We preserve this behavior so we can accurately compare times. + reportTimeStatistic("I/O read", ioReadTime); + reportTimeStatistic("I/O write", ioWriteTime); reportTimeStatistic("Parse time", programTime); - reportTimeStatistic("Bind time", ts.bindTime); - reportTimeStatistic("Check time", ts.checkTime); - reportTimeStatistic("Emit time", ts.emitTime); - - reportTimeStatistic("Parse time w/o IO", ts.parseTime); - reportTimeStatistic("IO read", ts.ioReadTime); - reportTimeStatistic("Compile time", compileTime); - reportTimeStatistic("Total time", end); + reportTimeStatistic("Bind time", bindTime); + reportTimeStatistic("Check time", checkTime); + reportTimeStatistic("Emit time", emitTime); + reportTimeStatistic("Total time", programTime + bindTime + checkTime + emitTime); } return { program, exitStatus }; From 99a6f2b194a92bc3a0753b0bc5ce01c4c4638e03 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 13 Mar 2015 14:49:54 -0700 Subject: [PATCH 02/23] Removing unused function from emitter --- src/compiler/emitter.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 8947314a6f6..a592c033c22 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -4999,14 +4999,6 @@ module ts { } } - function getFirstExportAssignment(sourceFile: SourceFile) { - return forEach(sourceFile.statements, node => { - if (node.kind === SyntaxKind.ExportAssignment) { - return node; - } - }); - } - function sortAMDModules(amdModules: {name: string; path: string}[]) { // AMD modules with declared variable names go first return amdModules.sort((moduleA, moduleB) => { From f6de919407e5134f68dd7a450f77cb2adc3db121 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Fri, 13 Mar 2015 15:35:58 -0700 Subject: [PATCH 03/23] Add assert in reportNoCommonSupertypeError --- src/compiler/checker.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0dacb20ece4..957a3e3630a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4379,6 +4379,8 @@ module ts { } } + Debug.assert(!!downfallType, "If there is no common supertype, each type should have a downfallType"); + if (score > bestSupertypeScore) { bestSupertype = types[i]; bestSupertypeDownfallType = downfallType; From df6f856ad530e553696e6ba5c0abe33e8752baa6 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Fri, 13 Mar 2015 16:41:26 -0700 Subject: [PATCH 04/23] Persist inference context object throughout the signature, and add isFixed property --- src/compiler/checker.ts | 46 +++++++++++-------- src/compiler/types.ts | 2 + .../baselines/reference/APISample_compile.js | 1 + .../reference/APISample_compile.types | 3 ++ tests/baselines/reference/APISample_linter.js | 1 + .../reference/APISample_linter.types | 3 ++ .../reference/APISample_transform.js | 1 + .../reference/APISample_transform.types | 3 ++ .../baselines/reference/APISample_watcher.js | 1 + .../reference/APISample_watcher.types | 3 ++ 10 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 957a3e3630a..44178aed74b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3505,6 +3505,7 @@ module ts { return t => { for (let i = 0; i < context.typeParameters.length; i++) { if (t === context.typeParameters[i]) { + context.inferences[i].isFixed = true; return getInferredType(context, i); } } @@ -4563,12 +4564,11 @@ module ts { function createInferenceContext(typeParameters: TypeParameter[], inferUnionTypes: boolean): InferenceContext { let inferences: TypeInferences[] = []; for (let unused of typeParameters) { - inferences.push({ primary: undefined, secondary: undefined }); + inferences.push({ primary: undefined, secondary: undefined, isFixed: false }); } return { typeParameters: typeParameters, inferUnionTypes: inferUnionTypes, - inferenceCount: 0, inferences: inferences, inferredTypes: new Array(typeParameters.length), }; @@ -4615,11 +4615,13 @@ module ts { for (let i = 0; i < typeParameters.length; i++) { if (target === typeParameters[i]) { let inferences = context.inferences[i]; - let candidates = inferiority ? - inferences.secondary || (inferences.secondary = []) : - inferences.primary || (inferences.primary = []); - if (!contains(candidates, source)) candidates.push(source); - break; + if (!inferences.isFixed) { + let candidates = inferiority ? + inferences.secondary || (inferences.secondary = []) : + inferences.primary || (inferences.primary = []); + if (!contains(candidates, source)) candidates.push(source); + } + return; } } } @@ -6336,11 +6338,15 @@ module ts { return getSignatureInstantiation(signature, getInferredTypes(context)); } - function inferTypeArguments(signature: Signature, args: Expression[], excludeArgument: boolean[]): InferenceContext { + function inferTypeArguments(signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): void { let typeParameters = signature.typeParameters; - let context = createInferenceContext(typeParameters, /*inferUnionTypes*/ false); let inferenceMapper = createInferenceMapper(context); + // Clear out all the inference results from the last time inferTypeArguments was called on this context + for (let i = 0; i < typeParameters.length; i++) { + context.inferredTypes[i] = undefined; + } + // We perform two passes over the arguments. In the first pass we infer from all arguments, but use // wildcards for all context sensitive function expressions. for (let i = 0; i < args.length; i++) { @@ -6385,8 +6391,6 @@ module ts { inferredTypes[i] = unknownType; } } - - return context; } function checkTypeArguments(signature: Signature, typeArguments: TypeNode[], typeArgumentResultTypes: Type[], reportErrors: boolean): boolean { @@ -6620,15 +6624,17 @@ module ts { return resolveErrorCall(node); function chooseOverload(candidates: Signature[], relation: Map) { - for (let current of candidates) { - if (!hasCorrectArity(node, args, current)) { + for (let originalCandidate of candidates) { + if (!hasCorrectArity(node, args, originalCandidate)) { continue; } - - let originalCandidate = current; - let inferenceResult: InferenceContext; + let candidate: Signature; let typeArgumentsAreValid: boolean; + let inferenceContext = originalCandidate.typeParameters + ? createInferenceContext(originalCandidate.typeParameters, /*inferUnionTypes*/ false) + : undefined; + while (true) { candidate = originalCandidate; if (candidate.typeParameters) { @@ -6638,9 +6644,9 @@ module ts { typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false) } else { - inferenceResult = inferTypeArguments(candidate, args, excludeArgument); - typeArgumentsAreValid = inferenceResult.failedTypeParameterIndex < 0; - typeArgumentTypes = inferenceResult.inferredTypes; + inferTypeArguments(candidate, args, excludeArgument, inferenceContext); + typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex < 0; + typeArgumentTypes = inferenceContext.inferredTypes; } if (!typeArgumentsAreValid) { break; @@ -6670,7 +6676,7 @@ module ts { else { candidateForTypeArgumentError = originalCandidate; if (!typeArguments) { - resultOfFailedInference = inferenceResult; + resultOfFailedInference = inferenceContext; } } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c43591911ab..5880dfdce92 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1485,6 +1485,8 @@ module ts { export interface TypeInferences { primary: Type[]; // Inferences made directly to a type parameter secondary: Type[]; // Inferences made to a type parameter in a union type + isFixed: boolean; // Whether the type parameter is fixed, as defined in section 4.12.2 of the TypeScript spec + // If a type parameter is fixed, no more inferences can be made for the type parameter } export interface InferenceContext { diff --git a/tests/baselines/reference/APISample_compile.js b/tests/baselines/reference/APISample_compile.js index 98571823181..d08d0b3fcc2 100644 --- a/tests/baselines/reference/APISample_compile.js +++ b/tests/baselines/reference/APISample_compile.js @@ -1175,6 +1175,7 @@ declare module "typescript" { interface TypeInferences { primary: Type[]; secondary: Type[]; + isFixed: boolean; } interface InferenceContext { typeParameters: TypeParameter[]; diff --git a/tests/baselines/reference/APISample_compile.types b/tests/baselines/reference/APISample_compile.types index 087c0389d0f..df0c57444b0 100644 --- a/tests/baselines/reference/APISample_compile.types +++ b/tests/baselines/reference/APISample_compile.types @@ -3767,6 +3767,9 @@ declare module "typescript" { secondary: Type[]; >secondary : Type[] >Type : Type + + isFixed: boolean; +>isFixed : boolean } interface InferenceContext { >InferenceContext : InferenceContext diff --git a/tests/baselines/reference/APISample_linter.js b/tests/baselines/reference/APISample_linter.js index d43d6220072..fb390d78f8f 100644 --- a/tests/baselines/reference/APISample_linter.js +++ b/tests/baselines/reference/APISample_linter.js @@ -1206,6 +1206,7 @@ declare module "typescript" { interface TypeInferences { primary: Type[]; secondary: Type[]; + isFixed: boolean; } interface InferenceContext { typeParameters: TypeParameter[]; diff --git a/tests/baselines/reference/APISample_linter.types b/tests/baselines/reference/APISample_linter.types index 14eb2936242..90360b5fe61 100644 --- a/tests/baselines/reference/APISample_linter.types +++ b/tests/baselines/reference/APISample_linter.types @@ -3913,6 +3913,9 @@ declare module "typescript" { secondary: Type[]; >secondary : Type[] >Type : Type + + isFixed: boolean; +>isFixed : boolean } interface InferenceContext { >InferenceContext : InferenceContext diff --git a/tests/baselines/reference/APISample_transform.js b/tests/baselines/reference/APISample_transform.js index bfe62135a0d..96b54ccd917 100644 --- a/tests/baselines/reference/APISample_transform.js +++ b/tests/baselines/reference/APISample_transform.js @@ -1207,6 +1207,7 @@ declare module "typescript" { interface TypeInferences { primary: Type[]; secondary: Type[]; + isFixed: boolean; } interface InferenceContext { typeParameters: TypeParameter[]; diff --git a/tests/baselines/reference/APISample_transform.types b/tests/baselines/reference/APISample_transform.types index baa497c95fa..999c81af401 100644 --- a/tests/baselines/reference/APISample_transform.types +++ b/tests/baselines/reference/APISample_transform.types @@ -3863,6 +3863,9 @@ declare module "typescript" { secondary: Type[]; >secondary : Type[] >Type : Type + + isFixed: boolean; +>isFixed : boolean } interface InferenceContext { >InferenceContext : InferenceContext diff --git a/tests/baselines/reference/APISample_watcher.js b/tests/baselines/reference/APISample_watcher.js index ee1fd062515..8a3d2065a23 100644 --- a/tests/baselines/reference/APISample_watcher.js +++ b/tests/baselines/reference/APISample_watcher.js @@ -1244,6 +1244,7 @@ declare module "typescript" { interface TypeInferences { primary: Type[]; secondary: Type[]; + isFixed: boolean; } interface InferenceContext { typeParameters: TypeParameter[]; diff --git a/tests/baselines/reference/APISample_watcher.types b/tests/baselines/reference/APISample_watcher.types index a8b534439d5..f66c818c53d 100644 --- a/tests/baselines/reference/APISample_watcher.types +++ b/tests/baselines/reference/APISample_watcher.types @@ -4036,6 +4036,9 @@ declare module "typescript" { secondary: Type[]; >secondary : Type[] >Type : Type + + isFixed: boolean; +>isFixed : boolean } interface InferenceContext { >InferenceContext : InferenceContext From 495caf0f6728e881e67b7fbe077a2c782b8e3f4d Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Fri, 13 Mar 2015 17:03:13 -0700 Subject: [PATCH 05/23] Optimize the clearing of inferredTypes --- src/compiler/checker.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 44178aed74b..0d29e928e31 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6344,7 +6344,11 @@ module ts { // Clear out all the inference results from the last time inferTypeArguments was called on this context for (let i = 0; i < typeParameters.length; i++) { - context.inferredTypes[i] = undefined; + // As an optimization, we don't have to clear (and later recompute) inferred types + // for type parameters that have already been fixed on the previous call to inferTypeArguments + if (!context.inferences[i].isFixed) { + context.inferredTypes[i] = undefined; + } } // We perform two passes over the arguments. In the first pass we infer from all arguments, but use From a0b96079c226f949256de391dac1cb03343c6d22 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Fri, 13 Mar 2015 17:43:37 -0700 Subject: [PATCH 06/23] Get rid of inferenceFailureType, just set the failedTypeParameterIndex directly --- src/compiler/checker.ts | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0d29e928e31..21707940a5a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -79,8 +79,7 @@ module ts { let emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); let anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); let noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - let inferenceFailureType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - + let anySignature = createSignature(undefined, undefined, emptyArray, anyType, 0, false, false); let unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, 0, false, false); @@ -4727,21 +4726,32 @@ module ts { function getInferredType(context: InferenceContext, index: number): Type { let inferredType = context.inferredTypes[index]; + let inferenceSucceeded: boolean; if (!inferredType) { let inferences = getInferenceCandidates(context, index); if (inferences.length) { // Infer widened union or supertype, or the undefined type for no common supertype let unionOrSuperType = context.inferUnionTypes ? getUnionType(inferences) : getCommonSupertype(inferences); - inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : inferenceFailureType; + inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType; + inferenceSucceeded = !!unionOrSuperType; } else { // Infer the empty object type when no inferences were made inferredType = emptyObjectType; + inferenceSucceeded = true; } - if (inferredType !== inferenceFailureType) { + + // Only do the constraint check if inference succeeded (to prevent cascading errors) + if (inferenceSucceeded) { let constraint = getConstraintOfTypeParameter(context.typeParameters[index]); inferredType = constraint && !isTypeAssignableTo(inferredType, constraint) ? constraint : inferredType; } + // If inference failed, it is necessary to record the index of the failed type parameter (the one we are on). + // It might be that inference has already failed on a later type parameter on a previous call to inferTypeArguments. + // So if this failure is on preceding type parameter, this type parameter is the new failure index. + else if (context.failedTypeParameterIndex === undefined || context.failedTypeParameterIndex > index) { + context.failedTypeParameterIndex = index; + } context.inferredTypes[index] = inferredType; } return inferredType; @@ -6350,6 +6360,9 @@ module ts { context.inferredTypes[i] = undefined; } } + if (context.failedTypeParameterIndex >= 0 && !context.inferences[context.failedTypeParameterIndex].isFixed) { + context.failedTypeParameterIndex = undefined; + } // We perform two passes over the arguments. In the first pass we infer from all arguments, but use // wildcards for all context sensitive function expressions. @@ -6385,16 +6398,7 @@ module ts { } } - let inferredTypes = getInferredTypes(context); - // Inference has failed if the inferenceFailureType type is in list of inferences - context.failedTypeParameterIndex = indexOf(inferredTypes, inferenceFailureType); - - // Wipe out the inferenceFailureType from the array so that error recovery can work properly - for (let i = 0; i < inferredTypes.length; i++) { - if (inferredTypes[i] === inferenceFailureType) { - inferredTypes[i] = unknownType; - } - } + getInferredTypes(context); } function checkTypeArguments(signature: Signature, typeArguments: TypeNode[], typeArgumentResultTypes: Type[], reportErrors: boolean): boolean { @@ -6649,7 +6653,7 @@ module ts { } else { inferTypeArguments(candidate, args, excludeArgument, inferenceContext); - typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex < 0; + typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined; typeArgumentTypes = inferenceContext.inferredTypes; } if (!typeArgumentsAreValid) { From a29b6fe8c759fd673f5199997af40cea5725a977 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Fri, 13 Mar 2015 18:22:30 -0700 Subject: [PATCH 07/23] Add tests for type parameter fixing --- .../typeParameterFixingWithConstraints.js | 21 ++++++ .../typeParameterFixingWithConstraints.types | 44 ++++++++++++ ...eterFixingWithContextSensitiveArguments.js | 28 ++++++++ ...rFixingWithContextSensitiveArguments.types | 71 +++++++++++++++++++ ...gWithContextSensitiveArguments2.errors.txt | 15 ++++ ...terFixingWithContextSensitiveArguments2.js | 22 ++++++ ...gWithContextSensitiveArguments3.errors.txt | 15 ++++ ...terFixingWithContextSensitiveArguments3.js | 22 ++++++ ...terFixingWithContextSensitiveArguments4.js | 22 ++++++ ...FixingWithContextSensitiveArguments4.types | 55 ++++++++++++++ ...terFixingWithContextSensitiveArguments5.js | 22 ++++++ ...FixingWithContextSensitiveArguments5.types | 56 +++++++++++++++ .../typeParameterFixingWithConstraints.ts | 10 +++ ...eterFixingWithContextSensitiveArguments.ts | 9 +++ ...terFixingWithContextSensitiveArguments2.ts | 7 ++ ...terFixingWithContextSensitiveArguments3.ts | 7 ++ ...terFixingWithContextSensitiveArguments4.ts | 7 ++ ...terFixingWithContextSensitiveArguments5.ts | 7 ++ 18 files changed, 440 insertions(+) create mode 100644 tests/baselines/reference/typeParameterFixingWithConstraints.js create mode 100644 tests/baselines/reference/typeParameterFixingWithConstraints.types create mode 100644 tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments.js create mode 100644 tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments.types create mode 100644 tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments2.errors.txt create mode 100644 tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments2.js create mode 100644 tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments3.errors.txt create mode 100644 tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments3.js create mode 100644 tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments4.js create mode 100644 tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments4.types create mode 100644 tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments5.js create mode 100644 tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments5.types create mode 100644 tests/cases/compiler/typeParameterFixingWithConstraints.ts create mode 100644 tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments.ts create mode 100644 tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments2.ts create mode 100644 tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments3.ts create mode 100644 tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments4.ts create mode 100644 tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments5.ts diff --git a/tests/baselines/reference/typeParameterFixingWithConstraints.js b/tests/baselines/reference/typeParameterFixingWithConstraints.js new file mode 100644 index 00000000000..49b2c48fbe2 --- /dev/null +++ b/tests/baselines/reference/typeParameterFixingWithConstraints.js @@ -0,0 +1,21 @@ +//// [typeParameterFixingWithConstraints.ts] +interface IBar { + [barId: string]: any; +} + +interface IFoo { + foo(bar: TBar, bar1: (bar: TBar) => TBar, bar2: (bar: TBar) => TBar): TBar; +} + +var foo: IFoo; +foo.foo({ bar: null }, bar => null, bar => null); + +//// [typeParameterFixingWithConstraints.js] +var foo; +foo.foo({ + bar: null +}, function (bar) { + return null; +}, function (bar) { + return null; +}); diff --git a/tests/baselines/reference/typeParameterFixingWithConstraints.types b/tests/baselines/reference/typeParameterFixingWithConstraints.types new file mode 100644 index 00000000000..c15f22fc974 --- /dev/null +++ b/tests/baselines/reference/typeParameterFixingWithConstraints.types @@ -0,0 +1,44 @@ +=== tests/cases/compiler/typeParameterFixingWithConstraints.ts === +interface IBar { +>IBar : IBar + + [barId: string]: any; +>barId : string +} + +interface IFoo { +>IFoo : IFoo + + foo(bar: TBar, bar1: (bar: TBar) => TBar, bar2: (bar: TBar) => TBar): TBar; +>foo : (bar: TBar, bar1: (bar: TBar) => TBar, bar2: (bar: TBar) => TBar) => TBar +>TBar : TBar +>IBar : IBar +>bar : TBar +>TBar : TBar +>bar1 : (bar: TBar) => TBar +>bar : TBar +>TBar : TBar +>TBar : TBar +>bar2 : (bar: TBar) => TBar +>bar : TBar +>TBar : TBar +>TBar : TBar +>TBar : TBar +} + +var foo: IFoo; +>foo : IFoo +>IFoo : IFoo + +foo.foo({ bar: null }, bar => null, bar => null); +>foo.foo({ bar: null }, bar => null, bar => null) : IBar +>foo.foo : (bar: TBar, bar1: (bar: TBar) => TBar, bar2: (bar: TBar) => TBar) => TBar +>foo : IFoo +>foo : (bar: TBar, bar1: (bar: TBar) => TBar, bar2: (bar: TBar) => TBar) => TBar +>{ bar: null } : { [x: string]: null; bar: null; } +>bar : null +>bar => null : (bar: IBar) => any +>bar : IBar +>bar => null : (bar: IBar) => any +>bar : IBar + diff --git a/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments.js b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments.js new file mode 100644 index 00000000000..170bd711b61 --- /dev/null +++ b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments.js @@ -0,0 +1,28 @@ +//// [typeParameterFixingWithContextSensitiveArguments.ts] +function f(y: T, f: (x: T) => U, x: T): [T, U] { return [y, f(x)]; } +interface A { a: A; } +interface B extends A { b; } + +var a: A, b: B; + +var d = f(b, x => x.a, a); // type [A, A] +var d2 = f(b, x => x.a, null); // type [B, A] +var d3 = f(b, x => x.b, null); // type [B, any] + +//// [typeParameterFixingWithContextSensitiveArguments.js] +function f(y, f, x) { + return [ + y, + f(x) + ]; +} +var a, b; +var d = f(b, function (x) { + return x.a; +}, a); // type [A, A] +var d2 = f(b, function (x) { + return x.a; +}, null); // type [B, A] +var d3 = f(b, function (x) { + return x.b; +}, null); // type [B, any] diff --git a/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments.types b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments.types new file mode 100644 index 00000000000..d6bd1b3b271 --- /dev/null +++ b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments.types @@ -0,0 +1,71 @@ +=== tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments.ts === +function f(y: T, f: (x: T) => U, x: T): [T, U] { return [y, f(x)]; } +>f : (y: T, f: (x: T) => U, x: T) => [T, U] +>T : T +>U : U +>y : T +>T : T +>f : (x: T) => U +>x : T +>T : T +>U : U +>x : T +>T : T +>T : T +>U : U +>[y, f(x)] : [T, U] +>y : T +>f(x) : U +>f : (x: T) => U +>x : T + +interface A { a: A; } +>A : A +>a : A +>A : A + +interface B extends A { b; } +>B : B +>A : A +>b : any + +var a: A, b: B; +>a : A +>A : A +>b : B +>B : B + +var d = f(b, x => x.a, a); // type [A, A] +>d : [A, A] +>f(b, x => x.a, a) : [A, A] +>f : (y: T, f: (x: T) => U, x: T) => [T, U] +>b : B +>x => x.a : (x: A) => A +>x : A +>x.a : A +>x : A +>a : A +>a : A + +var d2 = f(b, x => x.a, null); // type [B, A] +>d2 : [B, A] +>f(b, x => x.a, null) : [B, A] +>f : (y: T, f: (x: T) => U, x: T) => [T, U] +>b : B +>x => x.a : (x: B) => A +>x : B +>x.a : A +>x : B +>a : A + +var d3 = f(b, x => x.b, null); // type [B, any] +>d3 : [B, any] +>f(b, x => x.b, null) : [B, any] +>f : (y: T, f: (x: T) => U, x: T) => [T, U] +>b : B +>x => x.b : (x: B) => any +>x : B +>x.b : any +>x : B +>b : any + diff --git a/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments2.errors.txt b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments2.errors.txt new file mode 100644 index 00000000000..6a7975b4b62 --- /dev/null +++ b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments2.errors.txt @@ -0,0 +1,15 @@ +tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments2.ts(7,25): error TS2345: Argument of type '(x: A) => A' is not assignable to parameter of type '(x: A) => B'. + Type 'A' is not assignable to type 'B'. + + +==== tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments2.ts (1 errors) ==== + function f(y: T, y1: U, p: (z: U) => T, p1: (x: T) => U): [T, U] { return [y, p1(y)]; } + interface A { a: A; } + interface B extends A { b; } + + var a: A, b: B; + + var d = f(a, b, x => x, x => x); // A => A not assignable to A => B + ~~~~~~ +!!! error TS2345: Argument of type '(x: A) => A' is not assignable to parameter of type '(x: A) => B'. +!!! error TS2345: Type 'A' is not assignable to type 'B'. \ No newline at end of file diff --git a/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments2.js b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments2.js new file mode 100644 index 00000000000..1b97f04953e --- /dev/null +++ b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments2.js @@ -0,0 +1,22 @@ +//// [typeParameterFixingWithContextSensitiveArguments2.ts] +function f(y: T, y1: U, p: (z: U) => T, p1: (x: T) => U): [T, U] { return [y, p1(y)]; } +interface A { a: A; } +interface B extends A { b; } + +var a: A, b: B; + +var d = f(a, b, x => x, x => x); // A => A not assignable to A => B + +//// [typeParameterFixingWithContextSensitiveArguments2.js] +function f(y, y1, p, p1) { + return [ + y, + p1(y) + ]; +} +var a, b; +var d = f(a, b, function (x) { + return x; +}, function (x) { + return x; +}); // A => A not assignable to A => B diff --git a/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments3.errors.txt b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments3.errors.txt new file mode 100644 index 00000000000..89be3c06c64 --- /dev/null +++ b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments3.errors.txt @@ -0,0 +1,15 @@ +tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments3.ts(7,29): error TS2345: Argument of type '(t2: A) => A' is not assignable to parameter of type '(t2: A) => B'. + Type 'A' is not assignable to type 'B'. + + +==== tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments3.ts (1 errors) ==== + function f(t1: T, u1: U, pf1: (u2: U) => T, pf2: (t2: T) => U): [T, U] { return [t1, pf2(t1)]; } + interface A { a: A; } + interface B extends A { b: B; } + + var a: A, b: B; + + var d = f(a, b, u2 => u2.b, t2 => t2); + ~~~~~~~~ +!!! error TS2345: Argument of type '(t2: A) => A' is not assignable to parameter of type '(t2: A) => B'. +!!! error TS2345: Type 'A' is not assignable to type 'B'. \ No newline at end of file diff --git a/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments3.js b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments3.js new file mode 100644 index 00000000000..4b5370cfc1c --- /dev/null +++ b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments3.js @@ -0,0 +1,22 @@ +//// [typeParameterFixingWithContextSensitiveArguments3.ts] +function f(t1: T, u1: U, pf1: (u2: U) => T, pf2: (t2: T) => U): [T, U] { return [t1, pf2(t1)]; } +interface A { a: A; } +interface B extends A { b: B; } + +var a: A, b: B; + +var d = f(a, b, u2 => u2.b, t2 => t2); + +//// [typeParameterFixingWithContextSensitiveArguments3.js] +function f(t1, u1, pf1, pf2) { + return [ + t1, + pf2(t1) + ]; +} +var a, b; +var d = f(a, b, function (u2) { + return u2.b; +}, function (t2) { + return t2; +}); diff --git a/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments4.js b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments4.js new file mode 100644 index 00000000000..7efab1f62c5 --- /dev/null +++ b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments4.js @@ -0,0 +1,22 @@ +//// [typeParameterFixingWithContextSensitiveArguments4.ts] +function f(y: T, y1: U, p: (z: U) => T, p1: (x: T) => U): [T, U] { return [y, p1(y)]; } +interface A { a: A; } +interface B extends A { b; } + +var a: A, b: B; + +var d = f(a, b, x => x, x => x); // Type [A, B] + +//// [typeParameterFixingWithContextSensitiveArguments4.js] +function f(y, y1, p, p1) { + return [ + y, + p1(y) + ]; +} +var a, b; +var d = f(a, b, function (x) { + return x; +}, function (x) { + return x; +}); // Type [A, B] diff --git a/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments4.types b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments4.types new file mode 100644 index 00000000000..61158ae9738 --- /dev/null +++ b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments4.types @@ -0,0 +1,55 @@ +=== tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments4.ts === +function f(y: T, y1: U, p: (z: U) => T, p1: (x: T) => U): [T, U] { return [y, p1(y)]; } +>f : (y: T, y1: U, p: (z: U) => T, p1: (x: T) => U) => [T, U] +>T : T +>U : U +>y : T +>T : T +>y1 : U +>U : U +>p : (z: U) => T +>z : U +>U : U +>T : T +>p1 : (x: T) => U +>x : T +>T : T +>U : U +>T : T +>U : U +>[y, p1(y)] : [T, U] +>y : T +>p1(y) : U +>p1 : (x: T) => U +>y : T + +interface A { a: A; } +>A : A +>a : A +>A : A + +interface B extends A { b; } +>B : B +>A : A +>b : any + +var a: A, b: B; +>a : A +>A : A +>b : B +>B : B + +var d = f(a, b, x => x, x => x); // Type [A, B] +>d : [A, B] +>f(a, b, x => x, x => x) : [A, B] +>f : (y: T, y1: U, p: (z: U) => T, p1: (x: T) => U) => [T, U] +>a : A +>b : B +>x => x : (x: B) => B +>x : B +>x : B +>x => x : (x: A) => any +>x : A +>x : any +>x : A + diff --git a/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments5.js b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments5.js new file mode 100644 index 00000000000..7ab2502e02c --- /dev/null +++ b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments5.js @@ -0,0 +1,22 @@ +//// [typeParameterFixingWithContextSensitiveArguments5.ts] +function f(t1: T, u1: U, pf1: (u2: U) => T, pf2: (t2: T) => U): [T, U] { return [t1, pf2(t1)]; } +interface A { a: A; } +interface B extends A { b: any; } + +var a: A, b: B; + +var d = f(a, b, u2 => u2.b, t2 => t2); + +//// [typeParameterFixingWithContextSensitiveArguments5.js] +function f(t1, u1, pf1, pf2) { + return [ + t1, + pf2(t1) + ]; +} +var a, b; +var d = f(a, b, function (u2) { + return u2.b; +}, function (t2) { + return t2; +}); diff --git a/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments5.types b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments5.types new file mode 100644 index 00000000000..3eb7d07bc3c --- /dev/null +++ b/tests/baselines/reference/typeParameterFixingWithContextSensitiveArguments5.types @@ -0,0 +1,56 @@ +=== tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments5.ts === +function f(t1: T, u1: U, pf1: (u2: U) => T, pf2: (t2: T) => U): [T, U] { return [t1, pf2(t1)]; } +>f : (t1: T, u1: U, pf1: (u2: U) => T, pf2: (t2: T) => U) => [T, U] +>T : T +>U : U +>t1 : T +>T : T +>u1 : U +>U : U +>pf1 : (u2: U) => T +>u2 : U +>U : U +>T : T +>pf2 : (t2: T) => U +>t2 : T +>T : T +>U : U +>T : T +>U : U +>[t1, pf2(t1)] : [T, U] +>t1 : T +>pf2(t1) : U +>pf2 : (t2: T) => U +>t1 : T + +interface A { a: A; } +>A : A +>a : A +>A : A + +interface B extends A { b: any; } +>B : B +>A : A +>b : any + +var a: A, b: B; +>a : A +>A : A +>b : B +>B : B + +var d = f(a, b, u2 => u2.b, t2 => t2); +>d : [any, B] +>f(a, b, u2 => u2.b, t2 => t2) : [any, B] +>f : (t1: T, u1: U, pf1: (u2: U) => T, pf2: (t2: T) => U) => [T, U] +>a : A +>b : B +>u2 => u2.b : (u2: B) => any +>u2 : B +>u2.b : any +>u2 : B +>b : any +>t2 => t2 : (t2: any) => any +>t2 : any +>t2 : any + diff --git a/tests/cases/compiler/typeParameterFixingWithConstraints.ts b/tests/cases/compiler/typeParameterFixingWithConstraints.ts new file mode 100644 index 00000000000..3d8536ab4cf --- /dev/null +++ b/tests/cases/compiler/typeParameterFixingWithConstraints.ts @@ -0,0 +1,10 @@ +interface IBar { + [barId: string]: any; +} + +interface IFoo { + foo(bar: TBar, bar1: (bar: TBar) => TBar, bar2: (bar: TBar) => TBar): TBar; +} + +var foo: IFoo; +foo.foo({ bar: null }, bar => null, bar => null); \ No newline at end of file diff --git a/tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments.ts b/tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments.ts new file mode 100644 index 00000000000..c05b26fd2fc --- /dev/null +++ b/tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments.ts @@ -0,0 +1,9 @@ +function f(y: T, f: (x: T) => U, x: T): [T, U] { return [y, f(x)]; } +interface A { a: A; } +interface B extends A { b; } + +var a: A, b: B; + +var d = f(b, x => x.a, a); // type [A, A] +var d2 = f(b, x => x.a, null); // type [B, A] +var d3 = f(b, x => x.b, null); // type [B, any] \ No newline at end of file diff --git a/tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments2.ts b/tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments2.ts new file mode 100644 index 00000000000..f4f001c9f27 --- /dev/null +++ b/tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments2.ts @@ -0,0 +1,7 @@ +function f(y: T, y1: U, p: (z: U) => T, p1: (x: T) => U): [T, U] { return [y, p1(y)]; } +interface A { a: A; } +interface B extends A { b; } + +var a: A, b: B; + +var d = f(a, b, x => x, x => x); // A => A not assignable to A => B \ No newline at end of file diff --git a/tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments3.ts b/tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments3.ts new file mode 100644 index 00000000000..1bf4169624d --- /dev/null +++ b/tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments3.ts @@ -0,0 +1,7 @@ +function f(t1: T, u1: U, pf1: (u2: U) => T, pf2: (t2: T) => U): [T, U] { return [t1, pf2(t1)]; } +interface A { a: A; } +interface B extends A { b: B; } + +var a: A, b: B; + +var d = f(a, b, u2 => u2.b, t2 => t2); \ No newline at end of file diff --git a/tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments4.ts b/tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments4.ts new file mode 100644 index 00000000000..8fa501906b8 --- /dev/null +++ b/tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments4.ts @@ -0,0 +1,7 @@ +function f(y: T, y1: U, p: (z: U) => T, p1: (x: T) => U): [T, U] { return [y, p1(y)]; } +interface A { a: A; } +interface B extends A { b; } + +var a: A, b: B; + +var d = f(a, b, x => x, x => x); // Type [A, B] \ No newline at end of file diff --git a/tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments5.ts b/tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments5.ts new file mode 100644 index 00000000000..a74eb042692 --- /dev/null +++ b/tests/cases/compiler/typeParameterFixingWithContextSensitiveArguments5.ts @@ -0,0 +1,7 @@ +function f(t1: T, u1: U, pf1: (u2: U) => T, pf2: (t2: T) => U): [T, U] { return [t1, pf2(t1)]; } +interface A { a: A; } +interface B extends A { b: any; } + +var a: A, b: B; + +var d = f(a, b, u2 => u2.b, t2 => t2); \ No newline at end of file From 9933f6cd00f456442551a5ef9aeb6d48783e00f8 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Mon, 16 Mar 2015 11:04:11 -0700 Subject: [PATCH 08/23] Address PR feedback --- src/compiler/checker.ts | 13 ++++--- src/compiler/types.ts | 2 ++ .../baselines/reference/APISample_compile.js | 12 ------- .../reference/APISample_compile.types | 35 ------------------- tests/baselines/reference/APISample_linter.js | 12 ------- .../reference/APISample_linter.types | 35 ------------------- .../reference/APISample_transform.js | 12 ------- .../reference/APISample_transform.types | 35 ------------------- .../baselines/reference/APISample_watcher.js | 12 ------- .../reference/APISample_watcher.types | 35 ------------------- 10 files changed, 10 insertions(+), 193 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 21707940a5a..bb866c6b8cb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4730,13 +4730,16 @@ module ts { if (!inferredType) { let inferences = getInferenceCandidates(context, index); if (inferences.length) { - // Infer widened union or supertype, or the undefined type for no common supertype + // Infer widened union or supertype, or the unknown type for no common supertype let unionOrSuperType = context.inferUnionTypes ? getUnionType(inferences) : getCommonSupertype(inferences); inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType; inferenceSucceeded = !!unionOrSuperType; } else { - // Infer the empty object type when no inferences were made + // Infer the empty object type when no inferences were made. It is important to remember that + // in this case, inference still succeeds, meaning there is no error for not having inference + // candidates. An inference error only occurs when there are *conflicting* candidates, i.e. + // candidates with no common supertype. inferredType = emptyObjectType; inferenceSucceeded = true; } @@ -4746,10 +4749,10 @@ module ts { let constraint = getConstraintOfTypeParameter(context.typeParameters[index]); inferredType = constraint && !isTypeAssignableTo(inferredType, constraint) ? constraint : inferredType; } - // If inference failed, it is necessary to record the index of the failed type parameter (the one we are on). - // It might be that inference has already failed on a later type parameter on a previous call to inferTypeArguments. - // So if this failure is on preceding type parameter, this type parameter is the new failure index. else if (context.failedTypeParameterIndex === undefined || context.failedTypeParameterIndex > index) { + // If inference failed, it is necessary to record the index of the failed type parameter (the one we are on). + // It might be that inference has already failed on a later type parameter on a previous call to inferTypeArguments. + // So if this failure is on preceding type parameter, this type parameter is the new failure index. context.failedTypeParameterIndex = index; } context.inferredTypes[index] = inferredType; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5880dfdce92..403c96b239b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1482,6 +1482,7 @@ module ts { (t: Type): Type; } + // @internal export interface TypeInferences { primary: Type[]; // Inferences made directly to a type parameter secondary: Type[]; // Inferences made to a type parameter in a union type @@ -1489,6 +1490,7 @@ module ts { // If a type parameter is fixed, no more inferences can be made for the type parameter } + // @internal export interface InferenceContext { typeParameters: TypeParameter[]; // Type parameters for which inferences are made inferUnionTypes: boolean; // Infer union types for disjoint candidates (otherwise undefinedType) diff --git a/tests/baselines/reference/APISample_compile.js b/tests/baselines/reference/APISample_compile.js index d08d0b3fcc2..e2c0341d5dd 100644 --- a/tests/baselines/reference/APISample_compile.js +++ b/tests/baselines/reference/APISample_compile.js @@ -1172,18 +1172,6 @@ declare module "typescript" { interface TypeMapper { (t: Type): Type; } - interface TypeInferences { - primary: Type[]; - secondary: Type[]; - isFixed: boolean; - } - interface InferenceContext { - typeParameters: TypeParameter[]; - inferUnionTypes: boolean; - inferences: TypeInferences[]; - inferredTypes: Type[]; - failedTypeParameterIndex?: number; - } interface DiagnosticMessage { key: string; category: DiagnosticCategory; diff --git a/tests/baselines/reference/APISample_compile.types b/tests/baselines/reference/APISample_compile.types index df0c57444b0..12803044f6e 100644 --- a/tests/baselines/reference/APISample_compile.types +++ b/tests/baselines/reference/APISample_compile.types @@ -3756,41 +3756,6 @@ declare module "typescript" { >t : Type >Type : Type >Type : Type - } - interface TypeInferences { ->TypeInferences : TypeInferences - - primary: Type[]; ->primary : Type[] ->Type : Type - - secondary: Type[]; ->secondary : Type[] ->Type : Type - - isFixed: boolean; ->isFixed : boolean - } - interface InferenceContext { ->InferenceContext : InferenceContext - - typeParameters: TypeParameter[]; ->typeParameters : TypeParameter[] ->TypeParameter : TypeParameter - - inferUnionTypes: boolean; ->inferUnionTypes : boolean - - inferences: TypeInferences[]; ->inferences : TypeInferences[] ->TypeInferences : TypeInferences - - inferredTypes: Type[]; ->inferredTypes : Type[] ->Type : Type - - failedTypeParameterIndex?: number; ->failedTypeParameterIndex : number } interface DiagnosticMessage { >DiagnosticMessage : DiagnosticMessage diff --git a/tests/baselines/reference/APISample_linter.js b/tests/baselines/reference/APISample_linter.js index fb390d78f8f..265d84ac5b3 100644 --- a/tests/baselines/reference/APISample_linter.js +++ b/tests/baselines/reference/APISample_linter.js @@ -1203,18 +1203,6 @@ declare module "typescript" { interface TypeMapper { (t: Type): Type; } - interface TypeInferences { - primary: Type[]; - secondary: Type[]; - isFixed: boolean; - } - interface InferenceContext { - typeParameters: TypeParameter[]; - inferUnionTypes: boolean; - inferences: TypeInferences[]; - inferredTypes: Type[]; - failedTypeParameterIndex?: number; - } interface DiagnosticMessage { key: string; category: DiagnosticCategory; diff --git a/tests/baselines/reference/APISample_linter.types b/tests/baselines/reference/APISample_linter.types index 90360b5fe61..f818edbaf39 100644 --- a/tests/baselines/reference/APISample_linter.types +++ b/tests/baselines/reference/APISample_linter.types @@ -3902,41 +3902,6 @@ declare module "typescript" { >t : Type >Type : Type >Type : Type - } - interface TypeInferences { ->TypeInferences : TypeInferences - - primary: Type[]; ->primary : Type[] ->Type : Type - - secondary: Type[]; ->secondary : Type[] ->Type : Type - - isFixed: boolean; ->isFixed : boolean - } - interface InferenceContext { ->InferenceContext : InferenceContext - - typeParameters: TypeParameter[]; ->typeParameters : TypeParameter[] ->TypeParameter : TypeParameter - - inferUnionTypes: boolean; ->inferUnionTypes : boolean - - inferences: TypeInferences[]; ->inferences : TypeInferences[] ->TypeInferences : TypeInferences - - inferredTypes: Type[]; ->inferredTypes : Type[] ->Type : Type - - failedTypeParameterIndex?: number; ->failedTypeParameterIndex : number } interface DiagnosticMessage { >DiagnosticMessage : DiagnosticMessage diff --git a/tests/baselines/reference/APISample_transform.js b/tests/baselines/reference/APISample_transform.js index 96b54ccd917..f1da0e2533a 100644 --- a/tests/baselines/reference/APISample_transform.js +++ b/tests/baselines/reference/APISample_transform.js @@ -1204,18 +1204,6 @@ declare module "typescript" { interface TypeMapper { (t: Type): Type; } - interface TypeInferences { - primary: Type[]; - secondary: Type[]; - isFixed: boolean; - } - interface InferenceContext { - typeParameters: TypeParameter[]; - inferUnionTypes: boolean; - inferences: TypeInferences[]; - inferredTypes: Type[]; - failedTypeParameterIndex?: number; - } interface DiagnosticMessage { key: string; category: DiagnosticCategory; diff --git a/tests/baselines/reference/APISample_transform.types b/tests/baselines/reference/APISample_transform.types index 999c81af401..6f22fb1ec6a 100644 --- a/tests/baselines/reference/APISample_transform.types +++ b/tests/baselines/reference/APISample_transform.types @@ -3852,41 +3852,6 @@ declare module "typescript" { >t : Type >Type : Type >Type : Type - } - interface TypeInferences { ->TypeInferences : TypeInferences - - primary: Type[]; ->primary : Type[] ->Type : Type - - secondary: Type[]; ->secondary : Type[] ->Type : Type - - isFixed: boolean; ->isFixed : boolean - } - interface InferenceContext { ->InferenceContext : InferenceContext - - typeParameters: TypeParameter[]; ->typeParameters : TypeParameter[] ->TypeParameter : TypeParameter - - inferUnionTypes: boolean; ->inferUnionTypes : boolean - - inferences: TypeInferences[]; ->inferences : TypeInferences[] ->TypeInferences : TypeInferences - - inferredTypes: Type[]; ->inferredTypes : Type[] ->Type : Type - - failedTypeParameterIndex?: number; ->failedTypeParameterIndex : number } interface DiagnosticMessage { >DiagnosticMessage : DiagnosticMessage diff --git a/tests/baselines/reference/APISample_watcher.js b/tests/baselines/reference/APISample_watcher.js index 8a3d2065a23..734467a1c59 100644 --- a/tests/baselines/reference/APISample_watcher.js +++ b/tests/baselines/reference/APISample_watcher.js @@ -1241,18 +1241,6 @@ declare module "typescript" { interface TypeMapper { (t: Type): Type; } - interface TypeInferences { - primary: Type[]; - secondary: Type[]; - isFixed: boolean; - } - interface InferenceContext { - typeParameters: TypeParameter[]; - inferUnionTypes: boolean; - inferences: TypeInferences[]; - inferredTypes: Type[]; - failedTypeParameterIndex?: number; - } interface DiagnosticMessage { key: string; category: DiagnosticCategory; diff --git a/tests/baselines/reference/APISample_watcher.types b/tests/baselines/reference/APISample_watcher.types index f66c818c53d..37940e9a1f8 100644 --- a/tests/baselines/reference/APISample_watcher.types +++ b/tests/baselines/reference/APISample_watcher.types @@ -4025,41 +4025,6 @@ declare module "typescript" { >t : Type >Type : Type >Type : Type - } - interface TypeInferences { ->TypeInferences : TypeInferences - - primary: Type[]; ->primary : Type[] ->Type : Type - - secondary: Type[]; ->secondary : Type[] ->Type : Type - - isFixed: boolean; ->isFixed : boolean - } - interface InferenceContext { ->InferenceContext : InferenceContext - - typeParameters: TypeParameter[]; ->typeParameters : TypeParameter[] ->TypeParameter : TypeParameter - - inferUnionTypes: boolean; ->inferUnionTypes : boolean - - inferences: TypeInferences[]; ->inferences : TypeInferences[] ->TypeInferences : TypeInferences - - inferredTypes: Type[]; ->inferredTypes : Type[] ->Type : Type - - failedTypeParameterIndex?: number; ->failedTypeParameterIndex : number } interface DiagnosticMessage { >DiagnosticMessage : DiagnosticMessage From 90fae03f1f45708815ee7470183b7c3cf7e669bc Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Mon, 16 Mar 2015 14:52:03 -0700 Subject: [PATCH 09/23] More PR feedback --- src/compiler/checker.ts | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index eed4b259596..efaaafd2e19 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4615,10 +4615,18 @@ module ts { if (target === typeParameters[i]) { let inferences = context.inferences[i]; if (!inferences.isFixed) { + // Any inferences that are made to a type parameter in a union type are inferior + // to inferences made to a flat (non-union) type. This is because if we infer to + // T | string[], we really don't know if we should be inferring to T or not (because + // the correct constituent on the target side could be string[]). Therefore, we put + // such inferior inferences into a secondary bucket, and only use them if the primary + // bucket is empty. let candidates = inferiority ? inferences.secondary || (inferences.secondary = []) : inferences.primary || (inferences.primary = []); - if (!contains(candidates, source)) candidates.push(source); + if (!contains(candidates, source)) { + candidates.push(source); + } } return; } @@ -6358,12 +6366,22 @@ module ts { // Clear out all the inference results from the last time inferTypeArguments was called on this context for (let i = 0; i < typeParameters.length; i++) { // As an optimization, we don't have to clear (and later recompute) inferred types - // for type parameters that have already been fixed on the previous call to inferTypeArguments + // for type parameters that have already been fixed on the previous call to inferTypeArguments. + // It would be just as correct to reset all of them. But then we'd be repeating the same work + // for the type parameters that were fixed, namely the work done by getInferredType. if (!context.inferences[i].isFixed) { context.inferredTypes[i] = undefined; } } - if (context.failedTypeParameterIndex >= 0 && !context.inferences[context.failedTypeParameterIndex].isFixed) { + + // On this call to inferTypeArguments, we may get more inferences for certain type parameters that were not + // fixed last time. This means that a type parameter that failed inference last time may succeed this time, + // or vice versa. Therefore, the failedTypeParameterIndex is useless if it points to an unfixed type parameter, + // because it may change. So here we reset it. However, getInferredType will not revisit any type parameters + // that were previously fixed. So if a fixed type parameter failed previously, it will fail again because + // it will contain the exact same set of inferences. So if we reset the index from a fixed type parameter, + // we will lose information that we won't recover this time around. + if (context.failedTypeParameterIndex !== undefined && !context.inferences[context.failedTypeParameterIndex].isFixed) { context.failedTypeParameterIndex = undefined; } From 74eb96a5b906d68c42e509432caad5c07a314f84 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 16 Mar 2015 19:51:22 -0700 Subject: [PATCH 10/23] correctly merge const enum only and instantiated modules --- src/compiler/binder.ts | 13 ++++--- .../reference/constEnumOnlyModuleMerging.js | 26 +++++++++++++ .../constEnumOnlyModuleMerging.types | 37 +++++++++++++++++++ .../compiler/constEnumOnlyModuleMerging.ts | 13 +++++++ 4 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/constEnumOnlyModuleMerging.js create mode 100644 tests/baselines/reference/constEnumOnlyModuleMerging.types create mode 100644 tests/cases/compiler/constEnumOnlyModuleMerging.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index f951fe49269..3535aaffb27 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -322,13 +322,14 @@ module ts { } else { bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true); - if (state === ModuleInstanceState.ConstEnumOnly) { - // mark value module as module that contains only enums - node.symbol.constEnumOnlyModule = true; + let currentModuleIsConstEnumOnly = state === ModuleInstanceState.ConstEnumOnly; + if (node.symbol.constEnumOnlyModule === undefined) { + // non-merged case - use the current state + node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly; } - else if (node.symbol.constEnumOnlyModule) { - // const only value module was merged with instantiated module - reset flag - node.symbol.constEnumOnlyModule = false; + else { + // merged case: module is const enum only if all its pieces are non-instantiated or const enum + node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly; } } } diff --git a/tests/baselines/reference/constEnumOnlyModuleMerging.js b/tests/baselines/reference/constEnumOnlyModuleMerging.js new file mode 100644 index 00000000000..1d32fe748ab --- /dev/null +++ b/tests/baselines/reference/constEnumOnlyModuleMerging.js @@ -0,0 +1,26 @@ +//// [constEnumOnlyModuleMerging.ts] +module Outer { + export var x = 1; +} + +module Outer { + export const enum A { X } +} + +module B { + import O = Outer; + var x = O.A.X; + var y = O.x; +} + +//// [constEnumOnlyModuleMerging.js] +var Outer; +(function (Outer) { + Outer.x = 1; +})(Outer || (Outer = {})); +var B; +(function (B) { + var O = Outer; + var x = 0 /* X */; + var y = O.x; +})(B || (B = {})); diff --git a/tests/baselines/reference/constEnumOnlyModuleMerging.types b/tests/baselines/reference/constEnumOnlyModuleMerging.types new file mode 100644 index 00000000000..30426e3fa4c --- /dev/null +++ b/tests/baselines/reference/constEnumOnlyModuleMerging.types @@ -0,0 +1,37 @@ +=== tests/cases/compiler/constEnumOnlyModuleMerging.ts === +module Outer { +>Outer : typeof Outer + + export var x = 1; +>x : number +} + +module Outer { +>Outer : typeof Outer + + export const enum A { X } +>A : A +>X : A +} + +module B { +>B : typeof B + + import O = Outer; +>O : typeof O +>Outer : typeof O + + var x = O.A.X; +>x : O.A +>O.A.X : O.A +>O.A : typeof O.A +>O : typeof O +>A : typeof O.A +>X : O.A + + var y = O.x; +>y : number +>O.x : number +>O : typeof O +>x : number +} diff --git a/tests/cases/compiler/constEnumOnlyModuleMerging.ts b/tests/cases/compiler/constEnumOnlyModuleMerging.ts new file mode 100644 index 00000000000..0b1b9e3f0cb --- /dev/null +++ b/tests/cases/compiler/constEnumOnlyModuleMerging.ts @@ -0,0 +1,13 @@ +module Outer { + export var x = 1; +} + +module Outer { + export const enum A { X } +} + +module B { + import O = Outer; + var x = O.A.X; + var y = O.x; +} \ No newline at end of file From 686d1c60deb618040211c53c37590cf70187c74a Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 16 Mar 2015 21:33:39 -0700 Subject: [PATCH 11/23] A more complete isCompletedNode. --- src/harness/fourslash.ts | 8 ++-- src/services/formatting/smartIndenter.ts | 45 +++++++++++++++---- src/services/utilities.ts | 4 ++ tests/cases/fourslash/indentation.ts | 8 ++-- ...artIndentNonterminatedArgumentListAtEOF.ts | 2 +- 5 files changed, 51 insertions(+), 16 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index d8b7c358a55..0ae29a6ec87 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1621,8 +1621,9 @@ module FourSlash { this.taoInvalidReason = 'verifyIndentationAtCurrentPosition NYI'; var actual = this.getIndentation(this.activeFile.fileName, this.currentCaretPosition); - if (actual != numberOfSpaces) { - this.raiseError('verifyIndentationAtCurrentPosition failed - expected: ' + numberOfSpaces + ', actual: ' + actual); + var lineCol = this.getLineColStringAtPosition(this.currentCaretPosition); + if (actual !== numberOfSpaces) { + this.raiseError('verifyIndentationAtCurrentPosition failed at ' + lineCol + ' - expected: ' + numberOfSpaces + ', actual: ' + actual); } } @@ -1630,8 +1631,9 @@ module FourSlash { this.taoInvalidReason = 'verifyIndentationAtPosition NYI'; var actual = this.getIndentation(fileName, position); + var lineCol = this.getLineColStringAtPosition(position); if (actual !== numberOfSpaces) { - this.raiseError('verifyIndentationAtPosition failed - expected: ' + numberOfSpaces + ', actual: ' + actual); + this.raiseError('verifyIndentationAtCurrentPosition failed at ' + lineCol + ' - expected: ' + numberOfSpaces + ', actual: ' + actual); } } diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index f1d0935c132..38ed4cf8442 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -429,46 +429,74 @@ module ts.formatting { case SyntaxKind.InterfaceDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.TypeLiteral: case SyntaxKind.Block: case SyntaxKind.ModuleBlock: case SyntaxKind.CaseBlock: return nodeEndsWith(n, SyntaxKind.CloseBraceToken, sourceFile); case SyntaxKind.CatchClause: return isCompletedNode((n).block, sourceFile); - case SyntaxKind.ParenthesizedExpression: - case SyntaxKind.CallSignature: + case SyntaxKind.NewExpression: + if (!(n).arguments) { + return true; + } + // fall through case SyntaxKind.CallExpression: case SyntaxKind.ConstructSignature: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.ParenthesizedType: return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile); + + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + return isCompletedNode((n).type, sourceFile); + + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: + case SyntaxKind.CallSignature: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: case SyntaxKind.ArrowFunction: - return !(n).body || isCompletedNode((n).body, sourceFile); + if ((n).body) { + return isCompletedNode((n).body, sourceFile); + } + + return hasChildOfKind(n, SyntaxKind.CloseParenToken, sourceFile) || + (n).typeParameters && hasChildOfKind(n, SyntaxKind.GreaterThanToken, sourceFile) + case SyntaxKind.ModuleDeclaration: return (n).body && isCompletedNode((n).body, sourceFile); + case SyntaxKind.IfStatement: if ((n).elseStatement) { return isCompletedNode((n).elseStatement, sourceFile); } return isCompletedNode((n).thenStatement, sourceFile); + case SyntaxKind.ExpressionStatement: return isCompletedNode((n).expression, sourceFile); + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.IndexSignature: + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.TupleType: return nodeEndsWith(n, SyntaxKind.CloseBracketToken, sourceFile); + case SyntaxKind.CaseClause: case SyntaxKind.DefaultClause: - // there is no such thing as terminator token for CaseClause\DefaultClause so for simplicitly always consider them non-completed + // there is no such thing as terminator token for CaseClause/DefaultClause so for simplicitly always consider them non-completed return false; + case SyntaxKind.ForStatement: - return isCompletedNode((n).statement, sourceFile); case SyntaxKind.ForInStatement: - return isCompletedNode((n).statement, sourceFile); case SyntaxKind.ForOfStatement: - return isCompletedNode((n).statement, sourceFile); case SyntaxKind.WhileStatement: - return isCompletedNode((n).statement, sourceFile); + return isCompletedNode((n).statement, sourceFile); case SyntaxKind.DoStatement: // rough approximation: if DoStatement has While keyword - then if node is completed is checking the presence of ')'; var hasWhileKeyword = findChildOfKind(n, SyntaxKind.WhileKeyword, sourceFile); @@ -476,6 +504,7 @@ module ts.formatting { return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile); } return isCompletedNode((n).statement, sourceFile); + default: return true; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index e0ff5293546..70c8eada5b7 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -79,6 +79,10 @@ module ts { }; } + export function hasChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFile): boolean { + return !!findChildOfKind(n, kind, sourceFile); + } + export function findChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFile): Node { return forEach(n.getChildren(sourceFile), c => c.kind === kind && c); } diff --git a/tests/cases/fourslash/indentation.ts b/tests/cases/fourslash/indentation.ts index 2a2090c1d87..356d076b9f2 100644 --- a/tests/cases/fourslash/indentation.ts +++ b/tests/cases/fourslash/indentation.ts @@ -176,8 +176,8 @@ ////// the purpose of this test is to verity smart indent ////// works for unterminated function arguments at the end of a file. ////function unterminatedListIndentation(a, -////{| "indent": 0 |} +////{| "indent": 4 |} -test.markers().forEach((marker) => { - verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent); - }); +test.markers().forEach(marker => { + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent); +}); diff --git a/tests/cases/fourslash/smartIndentNonterminatedArgumentListAtEOF.ts b/tests/cases/fourslash/smartIndentNonterminatedArgumentListAtEOF.ts index b2b1f746a32..a533eca1d67 100644 --- a/tests/cases/fourslash/smartIndentNonterminatedArgumentListAtEOF.ts +++ b/tests/cases/fourslash/smartIndentNonterminatedArgumentListAtEOF.ts @@ -4,4 +4,4 @@ /////**/ goTo.marker(); -verify.indentationIs(0); +verify.indentationIs(4); From a7f57cbe41111938e60ee30a8717bd70ae73f5fc Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 16 Mar 2015 22:09:17 -0700 Subject: [PATCH 12/23] Indentation within binding patterns. Fixes #2380. --- src/services/formatting/smartIndenter.ts | 2 ++ .../indentationAfterArrayBindingPattern01.ts | 14 ++++++++++++++ .../indentationAfterArrayBindingPattern02.ts | 15 +++++++++++++++ .../indentationAfterObjectBindingPattern01.ts | 15 +++++++++++++++ .../indentationAfterObjectBindingPattern02.ts | 16 ++++++++++++++++ 5 files changed, 62 insertions(+) create mode 100644 tests/cases/fourslash/indentationAfterArrayBindingPattern01.ts create mode 100644 tests/cases/fourslash/indentationAfterArrayBindingPattern02.ts create mode 100644 tests/cases/fourslash/indentationAfterObjectBindingPattern01.ts create mode 100644 tests/cases/fourslash/indentationAfterObjectBindingPattern02.ts diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 38ed4cf8442..c0a84e25e24 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -368,6 +368,8 @@ module ts.formatting { case SyntaxKind.ExportAssignment: case SyntaxKind.ReturnStatement: case SyntaxKind.ConditionalExpression: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ObjectBindingPattern: return true; } return false; diff --git a/tests/cases/fourslash/indentationAfterArrayBindingPattern01.ts b/tests/cases/fourslash/indentationAfterArrayBindingPattern01.ts new file mode 100644 index 00000000000..980f2383299 --- /dev/null +++ b/tests/cases/fourslash/indentationAfterArrayBindingPattern01.ts @@ -0,0 +1,14 @@ +/// + +////var /*1*/[/*2*/a,/*3*/b,/*4*/ + +function verifyIndentationAfterNewLine(marker: string, indentation: number): void { + goTo.marker(marker); + edit.insert("\r\n"); + verify.indentationIs(indentation); +} + +verifyIndentationAfterNewLine("1", 4); +verifyIndentationAfterNewLine("2", 8); +verifyIndentationAfterNewLine("3", 8); +verifyIndentationAfterNewLine("4", 8); \ No newline at end of file diff --git a/tests/cases/fourslash/indentationAfterArrayBindingPattern02.ts b/tests/cases/fourslash/indentationAfterArrayBindingPattern02.ts new file mode 100644 index 00000000000..b9a1da7796a --- /dev/null +++ b/tests/cases/fourslash/indentationAfterArrayBindingPattern02.ts @@ -0,0 +1,15 @@ +/// + +////var /*1*/[/*2*/a,/*3*/b/*4*/]/*5*/ + +function verifyIndentationAfterNewLine(marker: string, indentation: number): void { + goTo.marker(marker); + edit.insert("\r\n"); + verify.indentationIs(indentation); +} + +verifyIndentationAfterNewLine("1", 4); +verifyIndentationAfterNewLine("2", 8); +verifyIndentationAfterNewLine("3", 8); +verifyIndentationAfterNewLine("4", 8); +verifyIndentationAfterNewLine("5", 0); \ No newline at end of file diff --git a/tests/cases/fourslash/indentationAfterObjectBindingPattern01.ts b/tests/cases/fourslash/indentationAfterObjectBindingPattern01.ts new file mode 100644 index 00000000000..8bfcbe83b72 --- /dev/null +++ b/tests/cases/fourslash/indentationAfterObjectBindingPattern01.ts @@ -0,0 +1,15 @@ +/// + +////var /*1*/{/*2*/a,/*3*/b:/*4*/k,/*5*/ + +function verifyIndentationAfterNewLine(marker: string, indentation: number): void { + goTo.marker(marker); + edit.insert("\r\n"); + verify.indentationIs(indentation); +} + +verifyIndentationAfterNewLine("1", 4); +verifyIndentationAfterNewLine("2", 8); +verifyIndentationAfterNewLine("3", 8); +verifyIndentationAfterNewLine("4", 8); +verifyIndentationAfterNewLine("5", 8); \ No newline at end of file diff --git a/tests/cases/fourslash/indentationAfterObjectBindingPattern02.ts b/tests/cases/fourslash/indentationAfterObjectBindingPattern02.ts new file mode 100644 index 00000000000..e1612dffbb4 --- /dev/null +++ b/tests/cases/fourslash/indentationAfterObjectBindingPattern02.ts @@ -0,0 +1,16 @@ +/// + +////var /*1*/{/*2*/a,/*3*/b:/*4*/k,/*5*/}/*6*/ + +function verifyIndentationAfterNewLine(marker: string, indentation: number): void { + goTo.marker(marker); + edit.insert("\r\n"); + verify.indentationIs(indentation); +} + +verifyIndentationAfterNewLine("1", 4); +verifyIndentationAfterNewLine("2", 8); +verifyIndentationAfterNewLine("3", 8); +verifyIndentationAfterNewLine("4", 8); +verifyIndentationAfterNewLine("5", 8); +verifyIndentationAfterNewLine("6", 0); \ No newline at end of file From 3eea65512c5eb652c7dbd69175d1c87b4f190749 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 16 Mar 2015 22:13:55 -0700 Subject: [PATCH 13/23] Rename tests. --- ...rayBindingPattern01.ts => smartIndentArrayBindingPattern01.ts} | 0 ...rayBindingPattern02.ts => smartIndentArrayBindingPattern02.ts} | 0 ...ctBindingPattern01.ts => smartIndentObjectBindingPattern01.ts} | 0 ...ctBindingPattern02.ts => smartIndentObjectBindingPattern02.ts} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename tests/cases/fourslash/{indentationAfterArrayBindingPattern01.ts => smartIndentArrayBindingPattern01.ts} (100%) rename tests/cases/fourslash/{indentationAfterArrayBindingPattern02.ts => smartIndentArrayBindingPattern02.ts} (100%) rename tests/cases/fourslash/{indentationAfterObjectBindingPattern01.ts => smartIndentObjectBindingPattern01.ts} (100%) rename tests/cases/fourslash/{indentationAfterObjectBindingPattern02.ts => smartIndentObjectBindingPattern02.ts} (100%) diff --git a/tests/cases/fourslash/indentationAfterArrayBindingPattern01.ts b/tests/cases/fourslash/smartIndentArrayBindingPattern01.ts similarity index 100% rename from tests/cases/fourslash/indentationAfterArrayBindingPattern01.ts rename to tests/cases/fourslash/smartIndentArrayBindingPattern01.ts diff --git a/tests/cases/fourslash/indentationAfterArrayBindingPattern02.ts b/tests/cases/fourslash/smartIndentArrayBindingPattern02.ts similarity index 100% rename from tests/cases/fourslash/indentationAfterArrayBindingPattern02.ts rename to tests/cases/fourslash/smartIndentArrayBindingPattern02.ts diff --git a/tests/cases/fourslash/indentationAfterObjectBindingPattern01.ts b/tests/cases/fourslash/smartIndentObjectBindingPattern01.ts similarity index 100% rename from tests/cases/fourslash/indentationAfterObjectBindingPattern01.ts rename to tests/cases/fourslash/smartIndentObjectBindingPattern01.ts diff --git a/tests/cases/fourslash/indentationAfterObjectBindingPattern02.ts b/tests/cases/fourslash/smartIndentObjectBindingPattern02.ts similarity index 100% rename from tests/cases/fourslash/indentationAfterObjectBindingPattern02.ts rename to tests/cases/fourslash/smartIndentObjectBindingPattern02.ts From 905e46e20f1a21358a4d0d2df49397702f3dba1b Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 16 Mar 2015 22:40:58 -0700 Subject: [PATCH 14/23] Account for call signatures properly. --- src/services/formatting/smartIndenter.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index c0a84e25e24..36e3f8579df 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -390,6 +390,7 @@ module ts.formatting { case SyntaxKind.FunctionExpression: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: case SyntaxKind.ArrowFunction: case SyntaxKind.Constructor: case SyntaxKind.GetAccessor: @@ -459,9 +460,9 @@ module ts.formatting { case SyntaxKind.SetAccessor: case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: - case SyntaxKind.CallSignature: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: case SyntaxKind.ArrowFunction: if ((n).body) { return isCompletedNode((n).body, sourceFile); From 686a10085c55d3ab77ecacf2200596103629b540 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 16 Mar 2015 23:05:03 -0700 Subject: [PATCH 15/23] Moved construct signature down appropriately, fixed logic for function-like constructs. --- src/services/formatting/smartIndenter.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 36e3f8579df..76a95bcdadc 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -446,7 +446,6 @@ module ts.formatting { } // fall through case SyntaxKind.CallExpression: - case SyntaxKind.ConstructSignature: case SyntaxKind.ParenthesizedExpression: case SyntaxKind.ParenthesizedType: return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile); @@ -462,14 +461,20 @@ module ts.formatting { case SyntaxKind.FunctionExpression: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: + case SyntaxKind.ConstructSignature: case SyntaxKind.CallSignature: case SyntaxKind.ArrowFunction: if ((n).body) { return isCompletedNode((n).body, sourceFile); } - return hasChildOfKind(n, SyntaxKind.CloseParenToken, sourceFile) || - (n).typeParameters && hasChildOfKind(n, SyntaxKind.GreaterThanToken, sourceFile) + if ((n).type) { + return isCompletedNode((n).type, sourceFile); + } + + // Even though type parameters can be unclosed, we can get away with + // having at least a closing paren. + return hasChildOfKind(n, SyntaxKind.CloseParenToken, sourceFile); case SyntaxKind.ModuleDeclaration: return (n).body && isCompletedNode((n).body, sourceFile); From 6a6839a1b3bddf559ebf91f9901b23244900cc62 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 16 Mar 2015 23:10:36 -0700 Subject: [PATCH 16/23] Always indent on tuple type literals. --- src/services/formatting/smartIndenter.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 76a95bcdadc..0932ad042e7 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -357,6 +357,7 @@ module ts.formatting { case SyntaxKind.ModuleBlock: case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.TypeLiteral: + case SyntaxKind.TupleType: case SyntaxKind.CaseBlock: case SyntaxKind.DefaultClause: case SyntaxKind.CaseClause: From 577c12e42e3ec3fb8fc3b237e3d62ae334786285 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 16 Mar 2015 23:19:21 -0700 Subject: [PATCH 17/23] Added accumulated tests. --- .../smartIndentAfterNewExpression.ts | 17 +++++++++ .../smartIndentInParenthesizedExpression01.ts | 13 +++++++ .../smartIndentInParenthesizedExpression02.ts | 8 +++++ .../cases/fourslash/smartIndentOnAccessors.ts | 36 +++++++++++++++++++ .../fourslash/smartIndentOnAccessors01.ts | 36 +++++++++++++++++++ .../fourslash/smartIndentOnAccessors02.ts | 9 +++++ .../smartIndentOnUnclosedArrowType01.ts | 8 +++++ ...smartIndentOnUnclosedComputedProperty01.ts | 11 ++++++ .../smartIndentOnUnclosedConstructorType01.ts | 8 +++++ ...rtIndentOnUnclosedFunctionDeclaration01.ts | 13 +++++++ ...rtIndentOnUnclosedFunctionDeclaration02.ts | 14 ++++++++ ...rtIndentOnUnclosedFunctionDeclaration03.ts | 12 +++++++ ...rtIndentOnUnclosedFunctionDeclaration04.ts | 17 +++++++++ ...rtIndentOnUnclosedFunctionDeclaration05.ts | 9 +++++ ...rtIndentOnUnclosedFunctionDeclaration06.ts | 10 ++++++ .../smartIndentOnUnclosedIndexSignature01.ts | 11 ++++++ ...martIndentOnUnclosedObjectTypeLiteral01.ts | 8 +++++ ...smartIndentOnUnclosedTupleTypeLiteral01.ts | 8 +++++ 18 files changed, 248 insertions(+) create mode 100644 tests/cases/fourslash/smartIndentAfterNewExpression.ts create mode 100644 tests/cases/fourslash/smartIndentInParenthesizedExpression01.ts create mode 100644 tests/cases/fourslash/smartIndentInParenthesizedExpression02.ts create mode 100644 tests/cases/fourslash/smartIndentOnAccessors.ts create mode 100644 tests/cases/fourslash/smartIndentOnAccessors01.ts create mode 100644 tests/cases/fourslash/smartIndentOnAccessors02.ts create mode 100644 tests/cases/fourslash/smartIndentOnUnclosedArrowType01.ts create mode 100644 tests/cases/fourslash/smartIndentOnUnclosedComputedProperty01.ts create mode 100644 tests/cases/fourslash/smartIndentOnUnclosedConstructorType01.ts create mode 100644 tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration01.ts create mode 100644 tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration02.ts create mode 100644 tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration03.ts create mode 100644 tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration04.ts create mode 100644 tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration05.ts create mode 100644 tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration06.ts create mode 100644 tests/cases/fourslash/smartIndentOnUnclosedIndexSignature01.ts create mode 100644 tests/cases/fourslash/smartIndentOnUnclosedObjectTypeLiteral01.ts create mode 100644 tests/cases/fourslash/smartIndentOnUnclosedTupleTypeLiteral01.ts diff --git a/tests/cases/fourslash/smartIndentAfterNewExpression.ts b/tests/cases/fourslash/smartIndentAfterNewExpression.ts new file mode 100644 index 00000000000..f2d699f988b --- /dev/null +++ b/tests/cases/fourslash/smartIndentAfterNewExpression.ts @@ -0,0 +1,17 @@ +/// + +//// +////new Array +////{| "indent": 0 |} +////new Array; +////{| "indent": 0 |} +////new Array(0); +////{| "indent": 0 |} +////new Array(; +////{| "indent": 0 |} +////new Array( +////{| "indent": 4 |} + +test.markers().forEach(marker => { + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent); +}); diff --git a/tests/cases/fourslash/smartIndentInParenthesizedExpression01.ts b/tests/cases/fourslash/smartIndentInParenthesizedExpression01.ts new file mode 100644 index 00000000000..253f58071d9 --- /dev/null +++ b/tests/cases/fourslash/smartIndentInParenthesizedExpression01.ts @@ -0,0 +1,13 @@ +/// + +////var x = (/*1*/1/*2*/)/*3*/ + +function verifyIndentationAfterNewLine(marker: string, indentation: number): void { + goTo.marker(marker); + edit.insert("\r\n"); + verify.indentationIs(indentation); +} + +verifyIndentationAfterNewLine("1", 4); +verifyIndentationAfterNewLine("2", 4); +verifyIndentationAfterNewLine("3", 0); \ No newline at end of file diff --git a/tests/cases/fourslash/smartIndentInParenthesizedExpression02.ts b/tests/cases/fourslash/smartIndentInParenthesizedExpression02.ts new file mode 100644 index 00000000000..ac169d0b17e --- /dev/null +++ b/tests/cases/fourslash/smartIndentInParenthesizedExpression02.ts @@ -0,0 +1,8 @@ +/// + +////var y = ( +////{| "indent": 4 |} + +test.markers().forEach(marker => { + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/smartIndentOnAccessors.ts b/tests/cases/fourslash/smartIndentOnAccessors.ts new file mode 100644 index 00000000000..a7972b1f48b --- /dev/null +++ b/tests/cases/fourslash/smartIndentOnAccessors.ts @@ -0,0 +1,36 @@ +/// + +////class Foo { +//// get foo(a, +//// /*1*/b,/*0*/ +//// //comment/*2*/ +//// /*3*/c +//// ) { +//// } +//// set foo(a, +//// /*5*/b,/*4*/ +//// //comment/*6*/ +//// /*7*/c +//// ) { +//// } +////} + + +goTo.marker("0"); +edit.insert("\r\n"); +verify.indentationIs(8); +goTo.marker("1"); +verify.currentLineContentIs(" b,"); +goTo.marker("2"); +verify.currentLineContentIs(" //comment"); +goTo.marker("3"); +verify.currentLineContentIs(" c"); +goTo.marker("4"); +edit.insert("\r\n"); +verify.indentationIs(8); +goTo.marker("5"); +verify.currentLineContentIs(" b,"); +goTo.marker("6"); +verify.currentLineContentIs(" //comment"); +goTo.marker("7"); +verify.currentLineContentIs(" c"); \ No newline at end of file diff --git a/tests/cases/fourslash/smartIndentOnAccessors01.ts b/tests/cases/fourslash/smartIndentOnAccessors01.ts new file mode 100644 index 00000000000..a7972b1f48b --- /dev/null +++ b/tests/cases/fourslash/smartIndentOnAccessors01.ts @@ -0,0 +1,36 @@ +/// + +////class Foo { +//// get foo(a, +//// /*1*/b,/*0*/ +//// //comment/*2*/ +//// /*3*/c +//// ) { +//// } +//// set foo(a, +//// /*5*/b,/*4*/ +//// //comment/*6*/ +//// /*7*/c +//// ) { +//// } +////} + + +goTo.marker("0"); +edit.insert("\r\n"); +verify.indentationIs(8); +goTo.marker("1"); +verify.currentLineContentIs(" b,"); +goTo.marker("2"); +verify.currentLineContentIs(" //comment"); +goTo.marker("3"); +verify.currentLineContentIs(" c"); +goTo.marker("4"); +edit.insert("\r\n"); +verify.indentationIs(8); +goTo.marker("5"); +verify.currentLineContentIs(" b,"); +goTo.marker("6"); +verify.currentLineContentIs(" //comment"); +goTo.marker("7"); +verify.currentLineContentIs(" c"); \ No newline at end of file diff --git a/tests/cases/fourslash/smartIndentOnAccessors02.ts b/tests/cases/fourslash/smartIndentOnAccessors02.ts new file mode 100644 index 00000000000..08f0083f2f2 --- /dev/null +++ b/tests/cases/fourslash/smartIndentOnAccessors02.ts @@ -0,0 +1,9 @@ +/// + +////class Foo { +//// get foo() { +////{| "indent": 8 |} + +test.markers().forEach(marker => { + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent); +}); diff --git a/tests/cases/fourslash/smartIndentOnUnclosedArrowType01.ts b/tests/cases/fourslash/smartIndentOnUnclosedArrowType01.ts new file mode 100644 index 00000000000..44a47d984ab --- /dev/null +++ b/tests/cases/fourslash/smartIndentOnUnclosedArrowType01.ts @@ -0,0 +1,8 @@ +/// + +////var x: () => { +////{| "indent": 4 |} + +test.markers().forEach(marker => { + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent); +}); diff --git a/tests/cases/fourslash/smartIndentOnUnclosedComputedProperty01.ts b/tests/cases/fourslash/smartIndentOnUnclosedComputedProperty01.ts new file mode 100644 index 00000000000..0b57a2cb466 --- /dev/null +++ b/tests/cases/fourslash/smartIndentOnUnclosedComputedProperty01.ts @@ -0,0 +1,11 @@ +/// + +////var x = { +//// [1123123123132 +////{| "indent": 4 |} +////} + +// Note that we currently do NOT indent further in a computed property. +test.markers().forEach(marker => { + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/smartIndentOnUnclosedConstructorType01.ts b/tests/cases/fourslash/smartIndentOnUnclosedConstructorType01.ts new file mode 100644 index 00000000000..ae76cbf06c9 --- /dev/null +++ b/tests/cases/fourslash/smartIndentOnUnclosedConstructorType01.ts @@ -0,0 +1,8 @@ +/// + +////var x: new () => { +////{| "indent": 4 |} + +test.markers().forEach(marker => { + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent); +}); diff --git a/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration01.ts b/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration01.ts new file mode 100644 index 00000000000..3e08fe5975e --- /dev/null +++ b/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration01.ts @@ -0,0 +1,13 @@ +/// + +////function /*1*/f/*2*/ + + +function verifyIndentationAfterNewLine(marker: string, indentation: number): void { + goTo.marker(marker); + edit.insert("\r\n"); + verify.indentationIs(indentation); +} + +verifyIndentationAfterNewLine("1", 4); +verifyIndentationAfterNewLine("2", 4); \ No newline at end of file diff --git a/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration02.ts b/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration02.ts new file mode 100644 index 00000000000..3de8b5ec6c3 --- /dev/null +++ b/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration02.ts @@ -0,0 +1,14 @@ +/// + +////function f + +////function f/*1*/ + + +function verifyIndentationAfterNewLine(marker: string, indentation: number): void { + goTo.marker(marker); + edit.insert("\r\n"); + verify.indentationIs(indentation); +} + +verifyIndentationAfterNewLine("1", 4); \ No newline at end of file diff --git a/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration04.ts b/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration04.ts new file mode 100644 index 00000000000..3931433e51f --- /dev/null +++ b/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration04.ts @@ -0,0 +1,17 @@ +/// + +////function f/*1*/(/*2*/a: A, /*3*/b:/*4*/B, c/*5*/, d: C/*6*/ + + +function verifyIndentationAfterNewLine(marker: string, indentation: number): void { + goTo.marker(marker); + edit.insert("\r\n"); + verify.indentationIs(indentation); +} + +verifyIndentationAfterNewLine("1", 4); +verifyIndentationAfterNewLine("2", 4); +verifyIndentationAfterNewLine("3", 4); +verifyIndentationAfterNewLine("4", 4); +verifyIndentationAfterNewLine("5", 4); +verifyIndentationAfterNewLine("6", 4); \ No newline at end of file diff --git a/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration05.ts b/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration05.ts new file mode 100644 index 00000000000..24c2bca72f7 --- /dev/null +++ b/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration05.ts @@ -0,0 +1,9 @@ +/// + +////function f(a: A, b:B, c, d: C): { +////{| "indent": 4 |} +//// + +test.markers().forEach(marker => { + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent); +}); diff --git a/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration06.ts b/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration06.ts new file mode 100644 index 00000000000..782a85c908a --- /dev/null +++ b/tests/cases/fourslash/smartIndentOnUnclosedFunctionDeclaration06.ts @@ -0,0 +1,10 @@ +/// + +////function f(a: A, b:B, c, d: C): { +////{| "indent": 4 |} +////} { +////{| "indent": 4 |} + +test.markers().forEach(marker => { + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent); +}); diff --git a/tests/cases/fourslash/smartIndentOnUnclosedIndexSignature01.ts b/tests/cases/fourslash/smartIndentOnUnclosedIndexSignature01.ts new file mode 100644 index 00000000000..da88bc9d0c1 --- /dev/null +++ b/tests/cases/fourslash/smartIndentOnUnclosedIndexSignature01.ts @@ -0,0 +1,11 @@ +/// + +////class C { +////[x: string +////{| "indent": 4 |} +//// + +// Note that we currently do NOT indent further in an index signature. +test.markers().forEach(marker => { + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/smartIndentOnUnclosedObjectTypeLiteral01.ts b/tests/cases/fourslash/smartIndentOnUnclosedObjectTypeLiteral01.ts new file mode 100644 index 00000000000..f2f900ce5d8 --- /dev/null +++ b/tests/cases/fourslash/smartIndentOnUnclosedObjectTypeLiteral01.ts @@ -0,0 +1,8 @@ +/// + +////var x: { +////{| "indent": 4 |} + +test.markers().forEach(marker => { + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/smartIndentOnUnclosedTupleTypeLiteral01.ts b/tests/cases/fourslash/smartIndentOnUnclosedTupleTypeLiteral01.ts new file mode 100644 index 00000000000..f2346e6bddc --- /dev/null +++ b/tests/cases/fourslash/smartIndentOnUnclosedTupleTypeLiteral01.ts @@ -0,0 +1,8 @@ +/// + +////var x: [string, number, +////{| "indent": 4 |} + +test.markers().forEach(marker => { + verify.indentationAtPositionIs(marker.fileName, marker.position, marker.data.indent); +}); \ No newline at end of file From b4811fc8bed9dccf1f73efff81e6c4d1a87f745e Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 16 Mar 2015 23:22:15 -0700 Subject: [PATCH 18/23] Fix copy/paste error. --- src/harness/fourslash.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 0ae29a6ec87..95a320ac052 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1633,7 +1633,7 @@ module FourSlash { var actual = this.getIndentation(fileName, position); var lineCol = this.getLineColStringAtPosition(position); if (actual !== numberOfSpaces) { - this.raiseError('verifyIndentationAtCurrentPosition failed at ' + lineCol + ' - expected: ' + numberOfSpaces + ', actual: ' + actual); + this.raiseError('verifyIndentationAtPosition failed at ' + lineCol + ' - expected: ' + numberOfSpaces + ', actual: ' + actual); } } From 857d1e0bb653959a36b4808bc805712386bd6b02 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 17 Mar 2015 07:42:24 -0700 Subject: [PATCH 19/23] Fixed case for index signatures. --- src/services/formatting/smartIndenter.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 0932ad042e7..be21b69f56b 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -491,11 +491,17 @@ module ts.formatting { case SyntaxKind.ArrayLiteralExpression: case SyntaxKind.ArrayBindingPattern: - case SyntaxKind.IndexSignature: case SyntaxKind.ComputedPropertyName: case SyntaxKind.TupleType: return nodeEndsWith(n, SyntaxKind.CloseBracketToken, sourceFile); + case SyntaxKind.IndexSignature: + if ((n).type) { + return isCompletedNode((n).type, sourceFile); + } + + return hasChildOfKind(n, SyntaxKind.CloseBracketToken, sourceFile); + case SyntaxKind.CaseClause: case SyntaxKind.DefaultClause: // there is no such thing as terminator token for CaseClause/DefaultClause so for simplicitly always consider them non-completed From f14abfefabb7d238e53589e0af1d578190bd5303 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Mon, 16 Mar 2015 18:25:44 -0700 Subject: [PATCH 20/23] Add clarifying comment --- src/compiler/checker.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d86a461dbc3..4f119232476 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4372,8 +4372,11 @@ module ts { } function reportNoCommonSupertypeError(types: Type[], errorLocation: Node, errorMessageChainHead: DiagnosticMessageChain): void { + // The downfallType/bestSupertypeDownfallType is the first type that caused a particular candidate + // to not be the common supertype. So if it weren't for this one downfallType (and possibly others), + // the type in question could have been the common supertype. let bestSupertype: Type; - let bestSupertypeDownfallType: Type; // The type that caused bestSupertype not to be the common supertype + let bestSupertypeDownfallType: Type; let bestSupertypeScore = 0; for (let i = 0; i < types.length; i++) { @@ -4575,9 +4578,9 @@ module ts { inferences.push({ primary: undefined, secondary: undefined, isFixed: false }); } return { - typeParameters: typeParameters, - inferUnionTypes: inferUnionTypes, - inferences: inferences, + typeParameters, + inferUnionTypes, + inferences, inferredTypes: new Array(typeParameters.length), }; } From 87dacb8c91a19209d1d02a5b0ad75a234f7400b1 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Mar 2015 11:57:40 -0700 Subject: [PATCH 21/23] Add .gitattributes to override GitHub Linguist language classification for the repo --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..74f5f4a6409 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.js linguist-language=TypeScript \ No newline at end of file From b2b3d8b2762710a00009c3341f71baf7778c4bc4 Mon Sep 17 00:00:00 2001 From: Dan Quirk Date: Tue, 17 Mar 2015 12:15:13 -0700 Subject: [PATCH 22/23] Remove CodeClimate stuff --- .travis.yml | 11 +---------- package.json | 3 +-- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 305fad1e4a7..572ac835cd4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,13 +3,4 @@ language: node_js node_js: - '0.10' -sudo: false - -before_script: npm install -g codeclimate-test-reporter - -after_script: - - cat coverage/lcov.info | codeclimate - -addons: - code_climate: - repo_token: 9852ac5362c8cc38c07ca5adc0f94c20c6c79bd78e17933dc284598a65338656 +sudo: false \ No newline at end of file diff --git a/package.json b/package.json index 9261174b68f..3fbd9b3313e 100644 --- a/package.json +++ b/package.json @@ -39,9 +39,8 @@ "chai": "latest", "browserify": "latest", "istanbul": "latest", - "codeclimate-test-reporter": "latest" }, "scripts": { - "test": "jake generate-code-coverage" + "test": "jake runtests" } } From 83d38c46dcddf349f5b84a1233b7b925024a25cb Mon Sep 17 00:00:00 2001 From: Dan Quirk Date: Tue, 17 Mar 2015 12:25:01 -0700 Subject: [PATCH 23/23] Delete extra comma --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3fbd9b3313e..c33f2a93ec1 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "mocha": "latest", "chai": "latest", "browserify": "latest", - "istanbul": "latest", + "istanbul": "latest" }, "scripts": { "test": "jake runtests"