From 456a6bf658b25d559d3eadc9e9ea04aaa5faf7f4 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Sat, 3 Jun 2017 00:10:41 +0200 Subject: [PATCH 001/405] program.getSourceFile[ByPath] can return undefined --- src/compiler/program.ts | 4 ++-- src/compiler/types.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 834122b3584..d481e72b689 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -969,11 +969,11 @@ namespace ts { return emitResult; } - function getSourceFile(fileName: string): SourceFile { + function getSourceFile(fileName: string): SourceFile | undefined { return getSourceFileByPath(toPath(fileName, currentDirectory, getCanonicalFileName)); } - function getSourceFileByPath(path: Path): SourceFile { + function getSourceFileByPath(path: Path): SourceFile | undefined { return filesByName.get(path); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ed1d5dcbe23..da438809d92 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2352,8 +2352,8 @@ namespace ts { export interface ScriptReferenceHost { getCompilerOptions(): CompilerOptions; - getSourceFile(fileName: string): SourceFile; - getSourceFileByPath(path: Path): SourceFile; + getSourceFile(fileName: string): SourceFile | undefined; + getSourceFileByPath(path: Path): SourceFile | undefined; getCurrentDirectory(): string; } From 0bd3d8c2eb01a0e881177c59e1f3a9136533de05 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Wed, 21 Jun 2017 15:03:20 -0700 Subject: [PATCH 002/405] unspoof call expression start in iife --- src/services/formatting/smartIndenter.ts | 53 ++++++++++++++++-------- src/services/services.ts | 2 +- src/services/textChanges.ts | 2 +- src/services/utilities.ts | 5 ++- 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 18b0479c85a..7609296ccf5 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -9,18 +9,21 @@ namespace ts.formatting { } /** - * Computed indentation for a given position in source file - * @param position - position in file - * @param sourceFile - target source file - * @param options - set of editor options that control indentation - * @param assumeNewLineBeforeCloseBrace - false when getIndentation is called on the text from the real source file. - * true - when we need to assume that position is on the newline. This is usefult for codefixes, i.e. + * @param assumeNewLineBeforeCloseBrace + * `false` when called on text from a real source file. + * `true` when we need to assume `position` is on a newline. + * + * This is useful for codefixes. Consider + * ``` * function f() { * |} - * when inserting some text after open brace we would like to get the value of indentation as if newline was already there. - * However by default indentation at position | will be 0 so 'assumeNewLineBeforeCloseBrace' allows to override this behavior, + * ``` + * with `position` at `|`. + * + * When inserting some text after an open brace, we would like to get indentation as if a newline was already there. + * By default indentation at `position` will be 0 so 'assumeNewLineBeforeCloseBrace' overrides this behavior, */ - export function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number { + export function getIndentationAtPosition(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number { if (position > sourceFile.text.length) { return getBaseIndentation(options); // past EOF } @@ -136,8 +139,10 @@ namespace ts.formatting { let parent: Node = current.parent; let parentStart: LineAndCharacter; - // walk upwards and collect indentations for pairs of parent-child nodes - // indentation is not added if parent and child nodes start on the same line or if parent is IfStatement and child starts on the same line with 'else clause' + // Walk up the tree and collect indentation for pairs of parent-child nodes. + // indentation is not added if + // * parent and child nodes start on the same line + // * parent is IfStatement and child starts on the same line with 'else clause' while (parent) { let useActualIndentation = true; if (ignoreActualIndentationRange) { @@ -174,22 +179,24 @@ namespace ts.formatting { indentationDelta += options.indentSize; } + // Update current and parent. + + const callExpressionUsesTrueStart = + isParameterAndStartLineOverlapsExpressionBeingCalled(parent, current, currentStart.line, sourceFile); + current = parent; - currentStart = parentStart; parent = current.parent; + currentStart = callExpressionUsesTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart()) : parentStart; + parentStart = undefined; } return indentationDelta + getBaseIndentation(options); } - function getParentStart(parent: Node, child: Node, sourceFile: SourceFile): LineAndCharacter { const containingList = getContainingList(child, sourceFile); - if (containingList) { - return sourceFile.getLineAndCharacterOfPosition(containingList.pos); - } - - return sourceFile.getLineAndCharacterOfPosition(parent.getStart(sourceFile)); + const startPos = containingList ? containingList.pos : parent.getStart(sourceFile); + return sourceFile.getLineAndCharacterOfPosition(startPos); } /* @@ -268,6 +275,16 @@ namespace ts.formatting { return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); } + export function isParameterAndStartLineOverlapsExpressionBeingCalled(parent: Node, child: Node, childStartLine: number, sourceFile: SourceFileLike): boolean { + if (!(isCallExpression(parent) && contains(parent.arguments, child))) { + return false; + } + + const callExpressionEnd = parent.expression.getEnd(); + const expressionEndLine = getLineAndCharacterOfPosition(sourceFile, callExpressionEnd).line; + return expressionEndLine === childStartLine; + } + export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFileLike): boolean { if (parent.kind === SyntaxKind.IfStatement && (parent).elseStatement === child) { const elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile); diff --git a/src/services/services.ts b/src/services/services.ts index b508285b182..13e6e2a2e4b 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1742,7 +1742,7 @@ namespace ts { start = timestamp(); - const result = formatting.SmartIndenter.getIndentation(position, sourceFile, settings); + const result = formatting.SmartIndenter.getIndentationAtPosition(position, sourceFile, settings); log("getIndentationAtPosition: computeIndentation : " + (timestamp() - start)); return result; diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 5aa4ebca7d0..e0d96d26a55 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -465,7 +465,7 @@ namespace ts.textChanges { change.options.indentation !== undefined ? change.options.indentation : change.useIndentationFromFile - ? formatting.SmartIndenter.getIndentation(change.range.pos, sourceFile, formatOptions, posStartsLine || (change.options.prefix === this.newLineCharacter)) + ? formatting.SmartIndenter.getIndentationAtPosition(change.range.pos, sourceFile, formatOptions, posStartsLine || (change.options.prefix === this.newLineCharacter)) : 0; const delta = change.options.delta !== undefined diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 78c71403736..f0a0c3ee758 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -402,8 +402,11 @@ namespace ts { return start < end; } + /** + * Assumes `candidate.start <= position` holds. + */ export function positionBelongsToNode(candidate: Node, position: number, sourceFile: SourceFile): boolean { - return candidate.end > position || !isCompletedNode(candidate, sourceFile); + return position < candidate.end || !isCompletedNode(candidate, sourceFile); } export function isCompletedNode(n: Node, sourceFile: SourceFile): boolean { From d1423739cdaea03f1e27f9522816e52517581dbe Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Wed, 21 Jun 2017 15:05:15 -0700 Subject: [PATCH 003/405] add test --- tests/cases/fourslash/indentationInAmdIife.ts | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 tests/cases/fourslash/indentationInAmdIife.ts diff --git a/tests/cases/fourslash/indentationInAmdIife.ts b/tests/cases/fourslash/indentationInAmdIife.ts new file mode 100644 index 00000000000..46169334463 --- /dev/null +++ b/tests/cases/fourslash/indentationInAmdIife.ts @@ -0,0 +1,52 @@ +/// + +//// function foo(a?,b?) { b(a); } +//// +//// (foo)(1, function() {/*4_0*/ +//// }); +//// +//// ///////////// +//// +//// ( +//// foo)(1, function () {/*4_1*/ +//// }); +//// (foo) +//// (1, function () {/*8_0*/ +//// }); +//// (foo)(1, +//// function () {/*8_1*/ +//// }); +//// (foo)(1, function() +//// {/*4_2*/ +//// }); +//// +//// ////////////////////// +//// +//// (foo +//// )(1, function () {/*4_3*/ +//// }); +//// (foo +//// ) +//// (1, function () {/*8_2*/ +//// }); +//// (foo +//// )(1, +//// function () {/*8_3*/ +//// }); +//// (foo +//// )(1, function() +//// {/*4_4*/ +//// }); + + +for (let i = 0; i < 5; ++i) { + goTo.marker(`4_${i}`); + edit.insertLine(""); + verify.indentationIs(4); +} + +for (let i = 1; i < 4; ++i) { + goTo.marker(`8_${i}`); + edit.insertLine(""); + verify.indentationIs(8); +} \ No newline at end of file From 902d0f501803af9d6e24ffe6ca85751386efd6ba Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Wed, 21 Jun 2017 17:04:39 -0700 Subject: [PATCH 004/405] cleanup --- src/services/formatting/smartIndenter.ts | 22 +++++++++---------- tests/cases/fourslash/indentationInAmdIife.ts | 13 +++++------ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 7609296ccf5..e1e440a9505 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -21,7 +21,7 @@ namespace ts.formatting { * with `position` at `|`. * * When inserting some text after an open brace, we would like to get indentation as if a newline was already there. - * By default indentation at `position` will be 0 so 'assumeNewLineBeforeCloseBrace' overrides this behavior, + * By default indentation at `position` will be 0 so 'assumeNewLineBeforeCloseBrace' overrides this behavior. */ export function getIndentationAtPosition(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number { if (position > sourceFile.text.length) { @@ -139,10 +139,9 @@ namespace ts.formatting { let parent: Node = current.parent; let parentStart: LineAndCharacter; - // Walk up the tree and collect indentation for pairs of parent-child nodes. - // indentation is not added if - // * parent and child nodes start on the same line - // * parent is IfStatement and child starts on the same line with 'else clause' + // Walk up the tree and collect indentation for parent-child node pairs. Indentation is not added if + // * parent and child nodes start on the same line, or + // * parent is an IfStatement and child starts on the same line as an 'else clause'. while (parent) { let useActualIndentation = true; if (ignoreActualIndentationRange) { @@ -157,6 +156,7 @@ namespace ts.formatting { return actualIndentation + indentationDelta; } } + parentStart = getParentStart(parent, current, sourceFile); const parentAndChildShareLine = parentStart.line === currentStart.line || @@ -179,14 +179,14 @@ namespace ts.formatting { indentationDelta += options.indentSize; } - // Update current and parent. + // Update `current` and `parent`. - const callExpressionUsesTrueStart = + const useTrueStart = isParameterAndStartLineOverlapsExpressionBeingCalled(parent, current, currentStart.line, sourceFile); current = parent; parent = current.parent; - currentStart = callExpressionUsesTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart()) : parentStart; + currentStart = useTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart()) : parentStart; parentStart = undefined; } @@ -280,9 +280,9 @@ namespace ts.formatting { return false; } - const callExpressionEnd = parent.expression.getEnd(); - const expressionEndLine = getLineAndCharacterOfPosition(sourceFile, callExpressionEnd).line; - return expressionEndLine === childStartLine; + const expressionOfCallExpressionEnd = parent.expression.getEnd(); + const expressionOfCallExpressionEndLine = getLineAndCharacterOfPosition(sourceFile, expressionOfCallExpressionEnd).line; + return expressionOfCallExpressionEndLine === childStartLine; } export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFileLike): boolean { diff --git a/tests/cases/fourslash/indentationInAmdIife.ts b/tests/cases/fourslash/indentationInAmdIife.ts index 46169334463..f735ae57eb2 100644 --- a/tests/cases/fourslash/indentationInAmdIife.ts +++ b/tests/cases/fourslash/indentationInAmdIife.ts @@ -5,11 +5,8 @@ //// (foo)(1, function() {/*4_0*/ //// }); //// -//// ///////////// +//// // No line-breaks in the expression part of the call expression //// -//// ( -//// foo)(1, function () {/*4_1*/ -//// }); //// (foo) //// (1, function () {/*8_0*/ //// }); @@ -20,8 +17,11 @@ //// {/*4_2*/ //// }); //// -//// ////////////////////// -//// +//// // Contains line-breaks in the expression part of the call expression. +//// +//// ( +//// foo)(1, function () {/*4_1*/ +//// }); //// (foo //// )(1, function () {/*4_3*/ //// }); @@ -38,7 +38,6 @@ //// {/*4_4*/ //// }); - for (let i = 0; i < 5; ++i) { goTo.marker(`4_${i}`); edit.insertLine(""); From 1251668342775f00c5f2654490e6078289eb35af Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 22 Jun 2017 10:32:04 -0700 Subject: [PATCH 005/405] rename variables --- src/services/formatting/smartIndenter.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index e1e440a9505..7900f8bb8c3 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -137,7 +137,7 @@ namespace ts.formatting { options: EditorSettings): number { let parent: Node = current.parent; - let parentStart: LineAndCharacter; + let containingListOrParentStart: LineAndCharacter; // Walk up the tree and collect indentation for parent-child node pairs. Indentation is not added if // * parent and child nodes start on the same line, or @@ -157,9 +157,9 @@ namespace ts.formatting { } } - parentStart = getParentStart(parent, current, sourceFile); + containingListOrParentStart = getContainingListOrParentStart(parent, current, sourceFile); const parentAndChildShareLine = - parentStart.line === currentStart.line || + containingListOrParentStart.line === currentStart.line || childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile); if (useActualIndentation) { @@ -182,18 +182,18 @@ namespace ts.formatting { // Update `current` and `parent`. const useTrueStart = - isParameterAndStartLineOverlapsExpressionBeingCalled(parent, current, currentStart.line, sourceFile); + isArgumentAndStartLineOverlapsExpressionBeingCalled(parent, current, currentStart.line, sourceFile); current = parent; parent = current.parent; - currentStart = useTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart()) : parentStart; - parentStart = undefined; + currentStart = useTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart()) : containingListOrParentStart; + containingListOrParentStart = undefined; } return indentationDelta + getBaseIndentation(options); } - function getParentStart(parent: Node, child: Node, sourceFile: SourceFile): LineAndCharacter { + function getContainingListOrParentStart(parent: Node, child: Node, sourceFile: SourceFile): LineAndCharacter { const containingList = getContainingList(child, sourceFile); const startPos = containingList ? containingList.pos : parent.getStart(sourceFile); return sourceFile.getLineAndCharacterOfPosition(startPos); @@ -275,7 +275,7 @@ namespace ts.formatting { return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); } - export function isParameterAndStartLineOverlapsExpressionBeingCalled(parent: Node, child: Node, childStartLine: number, sourceFile: SourceFileLike): boolean { + export function isArgumentAndStartLineOverlapsExpressionBeingCalled(parent: Node, child: Node, childStartLine: number, sourceFile: SourceFileLike): boolean { if (!(isCallExpression(parent) && contains(parent.arguments, child))) { return false; } From 1f77317b6459641212efcf3fd6b9b6aa005ba968 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sun, 13 Aug 2017 15:12:11 +0800 Subject: [PATCH 006/405] add strictTuples flag giving tuples known length --- src/compiler/checker.ts | 7 +++ src/compiler/commandLineParser.ts | 7 +++ src/compiler/diagnosticMessages.json | 4 ++ src/compiler/types.ts | 1 + .../unittests/configurationExtension.ts | 6 +++ src/harness/unittests/transpile.ts | 4 ++ src/server/protocol.ts | 1 + .../baselines/reference/genericTypeAliases.js | 4 +- .../reference/genericTypeAliases.symbols | 32 ++++++------- .../reference/genericTypeAliases.types | 12 ++--- .../nominalSubtypeCheckOfTypeParameter.js | 10 ++-- ...nominalSubtypeCheckOfTypeParameter.symbols | 46 +++++++++---------- .../nominalSubtypeCheckOfTypeParameter.types | 20 ++++---- .../Supports setting strictTuples.js | 2 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../reference/tupleLength.errors.txt | 26 +++++++++++ tests/baselines/reference/tupleLength.js | 32 +++++++++++++ tests/cases/compiler/tupleLength.ts | 18 ++++++++ .../types/typeAliases/genericTypeAliases.ts | 4 +- .../nominalSubtypeCheckOfTypeParameter.ts | 10 ++-- 27 files changed, 185 insertions(+), 69 deletions(-) create mode 100644 tests/baselines/reference/transpile/Supports setting strictTuples.js create mode 100644 tests/baselines/reference/tupleLength.errors.txt create mode 100644 tests/baselines/reference/tupleLength.js create mode 100644 tests/cases/compiler/tupleLength.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 90328770750..d533f5f82fb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -64,6 +64,7 @@ namespace ts { const noUnusedIdentifiers = !!compilerOptions.noUnusedLocals || !!compilerOptions.noUnusedParameters; const allowSyntheticDefaultImports = typeof compilerOptions.allowSyntheticDefaultImports !== "undefined" ? compilerOptions.allowSyntheticDefaultImports : modulekind === ModuleKind.System; const strictNullChecks = compilerOptions.strictNullChecks === undefined ? compilerOptions.strict : compilerOptions.strictNullChecks; + const strictTuples = compilerOptions.strictTuples === undefined ? compilerOptions.strict : compilerOptions.strictTuples; const noImplicitAny = compilerOptions.noImplicitAny === undefined ? compilerOptions.strict : compilerOptions.noImplicitAny; const noImplicitThis = compilerOptions.noImplicitThis === undefined ? compilerOptions.strict : compilerOptions.noImplicitThis; @@ -7161,6 +7162,12 @@ namespace ts { property.type = typeParameter; properties.push(property); } + if (strictTuples) { + const lengthSymbol = createSymbol(SymbolFlags.Property, "length" as __String); + lengthSymbol.type = getLiteralType(arity); + lengthSymbol.checkFlags = CheckFlags.Readonly; + properties.push(lengthSymbol); + } const type = createObjectType(ObjectFlags.Tuple | ObjectFlags.Reference); type.typeParameters = typeParameters; type.outerTypeParameters = undefined; diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index c92d147f9a9..f6baca68647 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -269,6 +269,13 @@ namespace ts { category: Diagnostics.Strict_Type_Checking_Options, description: Diagnostics.Enable_strict_null_checks }, + { + name: "strictTuples", + type: "boolean", + showInSimplifiedHelpView: true, + category: Diagnostics.Strict_Type_Checking_Options, + description: Diagnostics.Enable_strict_tuple_checks + }, { name: "noImplicitThis", type: "boolean", diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 77e7f7e7b62..bda14f2c9ce 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3302,6 +3302,10 @@ "category": "Message", "code": 6185 }, + "Enable strict tuple checks.": { + "category": "Message", + "code": 6187 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 0a09bb5b6ec..bc06d247f2c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3622,6 +3622,7 @@ namespace ts { sourceRoot?: string; strict?: boolean; strictNullChecks?: boolean; // Always combine with strict property + strictTuples?: boolean; /* @internal */ stripInternal?: boolean; suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; diff --git a/src/harness/unittests/configurationExtension.ts b/src/harness/unittests/configurationExtension.ts index 2d50d2cb2af..776feb535c5 100644 --- a/src/harness/unittests/configurationExtension.ts +++ b/src/harness/unittests/configurationExtension.ts @@ -16,6 +16,12 @@ namespace ts { strictNullChecks: false } }, + "/dev/tsconfig.strictTuples.json": { + extends: "./tsconfig", + compilerOptions: { + strictTuples: false + } + }, "/dev/configs/base.json": { compilerOptions: { allowJs: true, diff --git a/src/harness/unittests/transpile.ts b/src/harness/unittests/transpile.ts index e0c96797827..f727fff5594 100644 --- a/src/harness/unittests/transpile.ts +++ b/src/harness/unittests/transpile.ts @@ -413,6 +413,10 @@ var x = 0;`, { options: { compilerOptions: { strictNullChecks: true }, fileName: "input.js", reportDiagnostics: true } }); + transpilesCorrectly("Supports setting 'strictTuples'", "x;", { + options: { compilerOptions: { strictTuples: true }, fileName: "input.js", reportDiagnostics: true } + }); + transpilesCorrectly("Supports setting 'stripInternal'", "x;", { options: { compilerOptions: { stripInternal: true }, fileName: "input.js", reportDiagnostics: true } }); diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 0b7405c7b69..b5c959b484f 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -2448,6 +2448,7 @@ namespace ts.server.protocol { sourceRoot?: string; strict?: boolean; strictNullChecks?: boolean; + strictTuples?: boolean; suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; target?: ScriptTarget | ts.ScriptTarget; diff --git a/tests/baselines/reference/genericTypeAliases.js b/tests/baselines/reference/genericTypeAliases.js index 8218f5c886c..282fd9868a9 100644 --- a/tests/baselines/reference/genericTypeAliases.js +++ b/tests/baselines/reference/genericTypeAliases.js @@ -40,12 +40,12 @@ type Strange = string; // Type parameter not used var s: Strange; s = "hello"; -interface Tuple { +interface AB { a: A; b: B; } -type Pair = Tuple; +type Pair = AB; interface TaggedPair extends Pair { tag: string; diff --git a/tests/baselines/reference/genericTypeAliases.symbols b/tests/baselines/reference/genericTypeAliases.symbols index d5f68ec0615..521afe800b3 100644 --- a/tests/baselines/reference/genericTypeAliases.symbols +++ b/tests/baselines/reference/genericTypeAliases.symbols @@ -124,29 +124,29 @@ var s: Strange; s = "hello"; >s : Symbol(s, Decl(genericTypeAliases.ts, 38, 3)) -interface Tuple { ->Tuple : Symbol(Tuple, Decl(genericTypeAliases.ts, 39, 12)) ->A : Symbol(A, Decl(genericTypeAliases.ts, 41, 16)) ->B : Symbol(B, Decl(genericTypeAliases.ts, 41, 18)) +interface AB { +>AB : Symbol(AB, Decl(genericTypeAliases.ts, 39, 12)) +>A : Symbol(A, Decl(genericTypeAliases.ts, 41, 13)) +>B : Symbol(B, Decl(genericTypeAliases.ts, 41, 15)) a: A; ->a : Symbol(Tuple.a, Decl(genericTypeAliases.ts, 41, 23)) ->A : Symbol(A, Decl(genericTypeAliases.ts, 41, 16)) +>a : Symbol(AB.a, Decl(genericTypeAliases.ts, 41, 20)) +>A : Symbol(A, Decl(genericTypeAliases.ts, 41, 13)) b: B; ->b : Symbol(Tuple.b, Decl(genericTypeAliases.ts, 42, 9)) ->B : Symbol(B, Decl(genericTypeAliases.ts, 41, 18)) +>b : Symbol(AB.b, Decl(genericTypeAliases.ts, 42, 9)) +>B : Symbol(B, Decl(genericTypeAliases.ts, 41, 15)) } -type Pair = Tuple; +type Pair = AB; >Pair : Symbol(Pair, Decl(genericTypeAliases.ts, 44, 1)) >T : Symbol(T, Decl(genericTypeAliases.ts, 46, 10)) ->Tuple : Symbol(Tuple, Decl(genericTypeAliases.ts, 39, 12)) +>AB : Symbol(AB, Decl(genericTypeAliases.ts, 39, 12)) >T : Symbol(T, Decl(genericTypeAliases.ts, 46, 10)) >T : Symbol(T, Decl(genericTypeAliases.ts, 46, 10)) interface TaggedPair extends Pair { ->TaggedPair : Symbol(TaggedPair, Decl(genericTypeAliases.ts, 46, 27)) +>TaggedPair : Symbol(TaggedPair, Decl(genericTypeAliases.ts, 46, 24)) >T : Symbol(T, Decl(genericTypeAliases.ts, 48, 21)) >Pair : Symbol(Pair, Decl(genericTypeAliases.ts, 44, 1)) >T : Symbol(T, Decl(genericTypeAliases.ts, 48, 21)) @@ -157,17 +157,17 @@ interface TaggedPair extends Pair { var p: TaggedPair; >p : Symbol(p, Decl(genericTypeAliases.ts, 52, 3)) ->TaggedPair : Symbol(TaggedPair, Decl(genericTypeAliases.ts, 46, 27)) +>TaggedPair : Symbol(TaggedPair, Decl(genericTypeAliases.ts, 46, 24)) p.a = 1; ->p.a : Symbol(Tuple.a, Decl(genericTypeAliases.ts, 41, 23)) +>p.a : Symbol(AB.a, Decl(genericTypeAliases.ts, 41, 20)) >p : Symbol(p, Decl(genericTypeAliases.ts, 52, 3)) ->a : Symbol(Tuple.a, Decl(genericTypeAliases.ts, 41, 23)) +>a : Symbol(AB.a, Decl(genericTypeAliases.ts, 41, 20)) p.b = 2; ->p.b : Symbol(Tuple.b, Decl(genericTypeAliases.ts, 42, 9)) +>p.b : Symbol(AB.b, Decl(genericTypeAliases.ts, 42, 9)) >p : Symbol(p, Decl(genericTypeAliases.ts, 52, 3)) ->b : Symbol(Tuple.b, Decl(genericTypeAliases.ts, 42, 9)) +>b : Symbol(AB.b, Decl(genericTypeAliases.ts, 42, 9)) p.tag = "test"; >p.tag : Symbol(TaggedPair.tag, Decl(genericTypeAliases.ts, 48, 41)) diff --git a/tests/baselines/reference/genericTypeAliases.types b/tests/baselines/reference/genericTypeAliases.types index b4c75841245..722347b0f72 100644 --- a/tests/baselines/reference/genericTypeAliases.types +++ b/tests/baselines/reference/genericTypeAliases.types @@ -158,8 +158,8 @@ s = "hello"; >s : string >"hello" : "hello" -interface Tuple { ->Tuple : Tuple +interface AB { +>AB : AB >A : A >B : B @@ -172,17 +172,17 @@ interface Tuple { >B : B } -type Pair = Tuple; ->Pair : Tuple +type Pair = AB; +>Pair : AB >T : T ->Tuple : Tuple +>AB : AB >T : T >T : T interface TaggedPair extends Pair { >TaggedPair : TaggedPair >T : T ->Pair : Tuple +>Pair : AB >T : T tag: string; diff --git a/tests/baselines/reference/nominalSubtypeCheckOfTypeParameter.js b/tests/baselines/reference/nominalSubtypeCheckOfTypeParameter.js index 3259b3287fa..5712fb7c244 100644 --- a/tests/baselines/reference/nominalSubtypeCheckOfTypeParameter.js +++ b/tests/baselines/reference/nominalSubtypeCheckOfTypeParameter.js @@ -1,20 +1,20 @@ //// [nominalSubtypeCheckOfTypeParameter.ts] -interface Tuple { +interface BinaryTuple { first: T - second: S + second: S } interface Sequence { hasNext(): boolean - pop(): T - zip(seq: Sequence): Sequence> + pop(): T + zip(seq: Sequence): Sequence> } // error, despite the fact that the code explicitly says List extends Sequence, the current rules for infinitely expanding type references // perform nominal subtyping checks that allow variance for type arguments, but not nominal subtyping for the generic type itself interface List extends Sequence { getLength(): number - zip(seq: Sequence): List> + zip(seq: Sequence): List> } diff --git a/tests/baselines/reference/nominalSubtypeCheckOfTypeParameter.symbols b/tests/baselines/reference/nominalSubtypeCheckOfTypeParameter.symbols index c7d9a1b50f4..3d24b82aa8f 100644 --- a/tests/baselines/reference/nominalSubtypeCheckOfTypeParameter.symbols +++ b/tests/baselines/reference/nominalSubtypeCheckOfTypeParameter.symbols @@ -1,16 +1,16 @@ === tests/cases/conformance/types/typeRelationships/recursiveTypes/nominalSubtypeCheckOfTypeParameter.ts === -interface Tuple { ->Tuple : Symbol(Tuple, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 0)) ->T : Symbol(T, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 16)) ->S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 18)) +interface BinaryTuple { +>BinaryTuple : Symbol(BinaryTuple, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 0)) +>T : Symbol(T, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 22)) +>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 24)) first: T ->first : Symbol(Tuple.first, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 23)) ->T : Symbol(T, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 16)) +>first : Symbol(BinaryTuple.first, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 29)) +>T : Symbol(T, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 22)) - second: S ->second : Symbol(Tuple.second, Decl(nominalSubtypeCheckOfTypeParameter.ts, 1, 12)) ->S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 18)) + second: S +>second : Symbol(BinaryTuple.second, Decl(nominalSubtypeCheckOfTypeParameter.ts, 1, 12)) +>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 24)) } interface Sequence { @@ -20,20 +20,20 @@ interface Sequence { hasNext(): boolean >hasNext : Symbol(Sequence.hasNext, Decl(nominalSubtypeCheckOfTypeParameter.ts, 5, 23)) - pop(): T + pop(): T >pop : Symbol(Sequence.pop, Decl(nominalSubtypeCheckOfTypeParameter.ts, 6, 22)) >T : Symbol(T, Decl(nominalSubtypeCheckOfTypeParameter.ts, 5, 19)) - zip(seq: Sequence): Sequence> ->zip : Symbol(Sequence.zip, Decl(nominalSubtypeCheckOfTypeParameter.ts, 7, 14)) ->S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 8, 10)) ->seq : Symbol(seq, Decl(nominalSubtypeCheckOfTypeParameter.ts, 8, 13)) + zip(seq: Sequence): Sequence> +>zip : Symbol(Sequence.zip, Decl(nominalSubtypeCheckOfTypeParameter.ts, 7, 12)) +>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 8, 8)) +>seq : Symbol(seq, Decl(nominalSubtypeCheckOfTypeParameter.ts, 8, 11)) >Sequence : Symbol(Sequence, Decl(nominalSubtypeCheckOfTypeParameter.ts, 3, 1)) ->S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 8, 10)) +>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 8, 8)) >Sequence : Symbol(Sequence, Decl(nominalSubtypeCheckOfTypeParameter.ts, 3, 1)) ->Tuple : Symbol(Tuple, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 0)) +>BinaryTuple : Symbol(BinaryTuple, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 0)) >T : Symbol(T, Decl(nominalSubtypeCheckOfTypeParameter.ts, 5, 19)) ->S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 8, 10)) +>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 8, 8)) } // error, despite the fact that the code explicitly says List extends Sequence, the current rules for infinitely expanding type references @@ -47,15 +47,15 @@ interface List extends Sequence { getLength(): number >getLength : Symbol(List.getLength, Decl(nominalSubtypeCheckOfTypeParameter.ts, 13, 39)) - zip(seq: Sequence): List> + zip(seq: Sequence): List> >zip : Symbol(List.zip, Decl(nominalSubtypeCheckOfTypeParameter.ts, 14, 23)) ->S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 15, 10)) ->seq : Symbol(seq, Decl(nominalSubtypeCheckOfTypeParameter.ts, 15, 13)) +>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 15, 8)) +>seq : Symbol(seq, Decl(nominalSubtypeCheckOfTypeParameter.ts, 15, 11)) >Sequence : Symbol(Sequence, Decl(nominalSubtypeCheckOfTypeParameter.ts, 3, 1)) ->S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 15, 10)) +>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 15, 8)) >List : Symbol(List, Decl(nominalSubtypeCheckOfTypeParameter.ts, 9, 1)) ->Tuple : Symbol(Tuple, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 0)) +>BinaryTuple : Symbol(BinaryTuple, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 0)) >T : Symbol(T, Decl(nominalSubtypeCheckOfTypeParameter.ts, 13, 15)) ->S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 15, 10)) +>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 15, 8)) } diff --git a/tests/baselines/reference/nominalSubtypeCheckOfTypeParameter.types b/tests/baselines/reference/nominalSubtypeCheckOfTypeParameter.types index 79b2ac77d78..5da84d0c8a4 100644 --- a/tests/baselines/reference/nominalSubtypeCheckOfTypeParameter.types +++ b/tests/baselines/reference/nominalSubtypeCheckOfTypeParameter.types @@ -1,6 +1,6 @@ === tests/cases/conformance/types/typeRelationships/recursiveTypes/nominalSubtypeCheckOfTypeParameter.ts === -interface Tuple { ->Tuple : Tuple +interface BinaryTuple { +>BinaryTuple : BinaryTuple >T : T >S : S @@ -8,7 +8,7 @@ interface Tuple { >first : T >T : T - second: S + second: S >second : S >S : S } @@ -20,18 +20,18 @@ interface Sequence { hasNext(): boolean >hasNext : () => boolean - pop(): T + pop(): T >pop : () => T >T : T - zip(seq: Sequence): Sequence> ->zip : (seq: Sequence) => Sequence> + zip(seq: Sequence): Sequence> +>zip : (seq: Sequence) => Sequence> >S : S >seq : Sequence >Sequence : Sequence >S : S >Sequence : Sequence ->Tuple : Tuple +>BinaryTuple : BinaryTuple >T : T >S : S } @@ -47,14 +47,14 @@ interface List extends Sequence { getLength(): number >getLength : () => number - zip(seq: Sequence): List> ->zip : (seq: Sequence) => List> + zip(seq: Sequence): List> +>zip : (seq: Sequence) => List> >S : S >seq : Sequence >Sequence : Sequence >S : S >List : List ->Tuple : Tuple +>BinaryTuple : BinaryTuple >T : T >S : S } diff --git a/tests/baselines/reference/transpile/Supports setting strictTuples.js b/tests/baselines/reference/transpile/Supports setting strictTuples.js new file mode 100644 index 00000000000..8394371f908 --- /dev/null +++ b/tests/baselines/reference/transpile/Supports setting strictTuples.js @@ -0,0 +1,2 @@ +x; +//# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json index 0f5b2378468..5218d687724 100644 --- a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json @@ -22,6 +22,7 @@ "strict": true /* Enable all strict type-checking options. */ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictTuples": true, /* Enable strict tuple checks. */ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json index a545124a723..4fc67f07f0e 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json @@ -22,6 +22,7 @@ "strict": true, /* Enable all strict type-checking options. */ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictTuples": true, /* Enable strict tuple checks. */ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json index b53ac2d8552..cd190298fd8 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json @@ -22,6 +22,7 @@ "strict": true /* Enable all strict type-checking options. */ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictTuples": true, /* Enable strict tuple checks. */ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json index 4e06e06d159..278322852f8 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json @@ -22,6 +22,7 @@ "strict": true /* Enable all strict type-checking options. */ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictTuples": true, /* Enable strict tuple checks. */ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json index 94808d89ed0..c81634bccea 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json @@ -22,6 +22,7 @@ "strict": true /* Enable all strict type-checking options. */ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictTuples": true, /* Enable strict tuple checks. */ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json index 0f5b2378468..5218d687724 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json @@ -22,6 +22,7 @@ "strict": true /* Enable all strict type-checking options. */ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictTuples": true, /* Enable strict tuple checks. */ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json index d165b0f2775..0b34f4724f8 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json @@ -22,6 +22,7 @@ "strict": true /* Enable all strict type-checking options. */ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictTuples": true, /* Enable strict tuple checks. */ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json index 2a169b3aaaf..9a63db2069b 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json @@ -22,6 +22,7 @@ "strict": true, /* Enable all strict type-checking options. */ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictTuples": true, /* Enable strict tuple checks. */ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ diff --git a/tests/baselines/reference/tupleLength.errors.txt b/tests/baselines/reference/tupleLength.errors.txt new file mode 100644 index 00000000000..c68bd652c85 --- /dev/null +++ b/tests/baselines/reference/tupleLength.errors.txt @@ -0,0 +1,26 @@ +tests/cases/compiler/tupleLength.ts(11,5): error TS2403: Subsequent variable declarations must have the same type. Variable 't1' must be of type '[number]', but here has type '[number, number]'. +tests/cases/compiler/tupleLength.ts(12,5): error TS2403: Subsequent variable declarations must have the same type. Variable 't2' must be of type '[number, number]', but here has type '[number]'. + + +==== tests/cases/compiler/tupleLength.ts (2 errors) ==== + // var t0: []; + var t1: [number]; + var t2: [number, number]; + var arr: number[]; + + // var len0: 0 = t0.length; + var len1: 1 = t1.length; + var len2: 2 = t2.length; + var lena: number = arr.length; + + var t1 = t2; // error + ~~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 't1' must be of type '[number]', but here has type '[number, number]'. + var t2 = t1; // error + ~~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 't2' must be of type '[number, number]', but here has type '[number]'. + + type A = T['length']; + var b: A<[boolean]>; + var c: 1 = b; + \ No newline at end of file diff --git a/tests/baselines/reference/tupleLength.js b/tests/baselines/reference/tupleLength.js new file mode 100644 index 00000000000..3893305421b --- /dev/null +++ b/tests/baselines/reference/tupleLength.js @@ -0,0 +1,32 @@ +//// [tupleLength.ts] +// var t0: []; +var t1: [number]; +var t2: [number, number]; +var arr: number[]; + +// var len0: 0 = t0.length; +var len1: 1 = t1.length; +var len2: 2 = t2.length; +var lena: number = arr.length; + +var t1 = t2; // error +var t2 = t1; // error + +type A = T['length']; +var b: A<[boolean]>; +var c: 1 = b; + + +//// [tupleLength.js] +// var t0: []; +var t1; +var t2; +var arr; +// var len0: 0 = t0.length; +var len1 = t1.length; +var len2 = t2.length; +var lena = arr.length; +var t1 = t2; // error +var t2 = t1; // error +var b; +var c = b; diff --git a/tests/cases/compiler/tupleLength.ts b/tests/cases/compiler/tupleLength.ts new file mode 100644 index 00000000000..3c6db1a034a --- /dev/null +++ b/tests/cases/compiler/tupleLength.ts @@ -0,0 +1,18 @@ +// @strictTuples: true + +// var t0: []; +var t1: [number]; +var t2: [number, number]; +var arr: number[]; + +// var len0: 0 = t0.length; +var len1: 1 = t1.length; +var len2: 2 = t2.length; +var lena: number = arr.length; + +var t1 = t2; // error +var t2 = t1; // error + +type A = T['length']; +var b: A<[boolean]>; +var c: 1 = b; diff --git a/tests/cases/conformance/types/typeAliases/genericTypeAliases.ts b/tests/cases/conformance/types/typeAliases/genericTypeAliases.ts index e26279a8a41..8c8ab3291fa 100644 --- a/tests/cases/conformance/types/typeAliases/genericTypeAliases.ts +++ b/tests/cases/conformance/types/typeAliases/genericTypeAliases.ts @@ -39,12 +39,12 @@ type Strange = string; // Type parameter not used var s: Strange; s = "hello"; -interface Tuple { +interface AB { a: A; b: B; } -type Pair = Tuple; +type Pair = AB; interface TaggedPair extends Pair { tag: string; diff --git a/tests/cases/conformance/types/typeRelationships/recursiveTypes/nominalSubtypeCheckOfTypeParameter.ts b/tests/cases/conformance/types/typeRelationships/recursiveTypes/nominalSubtypeCheckOfTypeParameter.ts index ed8d724300d..ea16201ae91 100644 --- a/tests/cases/conformance/types/typeRelationships/recursiveTypes/nominalSubtypeCheckOfTypeParameter.ts +++ b/tests/cases/conformance/types/typeRelationships/recursiveTypes/nominalSubtypeCheckOfTypeParameter.ts @@ -1,17 +1,17 @@ -interface Tuple { +interface BinaryTuple { first: T - second: S + second: S } interface Sequence { hasNext(): boolean - pop(): T - zip(seq: Sequence): Sequence> + pop(): T + zip(seq: Sequence): Sequence> } // error, despite the fact that the code explicitly says List extends Sequence, the current rules for infinitely expanding type references // perform nominal subtyping checks that allow variance for type arguments, but not nominal subtyping for the generic type itself interface List extends Sequence { getLength(): number - zip(seq: Sequence): List> + zip(seq: Sequence): List> } From ff0961b85e33f6dd6f876df5c5ed2777ea309bde Mon Sep 17 00:00:00 2001 From: Yuval Greenfield Date: Fri, 8 Sep 2017 15:02:59 -0700 Subject: [PATCH 007/405] Remove trailing space from emitLeadingComment This will prevent emiting an extraneous trailing space on comments to match https://eslint.org/docs/rules/no-trailing-spaces This also removes a space that may have been originally there after a comment but isn't necessary syntactically. --- src/compiler/comments.ts | 3 --- .../baselines/reference/ambientDeclarationsExternal.js | 2 +- tests/baselines/reference/anyAssignableToEveryType.js | 2 +- tests/baselines/reference/augmentedTypesClass3.js | 2 +- tests/baselines/reference/augmentedTypesEnum.js | 2 +- tests/baselines/reference/augmentedTypesEnum2.js | 2 +- tests/baselines/reference/augmentedTypesFunction.js | 2 +- tests/baselines/reference/augmentedTypesInterface.js | 2 +- .../reference/baseIndexSignatureResolution.js | 2 +- tests/baselines/reference/commentEmitAtEndOfFile1.js | 2 +- .../reference/commentEmitWithCommentOnLastLine.js | 2 +- tests/baselines/reference/commentOnArrayElement1.js | 2 +- tests/baselines/reference/commentOnArrayElement3.js | 4 ++-- tests/baselines/reference/commentOnBlock1.js | 2 +- .../reference/commentsArgumentsOfCallExpression1.js | 2 +- .../reference/commentsArgumentsOfCallExpression2.js | 6 +++--- tests/baselines/reference/commentsCommentParsing.js | 10 +++++----- tests/baselines/reference/commentsFunction.js | 4 ++-- .../reference/commentsOnPropertyOfObjectLiteral1.js | 2 +- ...mparisonOperatorWithSubtypeObjectOnCallSignature.js | 2 +- ...nOperatorWithSubtypeObjectOnConstructorSignature.js | 2 +- ...atorWithSubtypeObjectOnInstantiatedCallSignature.js | 2 +- ...hSubtypeObjectOnInstantiatedConstructorSignature.js | 2 +- tests/baselines/reference/concatError.js | 2 +- tests/baselines/reference/errorSupression1.js | 2 +- tests/baselines/reference/everyTypeAssignableToAny.js | 2 +- .../reference/functionConstraintSatisfaction.js | 2 +- .../genericCallWithObjectTypeArgsAndNumericIndexer.js | 2 +- .../genericCallWithObjectTypeArgsAndStringIndexer.js | 2 +- .../baselines/reference/heterogeneousArrayLiterals.js | 2 +- .../reference/innerTypeParameterShadowingOuterOne.js | 2 +- .../reference/innerTypeParameterShadowingOuterOne2.js | 2 +- .../reference/literalsInComputedProperties1.js | 2 +- tests/baselines/reference/moduleIdentifiers.js | 2 +- .../reference/moduleResolutionWithExtensions.js | 4 ++-- tests/baselines/reference/nullAssignableToEveryType.js | 2 +- tests/baselines/reference/parserSkippedTokens10.js | 2 +- .../recursivelySpecializedConstructorDeclaration.js | 2 +- tests/baselines/reference/scannerS7.4_A2_T2.js | 2 +- tests/baselines/reference/sourceMap-Comment1.js | 2 +- .../reference/sourceMap-Comment1.sourcemap.txt | 2 +- .../reference/systemDefaultExportCommentValidity.js | 2 +- .../reference/systemModuleTrailingComments.js | 2 +- .../typeParameterUsedAsTypeParameterConstraint3.js | 2 +- .../reference/undefinedAssignableToEveryType.js | 2 +- 45 files changed, 53 insertions(+), 56 deletions(-) diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index 025a4f36d26..b936c0655e1 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -274,9 +274,6 @@ namespace ts { if (hasTrailingNewLine) { writer.writeLine(); } - else { - writer.write(" "); - } } function emitLeadingCommentsOfPosition(pos: number) { diff --git a/tests/baselines/reference/ambientDeclarationsExternal.js b/tests/baselines/reference/ambientDeclarationsExternal.js index fb531586467..ed413fb0d8e 100644 --- a/tests/baselines/reference/ambientDeclarationsExternal.js +++ b/tests/baselines/reference/ambientDeclarationsExternal.js @@ -24,7 +24,7 @@ var n: number; //// [decls.js] -// Ambient external import declaration referencing ambient external module using top level module name +// Ambient external import declaration referencing ambient external module using top level module name //// [consumer.js] "use strict"; exports.__esModule = true; diff --git a/tests/baselines/reference/anyAssignableToEveryType.js b/tests/baselines/reference/anyAssignableToEveryType.js index d6b2303de48..eff97905e4f 100644 --- a/tests/baselines/reference/anyAssignableToEveryType.js +++ b/tests/baselines/reference/anyAssignableToEveryType.js @@ -87,4 +87,4 @@ function foo(x, y, z) { // x = a; // y = a; // z = a; -//} +//} diff --git a/tests/baselines/reference/augmentedTypesClass3.js b/tests/baselines/reference/augmentedTypesClass3.js index d2ad63161b5..045109f8587 100644 --- a/tests/baselines/reference/augmentedTypesClass3.js +++ b/tests/baselines/reference/augmentedTypesClass3.js @@ -46,4 +46,4 @@ var c5c = /** @class */ (function () { c5c.prototype.foo = function () { }; return c5c; }()); -//import c5c = require(''); +//import c5c = require(''); diff --git a/tests/baselines/reference/augmentedTypesEnum.js b/tests/baselines/reference/augmentedTypesEnum.js index ff0ad93f817..edd4a92d767 100644 --- a/tests/baselines/reference/augmentedTypesEnum.js +++ b/tests/baselines/reference/augmentedTypesEnum.js @@ -100,4 +100,4 @@ var e6b; })(e6b || (e6b = {})); // should be error // enum then import, messes with error reporting //enum e7 { One } -//import e7 = require(''); // should be error +//import e7 = require(''); // should be error diff --git a/tests/baselines/reference/augmentedTypesEnum2.js b/tests/baselines/reference/augmentedTypesEnum2.js index 66fc96b62a0..0e6e70df263 100644 --- a/tests/baselines/reference/augmentedTypesEnum2.js +++ b/tests/baselines/reference/augmentedTypesEnum2.js @@ -41,4 +41,4 @@ var e2 = /** @class */ (function () { return e2; }()); //enum then enum - covered -//enum then import - covered +//enum then import - covered diff --git a/tests/baselines/reference/augmentedTypesFunction.js b/tests/baselines/reference/augmentedTypesFunction.js index 3c6066e5bb4..a2dd4a664a3 100644 --- a/tests/baselines/reference/augmentedTypesFunction.js +++ b/tests/baselines/reference/augmentedTypesFunction.js @@ -79,4 +79,4 @@ function y5b() { } function y5c() { } // function then import, messes with other errors //function y6() { } -//import y6 = require(''); +//import y6 = require(''); diff --git a/tests/baselines/reference/augmentedTypesInterface.js b/tests/baselines/reference/augmentedTypesInterface.js index b74da5bbfee..0409e157584 100644 --- a/tests/baselines/reference/augmentedTypesInterface.js +++ b/tests/baselines/reference/augmentedTypesInterface.js @@ -48,4 +48,4 @@ var i3; i3[i3["One"] = 0] = "One"; })(i3 || (i3 = {})); ; // error -//import i4 = require(''); // error +//import i4 = require(''); // error diff --git a/tests/baselines/reference/baseIndexSignatureResolution.js b/tests/baselines/reference/baseIndexSignatureResolution.js index 4053e588e44..3fdeecf78f6 100644 --- a/tests/baselines/reference/baseIndexSignatureResolution.js +++ b/tests/baselines/reference/baseIndexSignatureResolution.js @@ -59,4 +59,4 @@ interface B extends A { } var b: B = null; var z: Derived = b.foo(); -*/ +*/ diff --git a/tests/baselines/reference/commentEmitAtEndOfFile1.js b/tests/baselines/reference/commentEmitAtEndOfFile1.js index 1be031fa84a..d6ba7b158d6 100644 --- a/tests/baselines/reference/commentEmitAtEndOfFile1.js +++ b/tests/baselines/reference/commentEmitAtEndOfFile1.js @@ -18,4 +18,4 @@ var foo; (function (foo) { function bar() { } })(foo || (foo = {})); -// test #4 +// test #4 diff --git a/tests/baselines/reference/commentEmitWithCommentOnLastLine.js b/tests/baselines/reference/commentEmitWithCommentOnLastLine.js index ffd4addb264..077286a7364 100644 --- a/tests/baselines/reference/commentEmitWithCommentOnLastLine.js +++ b/tests/baselines/reference/commentEmitWithCommentOnLastLine.js @@ -8,4 +8,4 @@ var bar; var x; /* var bar; -*/ +*/ diff --git a/tests/baselines/reference/commentOnArrayElement1.js b/tests/baselines/reference/commentOnArrayElement1.js index 960df336dbb..c93cf634096 100644 --- a/tests/baselines/reference/commentOnArrayElement1.js +++ b/tests/baselines/reference/commentOnArrayElement1.js @@ -11,7 +11,7 @@ var array = [ var array = [ /* element 1*/ 1 - /* end of element 1 */ , + /* end of element 1 */, 2 /* end of element 2 */ ]; diff --git a/tests/baselines/reference/commentOnArrayElement3.js b/tests/baselines/reference/commentOnArrayElement3.js index e31f8adf26a..f19ef5d6050 100644 --- a/tests/baselines/reference/commentOnArrayElement3.js +++ b/tests/baselines/reference/commentOnArrayElement3.js @@ -12,8 +12,8 @@ var array = [ var array = [ /* element 1*/ 1 - /* end of element 1 */ , + /* end of element 1 */, 2 - /* end of element 2 */ , + /* end of element 2 */, , ]; diff --git a/tests/baselines/reference/commentOnBlock1.js b/tests/baselines/reference/commentOnBlock1.js index ed5437c1f66..20df3764b77 100644 --- a/tests/baselines/reference/commentOnBlock1.js +++ b/tests/baselines/reference/commentOnBlock1.js @@ -7,5 +7,5 @@ function f() { //// [commentOnBlock1.js] // asdf function f() { - /*asdf*/ { } + /*asdf*/{ } } diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression1.js b/tests/baselines/reference/commentsArgumentsOfCallExpression1.js index 4e6d693c5c2..f32e0bb8098 100644 --- a/tests/baselines/reference/commentsArgumentsOfCallExpression1.js +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression1.js @@ -29,4 +29,4 @@ function () { }); foo(/*c7*/ function () { }); foo( /*c7*/ -/*c8*/ function () { }); +/*c8*/function () { }); diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression2.js b/tests/baselines/reference/commentsArgumentsOfCallExpression2.js index f89e67ef3d8..1e1079a4d22 100644 --- a/tests/baselines/reference/commentsArgumentsOfCallExpression2.js +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression2.js @@ -17,7 +17,7 @@ foo(/*c2*/ 1, /*d2*/ 1 + 2, /*e1*/ a + b); foo(/*c3*/ function () { }, /*d2*/ function () { }, /*e2*/ a + /*e3*/ b); foo(/*c3*/ function () { }, /*d3*/ function () { }, /*e3*/ (a + b)); foo( -/*c4*/ function () { }, -/*d4*/ function () { }, +/*c4*/function () { }, +/*d4*/function () { }, /*e4*/ -/*e5*/ "hello"); +/*e5*/"hello"); diff --git a/tests/baselines/reference/commentsCommentParsing.js b/tests/baselines/reference/commentsCommentParsing.js index 889067a3c05..c39bf05e556 100644 --- a/tests/baselines/reference/commentsCommentParsing.js +++ b/tests/baselines/reference/commentsCommentParsing.js @@ -178,7 +178,7 @@ jsDocMultiLine(); *New line1 *New Line2*/ /** Shoul mege this line as well -* and this too*/ /** Another this one too*/ +* and this too*//** Another this one too*/ function jsDocMultiLineMerge() { } jsDocMultiLineMerge(); @@ -188,23 +188,23 @@ function jsDocMixedComments1() { } jsDocMixedComments1(); /// Triple slash comment -/** jsdoc comment */ /*** another jsDocComment*/ +/** jsdoc comment *//*** another jsDocComment*/ function jsDocMixedComments2() { } jsDocMixedComments2(); -/** jsdoc comment */ /*** another jsDocComment*/ +/** jsdoc comment *//*** another jsDocComment*/ /// Triple slash comment function jsDocMixedComments3() { } jsDocMixedComments3(); -/** jsdoc comment */ /*** another jsDocComment*/ +/** jsdoc comment *//*** another jsDocComment*/ /// Triple slash comment /// Triple slash comment 2 function jsDocMixedComments4() { } jsDocMixedComments4(); /// Triple slash comment 1 -/** jsdoc comment */ /*** another jsDocComment*/ +/** jsdoc comment *//*** another jsDocComment*/ /// Triple slash comment /// Triple slash comment 2 function jsDocMixedComments5() { diff --git a/tests/baselines/reference/commentsFunction.js b/tests/baselines/reference/commentsFunction.js index ad31aa47b91..a02ffb3b364 100644 --- a/tests/baselines/reference/commentsFunction.js +++ b/tests/baselines/reference/commentsFunction.js @@ -86,8 +86,8 @@ function blah3(a // trailing commen single line ) { } lambdaFoo = function (a, b) { return a * b; }; // This is trailing comment -/*leading comment*/ (function () { return 0; }); // Needs to be wrapped in parens to be a valid expression (not declaration) -/*leading comment*/ (function () { return 0; }); //trailing comment +/*leading comment*/(function () { return 0; }); // Needs to be wrapped in parens to be a valid expression (not declaration) +/*leading comment*/(function () { return 0; }); //trailing comment function blah4(/*1*/ a /*2*/, /*3*/ b /*4*/) { } function foo1() { diff --git a/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js index fa7790443ac..39190d9173a 100644 --- a/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js +++ b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js @@ -18,7 +18,7 @@ var resolve = { id: /*! @ngInject */ function (details) { return details.id; }, id1: /* c1 */ "hello", id2: - /*! @ngInject */ function (details) { return details.id; }, + /*! @ngInject */function (details) { return details.id; }, id3: /*! @ngInject */ function (details) { return details.id; }, diff --git a/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnCallSignature.js b/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnCallSignature.js index 079a1e276fb..bcd87998f83 100644 --- a/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnCallSignature.js +++ b/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnCallSignature.js @@ -505,4 +505,4 @@ var r8b8 = b8 !== a8; var r8b9 = b9 !== a9; var r8b10 = b10 !== a10; var r8b11 = b11 !== a11; -//var r8b12 = b12 !== a12; +//var r8b12 = b12 !== a12; diff --git a/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnConstructorSignature.js b/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnConstructorSignature.js index 38097a936e3..1721f564865 100644 --- a/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnConstructorSignature.js +++ b/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnConstructorSignature.js @@ -431,4 +431,4 @@ var r8b6 = b6 !== a6; var r8b7 = b7 !== a7; var r8b8 = b8 !== a8; var r8b9 = b9 !== a9; -//var r8b10 = b10 !== a10; +//var r8b10 = b10 !== a10; diff --git a/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnInstantiatedCallSignature.js b/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnInstantiatedCallSignature.js index 87359ea0074..72dd4be0afc 100644 --- a/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnInstantiatedCallSignature.js +++ b/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnInstantiatedCallSignature.js @@ -320,4 +320,4 @@ var r8b3 = b3 !== a3; var r8b4 = b4 !== a4; var r8b5 = b5 !== a5; var r8b6 = b6 !== a6; -//var r8b7 = b7 !== a7; +//var r8b7 = b7 !== a7; diff --git a/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnInstantiatedConstructorSignature.js b/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnInstantiatedConstructorSignature.js index fcfbfa4bfbc..19183773406 100644 --- a/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnInstantiatedConstructorSignature.js +++ b/tests/baselines/reference/comparisonOperatorWithSubtypeObjectOnInstantiatedConstructorSignature.js @@ -320,4 +320,4 @@ var r8b3 = b3 !== a3; var r8b4 = b4 !== a4; var r8b5 = b5 !== a5; var r8b6 = b6 !== a6; -//var r8b7 = b7 !== a7; +//var r8b7 = b7 !== a7; diff --git a/tests/baselines/reference/concatError.js b/tests/baselines/reference/concatError.js index 67361719702..d2b30218e50 100644 --- a/tests/baselines/reference/concatError.js +++ b/tests/baselines/reference/concatError.js @@ -56,4 +56,4 @@ var c: C; var cc: C>; c = c.m(cc); -*/ +*/ diff --git a/tests/baselines/reference/errorSupression1.js b/tests/baselines/reference/errorSupression1.js index 2f467871434..4b635a0d660 100644 --- a/tests/baselines/reference/errorSupression1.js +++ b/tests/baselines/reference/errorSupression1.js @@ -17,4 +17,4 @@ var Foo = /** @class */ (function () { var baz = Foo.b; // Foo.b won't bind. baz.concat("y"); -// So we don't want an error on 'concat'. +// So we don't want an error on 'concat'. diff --git a/tests/baselines/reference/everyTypeAssignableToAny.js b/tests/baselines/reference/everyTypeAssignableToAny.js index 7f02badca00..fd71ec624be 100644 --- a/tests/baselines/reference/everyTypeAssignableToAny.js +++ b/tests/baselines/reference/everyTypeAssignableToAny.js @@ -117,4 +117,4 @@ function foo(x, y, z) { // a = x; // a = y; // a = z; -//} +//} diff --git a/tests/baselines/reference/functionConstraintSatisfaction.js b/tests/baselines/reference/functionConstraintSatisfaction.js index fc8a2be88a7..f24fd32aff6 100644 --- a/tests/baselines/reference/functionConstraintSatisfaction.js +++ b/tests/baselines/reference/functionConstraintSatisfaction.js @@ -108,4 +108,4 @@ function foo2(x, y) { //function foo2(x: T, y: U) { // foo(x); // foo(y); -//} +//} diff --git a/tests/baselines/reference/genericCallWithObjectTypeArgsAndNumericIndexer.js b/tests/baselines/reference/genericCallWithObjectTypeArgsAndNumericIndexer.js index f300e3a8093..27e4093d9c7 100644 --- a/tests/baselines/reference/genericCallWithObjectTypeArgsAndNumericIndexer.js +++ b/tests/baselines/reference/genericCallWithObjectTypeArgsAndNumericIndexer.js @@ -63,4 +63,4 @@ function other3(arg) { // var d = r2[1]; // // BUG 821629 // //var u: U = r2[1]; // ok -//} +//} diff --git a/tests/baselines/reference/genericCallWithObjectTypeArgsAndStringIndexer.js b/tests/baselines/reference/genericCallWithObjectTypeArgsAndStringIndexer.js index eee87caf3de..ee33746b152 100644 --- a/tests/baselines/reference/genericCallWithObjectTypeArgsAndStringIndexer.js +++ b/tests/baselines/reference/genericCallWithObjectTypeArgsAndStringIndexer.js @@ -64,4 +64,4 @@ function other3(arg) { // var d: Date = r2['hm']; // ok // // BUG 821629 // //var u: U = r2['hm']; // ok -//} +//} diff --git a/tests/baselines/reference/heterogeneousArrayLiterals.js b/tests/baselines/reference/heterogeneousArrayLiterals.js index 499aa7e7818..46dee284ae9 100644 --- a/tests/baselines/reference/heterogeneousArrayLiterals.js +++ b/tests/baselines/reference/heterogeneousArrayLiterals.js @@ -268,4 +268,4 @@ function foo4(t, u) { // var i = [u, base]; // Base[] // var j = [u, derived]; // Derived[] // var k: Base[] = [t, u]; -//} +//} diff --git a/tests/baselines/reference/innerTypeParameterShadowingOuterOne.js b/tests/baselines/reference/innerTypeParameterShadowingOuterOne.js index 74354468e32..f566bbdd878 100644 --- a/tests/baselines/reference/innerTypeParameterShadowingOuterOne.js +++ b/tests/baselines/reference/innerTypeParameterShadowingOuterOne.js @@ -54,4 +54,4 @@ function f2() { // } // var x: U; // x.getDate(); -//} +//} diff --git a/tests/baselines/reference/innerTypeParameterShadowingOuterOne2.js b/tests/baselines/reference/innerTypeParameterShadowingOuterOne2.js index 984584389f6..824061fce1f 100644 --- a/tests/baselines/reference/innerTypeParameterShadowingOuterOne2.js +++ b/tests/baselines/reference/innerTypeParameterShadowingOuterOne2.js @@ -75,4 +75,4 @@ var C2 = /** @class */ (function () { // var x: U; // x.getDate(); // } -//} +//} diff --git a/tests/baselines/reference/literalsInComputedProperties1.js b/tests/baselines/reference/literalsInComputedProperties1.js index c5b0060f626..4611925f2d4 100644 --- a/tests/baselines/reference/literalsInComputedProperties1.js +++ b/tests/baselines/reference/literalsInComputedProperties1.js @@ -89,4 +89,4 @@ var X; var a = X["foo"]; var a0 = X["bar"]; var _a; -// TODO: make sure that enum still disallow template literals as member names +// TODO: make sure that enum still disallow template literals as member names diff --git a/tests/baselines/reference/moduleIdentifiers.js b/tests/baselines/reference/moduleIdentifiers.js index 04d39019482..d3a654b8670 100644 --- a/tests/baselines/reference/moduleIdentifiers.js +++ b/tests/baselines/reference/moduleIdentifiers.js @@ -19,4 +19,4 @@ var M; //var m: M = M; var x1 = M.a; //var x2 = m.a; -//var q: m.P; +//var q: m.P; diff --git a/tests/baselines/reference/moduleResolutionWithExtensions.js b/tests/baselines/reference/moduleResolutionWithExtensions.js index c1e0310e995..3406bb0adae 100644 --- a/tests/baselines/reference/moduleResolutionWithExtensions.js +++ b/tests/baselines/reference/moduleResolutionWithExtensions.js @@ -28,11 +28,11 @@ import j from "./jquery.js" "use strict"; exports.__esModule = true; exports["default"] = 0; -// No extension: '.ts' added +// No extension: '.ts' added //// [b.js] "use strict"; exports.__esModule = true; -// '.js' extension: stripped and replaced with '.ts' +// '.js' extension: stripped and replaced with '.ts' //// [d.js] "use strict"; exports.__esModule = true; diff --git a/tests/baselines/reference/nullAssignableToEveryType.js b/tests/baselines/reference/nullAssignableToEveryType.js index f04ae865692..50914b366f8 100644 --- a/tests/baselines/reference/nullAssignableToEveryType.js +++ b/tests/baselines/reference/nullAssignableToEveryType.js @@ -84,4 +84,4 @@ function foo(x, y, z) { // x = null; // y = null; // z = null; -//} +//} diff --git a/tests/baselines/reference/parserSkippedTokens10.js b/tests/baselines/reference/parserSkippedTokens10.js index cfacb2e21bd..3af628a2e1e 100644 --- a/tests/baselines/reference/parserSkippedTokens10.js +++ b/tests/baselines/reference/parserSkippedTokens10.js @@ -5,4 +5,4 @@ //// [parserSkippedTokens10.js] -/*existing trivia*/ ; +/*existing trivia*/; diff --git a/tests/baselines/reference/recursivelySpecializedConstructorDeclaration.js b/tests/baselines/reference/recursivelySpecializedConstructorDeclaration.js index beff303c540..dbf4b6b27d1 100644 --- a/tests/baselines/reference/recursivelySpecializedConstructorDeclaration.js +++ b/tests/baselines/reference/recursivelySpecializedConstructorDeclaration.js @@ -78,4 +78,4 @@ declare module MsPortal.Controls.Base.ItemList { class ViewModel extends ItemValue { } } -*/ +*/ diff --git a/tests/baselines/reference/scannerS7.4_A2_T2.js b/tests/baselines/reference/scannerS7.4_A2_T2.js index 9cfc0b03bd8..4a446b520ad 100644 --- a/tests/baselines/reference/scannerS7.4_A2_T2.js +++ b/tests/baselines/reference/scannerS7.4_A2_T2.js @@ -26,4 +26,4 @@ */ /*CHECK#1/ - + diff --git a/tests/baselines/reference/sourceMap-Comment1.js b/tests/baselines/reference/sourceMap-Comment1.js index 071e54b5716..6f1f43cd8e2 100644 --- a/tests/baselines/reference/sourceMap-Comment1.js +++ b/tests/baselines/reference/sourceMap-Comment1.js @@ -2,5 +2,5 @@ // Comment //// [sourceMap-Comment1.js] -// Comment +// Comment //# sourceMappingURL=sourceMap-Comment1.js.map \ No newline at end of file diff --git a/tests/baselines/reference/sourceMap-Comment1.sourcemap.txt b/tests/baselines/reference/sourceMap-Comment1.sourcemap.txt index 4d427d1de89..e2f9174a45f 100644 --- a/tests/baselines/reference/sourceMap-Comment1.sourcemap.txt +++ b/tests/baselines/reference/sourceMap-Comment1.sourcemap.txt @@ -8,7 +8,7 @@ sources: sourceMap-Comment1.ts emittedFile:tests/cases/compiler/sourceMap-Comment1.js sourceFile:sourceMap-Comment1.ts ------------------------------------------------------------------- ->>>// Comment +>>>// Comment 1 > 2 >^^^^^^^^^^ 3 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> diff --git a/tests/baselines/reference/systemDefaultExportCommentValidity.js b/tests/baselines/reference/systemDefaultExportCommentValidity.js index a56110b0de9..45fe1df3ccd 100644 --- a/tests/baselines/reference/systemDefaultExportCommentValidity.js +++ b/tests/baselines/reference/systemDefaultExportCommentValidity.js @@ -14,7 +14,7 @@ System.register([], function (exports_1, context_1) { execute: function () { Home = {}; exports_1("default", Home); - // There is intentionally no semicolon on the prior line, this comment should not break emit + // There is intentionally no semicolon on the prior line, this comment should not break emit } }; }); diff --git a/tests/baselines/reference/systemModuleTrailingComments.js b/tests/baselines/reference/systemModuleTrailingComments.js index 41b0bd299a0..01f17d1facf 100644 --- a/tests/baselines/reference/systemModuleTrailingComments.js +++ b/tests/baselines/reference/systemModuleTrailingComments.js @@ -12,7 +12,7 @@ System.register([], function (exports_1, context_1) { setters: [], execute: function () { exports_1("test", test = "TEST"); - //some comment + //some comment } }; }); diff --git a/tests/baselines/reference/typeParameterUsedAsTypeParameterConstraint3.js b/tests/baselines/reference/typeParameterUsedAsTypeParameterConstraint3.js index 95c65d5f3a9..0655ad17138 100644 --- a/tests/baselines/reference/typeParameterUsedAsTypeParameterConstraint3.js +++ b/tests/baselines/reference/typeParameterUsedAsTypeParameterConstraint3.js @@ -64,4 +64,4 @@ interface I2 { // y: U; // z: V; // foo(x: W): T; -//} +//} diff --git a/tests/baselines/reference/undefinedAssignableToEveryType.js b/tests/baselines/reference/undefinedAssignableToEveryType.js index 507f647763a..de64f97f70b 100644 --- a/tests/baselines/reference/undefinedAssignableToEveryType.js +++ b/tests/baselines/reference/undefinedAssignableToEveryType.js @@ -83,4 +83,4 @@ function foo(x, y, z) { // x = undefined; // y = undefined; // z = undefined; -//} +//} From 262d7bd53bda077786341c9cd3ad912d0f4f5eb0 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Tue, 19 Sep 2017 16:23:45 -0700 Subject: [PATCH 008/405] revert method rename --- src/services/formatting/smartIndenter.ts | 2 +- src/services/services.ts | 2 +- src/services/textChanges.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index b04369f30ae..fac61be45d5 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -23,7 +23,7 @@ namespace ts.formatting { * When inserting some text after an open brace, we would like to get indentation as if a newline was already there. * By default indentation at `position` will be 0 so 'assumeNewLineBeforeCloseBrace' overrides this behavior. */ - export function getIndentationAtPosition(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number { + export function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number { if (position > sourceFile.text.length) { return getBaseIndentation(options); // past EOF } diff --git a/src/services/services.ts b/src/services/services.ts index 4008d4382fc..90f9acd82ea 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1772,7 +1772,7 @@ namespace ts { start = timestamp(); - const result = formatting.SmartIndenter.getIndentationAtPosition(position, sourceFile, settings); + const result = formatting.SmartIndenter.getIndentation(position, sourceFile, settings); log("getIndentationAtPosition: computeIndentation : " + (timestamp() - start)); return result; diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 8883724f698..b4a2d3e07e2 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -557,7 +557,7 @@ namespace ts.textChanges { options.indentation !== undefined ? options.indentation : (options.useIndentationFromFile !== false) - ? formatting.SmartIndenter.getIndentationAtPosition(pos, sourceFile, formatOptions, posStartsLine || (options.prefix === this.newLineCharacter)) + ? formatting.SmartIndenter.getIndentation(pos, sourceFile, formatOptions, posStartsLine || (options.prefix === this.newLineCharacter)) : 0; const delta = options.delta !== undefined From e3a720f863fc353b6ec8c77aee5470cd1011a3d8 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Tue, 19 Sep 2017 16:25:06 -0700 Subject: [PATCH 009/405] explain changes and remove spurious assignment --- src/services/formatting/smartIndenter.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index fac61be45d5..7701cff182c 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -202,7 +202,14 @@ namespace ts.formatting { indentationDelta += options.indentSize; } - // Update `current` and `parent`. + // In our AST, a call argument's `parent` is the call-expression, not the argument list. + // We would like to increase indentation based on the relationship between an argument and its argument-list, + // so we spoof the starting position of the (parent) call-expression to match the (non-parent) argument-list. + // But, the spoofed start-value could then cause a problem when comparing the start position of the call-expression + // to *its* parent (in the case of an iife, an expression statement), adding an extra level of indentation. + // + // Instead, when at an argument, we unspoof the starting position of the enclosing call expression + // *after* applying indentation for the argument. const useTrueStart = isArgumentAndStartLineOverlapsExpressionBeingCalled(parent, current, currentStart.line, sourceFile); @@ -210,7 +217,6 @@ namespace ts.formatting { current = parent; parent = current.parent; currentStart = useTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart()) : containingListOrParentStart; - containingListOrParentStart = undefined; } return indentationDelta + getBaseIndentation(options); From 4b464ebca887d5bdf69968c8f46c7c888c97be59 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Tue, 19 Sep 2017 17:56:34 -0700 Subject: [PATCH 010/405] add tests * verified that new tests show no regressions against master --- tests/cases/fourslash/indentationInArrays.ts | 21 +++++++++++ .../fourslash/indentationInAssignment.ts | 37 +++++++++++++++++++ .../indentationInAsyncExpressions.ts | 16 ++++++++ .../fourslash/indentationInClassExpression.ts | 31 ++++++++++++++++ tests/cases/fourslash/indentationInObject.ts | 30 +++++++++++++++ 5 files changed, 135 insertions(+) create mode 100644 tests/cases/fourslash/indentationInArrays.ts create mode 100644 tests/cases/fourslash/indentationInAssignment.ts create mode 100644 tests/cases/fourslash/indentationInAsyncExpressions.ts create mode 100644 tests/cases/fourslash/indentationInClassExpression.ts create mode 100644 tests/cases/fourslash/indentationInObject.ts diff --git a/tests/cases/fourslash/indentationInArrays.ts b/tests/cases/fourslash/indentationInArrays.ts new file mode 100644 index 00000000000..9468ff43a08 --- /dev/null +++ b/tests/cases/fourslash/indentationInArrays.ts @@ -0,0 +1,21 @@ +/// + +//// function foo() { +//// [/*8_0*/1,2,3]; +//// [1/*8_1*/,2,3]; +//// [1,/*8_2*/2,3]; +//// [ +//// 1,/*8_3*/2,3]; +//// [1,2,3/*8_4*/]; +//// [ +//// 1,2,3/*8_5*/]; +//// [1,2,3]/*8_6*/; +//// [ +//// 1,2,3]/*8_7*/; +//// } + +for (let i = 0; i < 8; ++i) { + goTo.marker(`8_${i}`); + edit.insertLine(""); + verify.indentationIs(8); +} diff --git a/tests/cases/fourslash/indentationInAssignment.ts b/tests/cases/fourslash/indentationInAssignment.ts new file mode 100644 index 00000000000..253cb30cf38 --- /dev/null +++ b/tests/cases/fourslash/indentationInAssignment.ts @@ -0,0 +1,37 @@ +/// + +//// var v0 = /*4_0*/ +//// 1; +//// +//// let v1 = 1 /*4_1*/ +//// + 10; +//// +//// let v2 = 1 + /*4_2*/ +//// 1; +//// +//// let v3 = 1 + (function /*0_0*/(x: number, y: number) { return x || y; })(0, 1); +//// +//// let v4 = 1 + (function (x: number, /*4_3*/y: number) { return x || y; })(0, 1); +//// +//// let v5 = 1 + (function (x: number, y: number) { /*4_4*/return x || y; })(0, 1); +//// +//// let v6 = 1 + (function (x: number, y: number) { return x || y;/*0_1*/})(0, 1); +//// +//// let v7 = 1 + (function (x: number, y: number) { +//// return x || y;/*4_5*/ +//// })(0, 1); +//// +//// let v8 = 1 + (function (x: number, y: number) { return x || y; })(0, /*4_6*/1); + + +for (let i = 0; i < 2; ++i) { + goTo.marker(`0_${i}`); + edit.insertLine(""); + verify.indentationIs(0); +} + +for (let i = 0; i < 7; ++i) { + goTo.marker(`4_${i}`); + edit.insertLine(""); + verify.indentationIs(4); +} \ No newline at end of file diff --git a/tests/cases/fourslash/indentationInAsyncExpressions.ts b/tests/cases/fourslash/indentationInAsyncExpressions.ts new file mode 100644 index 00000000000..5273dcbd97a --- /dev/null +++ b/tests/cases/fourslash/indentationInAsyncExpressions.ts @@ -0,0 +1,16 @@ +/// + + +//// async function* foo() { +//// yield /*8_0*/await 1; +//// yield await /*8_1*/1; +//// yield +//// await /*8_2*/1; +//// yield await 1/*8_3*/; +//// } + +for (let i = 0; i < 4; ++i) { + goTo.marker(`8_${i}`); + edit.insertLine(""); + verify.indentationIs(8); +} \ No newline at end of file diff --git a/tests/cases/fourslash/indentationInClassExpression.ts b/tests/cases/fourslash/indentationInClassExpression.ts new file mode 100644 index 00000000000..77ac668790a --- /dev/null +++ b/tests/cases/fourslash/indentationInClassExpression.ts @@ -0,0 +1,31 @@ +/// + +////function foo() { +//// let x: any; +//// x = /*8_0*/class { constructor(public x: number) { } }; +//// x = class /*4_0*/{ constructor(public x: number) { } }; +//// x = class { /*8_1*/constructor(public x: number) { } }; +//// x = class { constructor(/*12_0*/public x: number) { } }; +//// x = class { constructor(public /*12_1*/x: number) { } }; +//// x = class { constructor(public x: number) {/*8_2*/ } }; +//// x = class { +//// constructor(/*12_2*/public x: number) { } +//// }; +//// x = class { +//// constructor(public x: number) {/*8_3*/ } +//// }; +//// x = class { +//// constructor(public x: number) { }/*4_1*/}; +////} + +function verifyIndentation(level: number, count: number) { + for (let i = 0; i < count; ++i) { + goTo.marker(`${level}_${i}`); + edit.insertLine(""); + verify.indentationIs(level); + } +} + +verifyIndentation(4, 2); +verifyIndentation(8, 4); +verifyIndentation(12, 3); \ No newline at end of file diff --git a/tests/cases/fourslash/indentationInObject.ts b/tests/cases/fourslash/indentationInObject.ts new file mode 100644 index 00000000000..2acb651c933 --- /dev/null +++ b/tests/cases/fourslash/indentationInObject.ts @@ -0,0 +1,30 @@ +/// + +//// function foo() { +//// {/*8_0*/x:1;y:2;z:3}; +//// {x:1/*12_0*/;y:2;z:3}; +//// {x:1;/*8_1*/y:2;z:3}; +//// { +//// x:1;/*8_2*/y:2;z:3}; +//// {x:1;y:2;z:3/*4_0*/}; +//// { +//// x:1;y:2;z:3/*4_1*/}; +//// {x:1;y:2;z:3}/*4_2*/; +//// { +//// x:1;y:2;z:3}/*4_3*/; +//// } + +for (let i = 0; i < 4; ++i) { + goTo.marker(`4_${i}`); + edit.insertLine(""); + verify.indentationIs(4); +} +for (let i = 0; i < 3; ++i) { + goTo.marker(`8_${i}`); + edit.insertLine(""); + verify.indentationIs(8); +} + + goTo.marker(`12_0`); + edit.insertLine(""); + verify.indentationIs(12); From cc8770390c8419a14d8563407a368a6f63eb3aef Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Wed, 20 Sep 2017 10:23:45 -0700 Subject: [PATCH 011/405] remove newline --- src/services/textChanges.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index b4a2d3e07e2..f3ad7df1607 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -553,7 +553,6 @@ namespace ts.textChanges { const posStartsLine = getLineStartPositionForPosition(pos, sourceFile) === pos; const initialIndentation = - options.indentation !== undefined ? options.indentation : (options.useIndentationFromFile !== false) From dcd2ddd0b71f6682c3d020ada0e9ac482b9b3d33 Mon Sep 17 00:00:00 2001 From: Yuval Greenfield Date: Tue, 26 Sep 2017 12:09:58 -0700 Subject: [PATCH 012/405] Yes space after multiline comments --- src/compiler/comments.ts | 3 +++ .../reference/baseIndexSignatureResolution.js | 2 +- .../reference/commentEmitWithCommentOnLastLine.js | 2 +- tests/baselines/reference/commentOnArrayElement1.js | 2 +- tests/baselines/reference/commentOnArrayElement3.js | 4 ++-- tests/baselines/reference/commentOnBlock1.js | 2 +- .../reference/commentsArgumentsOfCallExpression1.js | 2 +- .../reference/commentsArgumentsOfCallExpression2.js | 6 +++--- tests/baselines/reference/commentsCommentParsing.js | 10 +++++----- tests/baselines/reference/commentsFunction.js | 4 ++-- .../reference/commentsOnPropertyOfObjectLiteral1.js | 2 +- tests/baselines/reference/concatError.js | 2 +- tests/baselines/reference/parserSkippedTokens10.js | 2 +- .../recursivelySpecializedConstructorDeclaration.js | 2 +- tests/baselines/reference/scannerS7.4_A2_T2.js | 2 +- 15 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index b936c0655e1..bb8ec9bf3e7 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -274,6 +274,9 @@ namespace ts { if (hasTrailingNewLine) { writer.writeLine(); } + else if (_kind === SyntaxKind.MultiLineCommentTrivia) { + writer.write(" "); + } } function emitLeadingCommentsOfPosition(pos: number) { diff --git a/tests/baselines/reference/baseIndexSignatureResolution.js b/tests/baselines/reference/baseIndexSignatureResolution.js index 3fdeecf78f6..4053e588e44 100644 --- a/tests/baselines/reference/baseIndexSignatureResolution.js +++ b/tests/baselines/reference/baseIndexSignatureResolution.js @@ -59,4 +59,4 @@ interface B extends A { } var b: B = null; var z: Derived = b.foo(); -*/ +*/ diff --git a/tests/baselines/reference/commentEmitWithCommentOnLastLine.js b/tests/baselines/reference/commentEmitWithCommentOnLastLine.js index 077286a7364..ffd4addb264 100644 --- a/tests/baselines/reference/commentEmitWithCommentOnLastLine.js +++ b/tests/baselines/reference/commentEmitWithCommentOnLastLine.js @@ -8,4 +8,4 @@ var bar; var x; /* var bar; -*/ +*/ diff --git a/tests/baselines/reference/commentOnArrayElement1.js b/tests/baselines/reference/commentOnArrayElement1.js index c93cf634096..960df336dbb 100644 --- a/tests/baselines/reference/commentOnArrayElement1.js +++ b/tests/baselines/reference/commentOnArrayElement1.js @@ -11,7 +11,7 @@ var array = [ var array = [ /* element 1*/ 1 - /* end of element 1 */, + /* end of element 1 */ , 2 /* end of element 2 */ ]; diff --git a/tests/baselines/reference/commentOnArrayElement3.js b/tests/baselines/reference/commentOnArrayElement3.js index f19ef5d6050..e31f8adf26a 100644 --- a/tests/baselines/reference/commentOnArrayElement3.js +++ b/tests/baselines/reference/commentOnArrayElement3.js @@ -12,8 +12,8 @@ var array = [ var array = [ /* element 1*/ 1 - /* end of element 1 */, + /* end of element 1 */ , 2 - /* end of element 2 */, + /* end of element 2 */ , , ]; diff --git a/tests/baselines/reference/commentOnBlock1.js b/tests/baselines/reference/commentOnBlock1.js index 20df3764b77..ed5437c1f66 100644 --- a/tests/baselines/reference/commentOnBlock1.js +++ b/tests/baselines/reference/commentOnBlock1.js @@ -7,5 +7,5 @@ function f() { //// [commentOnBlock1.js] // asdf function f() { - /*asdf*/{ } + /*asdf*/ { } } diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression1.js b/tests/baselines/reference/commentsArgumentsOfCallExpression1.js index f32e0bb8098..4e6d693c5c2 100644 --- a/tests/baselines/reference/commentsArgumentsOfCallExpression1.js +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression1.js @@ -29,4 +29,4 @@ function () { }); foo(/*c7*/ function () { }); foo( /*c7*/ -/*c8*/function () { }); +/*c8*/ function () { }); diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression2.js b/tests/baselines/reference/commentsArgumentsOfCallExpression2.js index 1e1079a4d22..f89e67ef3d8 100644 --- a/tests/baselines/reference/commentsArgumentsOfCallExpression2.js +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression2.js @@ -17,7 +17,7 @@ foo(/*c2*/ 1, /*d2*/ 1 + 2, /*e1*/ a + b); foo(/*c3*/ function () { }, /*d2*/ function () { }, /*e2*/ a + /*e3*/ b); foo(/*c3*/ function () { }, /*d3*/ function () { }, /*e3*/ (a + b)); foo( -/*c4*/function () { }, -/*d4*/function () { }, +/*c4*/ function () { }, +/*d4*/ function () { }, /*e4*/ -/*e5*/"hello"); +/*e5*/ "hello"); diff --git a/tests/baselines/reference/commentsCommentParsing.js b/tests/baselines/reference/commentsCommentParsing.js index c39bf05e556..889067a3c05 100644 --- a/tests/baselines/reference/commentsCommentParsing.js +++ b/tests/baselines/reference/commentsCommentParsing.js @@ -178,7 +178,7 @@ jsDocMultiLine(); *New line1 *New Line2*/ /** Shoul mege this line as well -* and this too*//** Another this one too*/ +* and this too*/ /** Another this one too*/ function jsDocMultiLineMerge() { } jsDocMultiLineMerge(); @@ -188,23 +188,23 @@ function jsDocMixedComments1() { } jsDocMixedComments1(); /// Triple slash comment -/** jsdoc comment *//*** another jsDocComment*/ +/** jsdoc comment */ /*** another jsDocComment*/ function jsDocMixedComments2() { } jsDocMixedComments2(); -/** jsdoc comment *//*** another jsDocComment*/ +/** jsdoc comment */ /*** another jsDocComment*/ /// Triple slash comment function jsDocMixedComments3() { } jsDocMixedComments3(); -/** jsdoc comment *//*** another jsDocComment*/ +/** jsdoc comment */ /*** another jsDocComment*/ /// Triple slash comment /// Triple slash comment 2 function jsDocMixedComments4() { } jsDocMixedComments4(); /// Triple slash comment 1 -/** jsdoc comment *//*** another jsDocComment*/ +/** jsdoc comment */ /*** another jsDocComment*/ /// Triple slash comment /// Triple slash comment 2 function jsDocMixedComments5() { diff --git a/tests/baselines/reference/commentsFunction.js b/tests/baselines/reference/commentsFunction.js index a02ffb3b364..ad31aa47b91 100644 --- a/tests/baselines/reference/commentsFunction.js +++ b/tests/baselines/reference/commentsFunction.js @@ -86,8 +86,8 @@ function blah3(a // trailing commen single line ) { } lambdaFoo = function (a, b) { return a * b; }; // This is trailing comment -/*leading comment*/(function () { return 0; }); // Needs to be wrapped in parens to be a valid expression (not declaration) -/*leading comment*/(function () { return 0; }); //trailing comment +/*leading comment*/ (function () { return 0; }); // Needs to be wrapped in parens to be a valid expression (not declaration) +/*leading comment*/ (function () { return 0; }); //trailing comment function blah4(/*1*/ a /*2*/, /*3*/ b /*4*/) { } function foo1() { diff --git a/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js index 39190d9173a..fa7790443ac 100644 --- a/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js +++ b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js @@ -18,7 +18,7 @@ var resolve = { id: /*! @ngInject */ function (details) { return details.id; }, id1: /* c1 */ "hello", id2: - /*! @ngInject */function (details) { return details.id; }, + /*! @ngInject */ function (details) { return details.id; }, id3: /*! @ngInject */ function (details) { return details.id; }, diff --git a/tests/baselines/reference/concatError.js b/tests/baselines/reference/concatError.js index d2b30218e50..67361719702 100644 --- a/tests/baselines/reference/concatError.js +++ b/tests/baselines/reference/concatError.js @@ -56,4 +56,4 @@ var c: C; var cc: C>; c = c.m(cc); -*/ +*/ diff --git a/tests/baselines/reference/parserSkippedTokens10.js b/tests/baselines/reference/parserSkippedTokens10.js index 3af628a2e1e..cfacb2e21bd 100644 --- a/tests/baselines/reference/parserSkippedTokens10.js +++ b/tests/baselines/reference/parserSkippedTokens10.js @@ -5,4 +5,4 @@ //// [parserSkippedTokens10.js] -/*existing trivia*/; +/*existing trivia*/ ; diff --git a/tests/baselines/reference/recursivelySpecializedConstructorDeclaration.js b/tests/baselines/reference/recursivelySpecializedConstructorDeclaration.js index dbf4b6b27d1..beff303c540 100644 --- a/tests/baselines/reference/recursivelySpecializedConstructorDeclaration.js +++ b/tests/baselines/reference/recursivelySpecializedConstructorDeclaration.js @@ -78,4 +78,4 @@ declare module MsPortal.Controls.Base.ItemList { class ViewModel extends ItemValue { } } -*/ +*/ diff --git a/tests/baselines/reference/scannerS7.4_A2_T2.js b/tests/baselines/reference/scannerS7.4_A2_T2.js index 4a446b520ad..9cfc0b03bd8 100644 --- a/tests/baselines/reference/scannerS7.4_A2_T2.js +++ b/tests/baselines/reference/scannerS7.4_A2_T2.js @@ -26,4 +26,4 @@ */ /*CHECK#1/ - + From 405d8cf8ebd3f6c9c2a5f7e19c2a687235ec0a18 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 9 Oct 2017 10:45:50 -0700 Subject: [PATCH 013/405] In getSuggestionForNonexistentSymbol, guard name against undefined --- src/compiler/checker.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a8e18c432a6..738a484d254 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15064,7 +15064,10 @@ namespace ts { function getSuggestionForNonexistentSymbol(location: Node, name: __String, meaning: SymbolFlags): string { const result = resolveNameHelper(location, name, meaning, /*nameNotFoundMessage*/ undefined, name, /*isUse*/ false, (symbols, name, meaning) => { - // `name` from the callback === the outer `name` + // NOTE: `name` from the callback is supposed to === the outer `name`, but is undefined in some cases + if (name === undefined) { + return undefined; + } const symbol = getSymbol(symbols, name, meaning); // Sometimes the symbol is found when location is a return type of a function: `typeof x` and `x` is declared in the body of the function // So the table *contains* `x` but `x` isn't actually in scope. From 412e31b8bc99472c17641bb12f65efd349a93cb8 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 11 Oct 2017 17:10:45 -0700 Subject: [PATCH 014/405] Adding test case where opened file included in project is not added to ref count of configured project --- .../unittests/tsserverProjectSystem.ts | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 236f52db134..40eef501e52 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -335,6 +335,10 @@ namespace ts.projectSystem { return countWhere(recursiveWatchedDirs, dir => file.length > dir.length && startsWith(file, dir) && file[dir.length] === directorySeparator); } + function checkOpenFiles(projectService: server.ProjectService, expectedFiles: FileOrFolder[]) { + checkFileNames("Open files", projectService.openFiles.map(info => info.fileName), expectedFiles.map(file => file.path)); + } + /** * Test server cancellation token used to mock host token cancellation requests. * The cancelAfterRequest constructor param specifies how many isCancellationRequested() calls @@ -2109,6 +2113,90 @@ namespace ts.projectSystem { assert.equal(project1.openRefCount, 1, "Open ref count in project1 - 5"); }); + it("Open ref of configured project when open file gets added to the project as part of configured file update", () => { + const file1 = { + path: "/a/b/src/file1.ts", + content: "let x = 1;" + }; + const file2 = { + path: "/a/b/src/file2.ts", + content: "let y = 1;" + }; + const file3 = { + path: "/a/b/file3.ts", + content: "let z = 1;" + }; + const file4 = { + path: "/a/file4.ts", + content: "let z = 1;" + }; + const configFile = { + path: "/a/b/tsconfig.json", + content: JSON.stringify({ files: ["src/file1.ts", "file3.ts"] }) + }; + + const files = [file1, file2, file3, file4]; + const host = createServerHost(files.concat(configFile)); + const projectService = createProjectService(host); + + projectService.openClientFile(file1.path); + projectService.openClientFile(file2.path); + projectService.openClientFile(file3.path); + projectService.openClientFile(file4.path); + + const infos = files.map(file => projectService.getScriptInfoForPath(file.path as Path)); + checkOpenFiles(projectService, files); + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); + const configProject1 = projectService.configuredProjects.get(configFile.path); + assert.equal(configProject1.openRefCount, 2); + checkProjectActualFiles(configProject1, [file1.path, file3.path, configFile.path]); + const inferredProject1 = projectService.inferredProjects[0]; + checkProjectActualFiles(inferredProject1, [file2.path]); + const inferredProject2 = projectService.inferredProjects[1]; + checkProjectActualFiles(inferredProject2, [file4.path]); + + configFile.content = "{}"; + host.reloadFS(files.concat(configFile)); + host.runQueuedTimeoutCallbacks(); + + verifyScriptInfos(); + checkOpenFiles(projectService, files); + verifyConfiguredProjectStateAfterUpdate(3); + checkNumberOfInferredProjects(projectService, 1); + const inferredProject3 = projectService.inferredProjects[0]; + checkProjectActualFiles(inferredProject3, [file4.path]); + assert.strictEqual(inferredProject2, inferredProject3); + + projectService.closeClientFile(file1.path); + projectService.closeClientFile(file2.path); + projectService.closeClientFile(file4.path); + + verifyScriptInfos(); + checkOpenFiles(projectService, [file3]); + verifyConfiguredProjectStateAfterUpdate(1); + checkNumberOfInferredProjects(projectService, 0); + + projectService.openClientFile(file4.path); + //verifyScriptInfos(); + checkOpenFiles(projectService, [file3, file4]); + //verifyConfiguredProjectStateAfterUpdate(1); + checkNumberOfInferredProjects(projectService, 1); + const inferredProject4 = projectService.inferredProjects[0]; + checkProjectActualFiles(inferredProject4, [file4.path]); + + function verifyScriptInfos() { + infos.forEach(info => assert.strictEqual(projectService.getScriptInfoForPath(info.path), info)); + } + + function verifyConfiguredProjectStateAfterUpdate(_openRefCount: number) { + checkNumberOfConfiguredProjects(projectService, 1); + const configProject2 = projectService.configuredProjects.get(configFile.path); + assert.strictEqual(configProject1, configProject2); + checkProjectActualFiles(configProject2, [file1.path, file2.path, file3.path, configFile.path]); + //assert.equal(configProject2.openRefCount, openRefCount); + } + }); + it("language service disabled state is updated in external projects", () => { const f1 = { path: "/a/app.js", From b68a6363480409067e244da35b1372868947e17b Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 12 Oct 2017 11:48:25 -0700 Subject: [PATCH 015/405] Fix the way configured project's reference is managed so that the open file --- .../unittests/tsserverProjectSystem.ts | 186 +++++++++++++++--- src/server/editorServices.ts | 55 +++--- src/server/project.ts | 48 +++-- .../reference/api/tsserverlibrary.d.ts | 10 +- 4 files changed, 224 insertions(+), 75 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 40eef501e52..dfed47084e0 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -1053,16 +1053,19 @@ namespace ts.projectSystem { projectService.openClientFile(file1.path); checkNumberOfConfiguredProjects(projectService, 1); const project = projectService.configuredProjects.get(configFile.path); + assert.isTrue(project.hasOpenRef()); // file1 projectService.closeClientFile(file1.path); checkNumberOfConfiguredProjects(projectService, 1); assert.strictEqual(projectService.configuredProjects.get(configFile.path), project); - assert.equal(project.openRefCount, 0); + assert.isFalse(project.hasOpenRef()); // No open files + assert.isFalse(project.isClosed()); projectService.openClientFile(file2.path); checkNumberOfConfiguredProjects(projectService, 1); assert.strictEqual(projectService.configuredProjects.get(configFile.path), project); - assert.equal(project.openRefCount, 1); + assert.isTrue(project.hasOpenRef()); // file2 + assert.isFalse(project.isClosed()); }); it("should not close configured project after closing last open file, but should be closed on next file open if its not the file from same project", () => { @@ -1084,14 +1087,18 @@ namespace ts.projectSystem { projectService.openClientFile(file1.path); checkNumberOfConfiguredProjects(projectService, 1); const project = projectService.configuredProjects.get(configFile.path); + assert.isTrue(project.hasOpenRef()); // file1 projectService.closeClientFile(file1.path); checkNumberOfConfiguredProjects(projectService, 1); assert.strictEqual(projectService.configuredProjects.get(configFile.path), project); - assert.equal(project.openRefCount, 0); + assert.isFalse(project.hasOpenRef()); // No files + assert.isFalse(project.isClosed()); projectService.openClientFile(libFile.path); checkNumberOfConfiguredProjects(projectService, 0); + assert.isFalse(project.hasOpenRef()); // No files + project closed + assert.isTrue(project.isClosed()); }); it("should not close external project with no open files", () => { @@ -2078,55 +2085,64 @@ namespace ts.projectSystem { projectService.openClientFile(file2.path); checkNumberOfProjects(projectService, { configuredProjects: 1 }); const project1 = projectService.configuredProjects.get(tsconfig1.path); - assert.equal(project1.openRefCount, 1, "Open ref count in project1 - 1"); + assert.isTrue(project1.hasOpenRef(), "Has open ref count in project1 - 1"); // file2 assert.equal(project1.getScriptInfo(file2.path).containingProjects.length, 1, "containing projects count"); + assert.isFalse(project1.isClosed()); projectService.openClientFile(file1.path); checkNumberOfProjects(projectService, { configuredProjects: 2 }); - assert.equal(project1.openRefCount, 2, "Open ref count in project1 - 2"); + assert.isTrue(project1.hasOpenRef(), "Has open ref count in project1 - 2"); // file2 assert.strictEqual(projectService.configuredProjects.get(tsconfig1.path), project1); + assert.isFalse(project1.isClosed()); const project2 = projectService.configuredProjects.get(tsconfig2.path); - assert.equal(project2.openRefCount, 1, "Open ref count in project2 - 2"); + assert.isTrue(project2.hasOpenRef(), "Has open ref count in project2 - 2"); // file1 + assert.isFalse(project2.isClosed()); assert.equal(project1.getScriptInfo(file1.path).containingProjects.length, 2, `${file1.path} containing projects count`); assert.equal(project1.getScriptInfo(file2.path).containingProjects.length, 1, `${file2.path} containing projects count`); projectService.closeClientFile(file2.path); checkNumberOfProjects(projectService, { configuredProjects: 2 }); - assert.equal(project1.openRefCount, 1, "Open ref count in project1 - 3"); - assert.equal(project2.openRefCount, 1, "Open ref count in project2 - 3"); + assert.isFalse(project1.hasOpenRef(), "Has open ref count in project1 - 3"); // No files + assert.isTrue(project2.hasOpenRef(), "Has open ref count in project2 - 3"); // file1 assert.strictEqual(projectService.configuredProjects.get(tsconfig1.path), project1); assert.strictEqual(projectService.configuredProjects.get(tsconfig2.path), project2); + assert.isFalse(project1.isClosed()); + assert.isFalse(project2.isClosed()); projectService.closeClientFile(file1.path); checkNumberOfProjects(projectService, { configuredProjects: 2 }); - assert.equal(project1.openRefCount, 0, "Open ref count in project1 - 4"); - assert.equal(project2.openRefCount, 0, "Open ref count in project2 - 4"); + assert.isFalse(project1.hasOpenRef(), "Has open ref count in project1 - 4"); // No files + assert.isFalse(project2.hasOpenRef(), "Has open ref count in project2 - 4"); // No files assert.strictEqual(projectService.configuredProjects.get(tsconfig1.path), project1); assert.strictEqual(projectService.configuredProjects.get(tsconfig2.path), project2); + assert.isFalse(project1.isClosed()); + assert.isFalse(project2.isClosed()); projectService.openClientFile(file2.path); checkNumberOfProjects(projectService, { configuredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(tsconfig1.path), project1); assert.isUndefined(projectService.configuredProjects.get(tsconfig2.path)); - assert.equal(project1.openRefCount, 1, "Open ref count in project1 - 5"); + assert.isTrue(project1.hasOpenRef(), "Has open ref count in project1 - 5"); // file2 + assert.isFalse(project1.isClosed()); + assert.isTrue(project2.isClosed()); }); it("Open ref of configured project when open file gets added to the project as part of configured file update", () => { - const file1 = { + const file1: FileOrFolder = { path: "/a/b/src/file1.ts", content: "let x = 1;" }; - const file2 = { + const file2: FileOrFolder = { path: "/a/b/src/file2.ts", content: "let y = 1;" }; - const file3 = { + const file3: FileOrFolder = { path: "/a/b/file3.ts", content: "let z = 1;" }; - const file4 = { + const file4: FileOrFolder = { path: "/a/file4.ts", content: "let z = 1;" }; @@ -2148,7 +2164,7 @@ namespace ts.projectSystem { checkOpenFiles(projectService, files); checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); const configProject1 = projectService.configuredProjects.get(configFile.path); - assert.equal(configProject1.openRefCount, 2); + assert.isTrue(configProject1.hasOpenRef()); // file1 and file3 checkProjectActualFiles(configProject1, [file1.path, file3.path, configFile.path]); const inferredProject1 = projectService.inferredProjects[0]; checkProjectActualFiles(inferredProject1, [file2.path]); @@ -2161,11 +2177,11 @@ namespace ts.projectSystem { verifyScriptInfos(); checkOpenFiles(projectService, files); - verifyConfiguredProjectStateAfterUpdate(3); + verifyConfiguredProjectStateAfterUpdate(/*hasOpenRef*/ true); // file1, file2, file3 checkNumberOfInferredProjects(projectService, 1); const inferredProject3 = projectService.inferredProjects[0]; checkProjectActualFiles(inferredProject3, [file4.path]); - assert.strictEqual(inferredProject2, inferredProject3); + assert.strictEqual(inferredProject3, inferredProject2); projectService.closeClientFile(file1.path); projectService.closeClientFile(file2.path); @@ -2173,30 +2189,122 @@ namespace ts.projectSystem { verifyScriptInfos(); checkOpenFiles(projectService, [file3]); - verifyConfiguredProjectStateAfterUpdate(1); + verifyConfiguredProjectStateAfterUpdate(/*hasOpenRef*/ true); // file3 checkNumberOfInferredProjects(projectService, 0); projectService.openClientFile(file4.path); - //verifyScriptInfos(); + verifyScriptInfos(); checkOpenFiles(projectService, [file3, file4]); - //verifyConfiguredProjectStateAfterUpdate(1); + verifyConfiguredProjectStateAfterUpdate(/*hasOpenRef*/ true); // file3 checkNumberOfInferredProjects(projectService, 1); const inferredProject4 = projectService.inferredProjects[0]; checkProjectActualFiles(inferredProject4, [file4.path]); + projectService.closeClientFile(file3.path); + verifyScriptInfos(); + checkOpenFiles(projectService, [file4]); + verifyConfiguredProjectStateAfterUpdate(/*hasOpenRef*/ false); // No open files + checkNumberOfInferredProjects(projectService, 1); + const inferredProject5 = projectService.inferredProjects[0]; + checkProjectActualFiles(inferredProject4, [file4.path]); + assert.strictEqual(inferredProject5, inferredProject4); + + const file5: FileOrFolder = { + path: "/file5.ts", + content: "let zz = 1;" + }; + host.reloadFS(files.concat(configFile, file5)); + projectService.openClientFile(file5.path); + verifyScriptInfosAreUndefined([file1, file2, file3]); + assert.strictEqual(projectService.getScriptInfoForPath(file4.path as Path), find(infos, info => info.path === file4.path)); + assert.isDefined(projectService.getScriptInfoForPath(file5.path as Path)); + checkOpenFiles(projectService, [file4, file5]); + checkNumberOfConfiguredProjects(projectService, 0); + function verifyScriptInfos() { infos.forEach(info => assert.strictEqual(projectService.getScriptInfoForPath(info.path), info)); } - function verifyConfiguredProjectStateAfterUpdate(_openRefCount: number) { + function verifyScriptInfosAreUndefined(files: FileOrFolder[]) { + for (const file of files) { + assert.isUndefined(projectService.getScriptInfoForPath(file.path as Path)); + } + } + + function verifyConfiguredProjectStateAfterUpdate(hasOpenRef: boolean) { checkNumberOfConfiguredProjects(projectService, 1); const configProject2 = projectService.configuredProjects.get(configFile.path); - assert.strictEqual(configProject1, configProject2); + assert.strictEqual(configProject2, configProject1); checkProjectActualFiles(configProject2, [file1.path, file2.path, file3.path, configFile.path]); - //assert.equal(configProject2.openRefCount, openRefCount); + assert.equal(configProject2.hasOpenRef(), hasOpenRef); } }); + it("Open ref of configured project when open file gets added to the project as part of configured file update buts its open file references are all closed when the update happens", () => { + const file1: FileOrFolder = { + path: "/a/b/src/file1.ts", + content: "let x = 1;" + }; + const file2: FileOrFolder = { + path: "/a/b/src/file2.ts", + content: "let y = 1;" + }; + const file3: FileOrFolder = { + path: "/a/b/file3.ts", + content: "let z = 1;" + }; + const file4: FileOrFolder = { + path: "/a/file4.ts", + content: "let z = 1;" + }; + const configFile = { + path: "/a/b/tsconfig.json", + content: JSON.stringify({ files: ["src/file1.ts", "file3.ts"] }) + }; + + const files = [file1, file2, file3]; + const hostFiles = files.concat(file4, configFile); + const host = createServerHost(hostFiles); + const projectService = createProjectService(host); + + projectService.openClientFile(file1.path); + projectService.openClientFile(file2.path); + projectService.openClientFile(file3.path); + + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 1 }); + const configuredProject = projectService.configuredProjects.get(configFile.path); + assert.isTrue(configuredProject.hasOpenRef()); // file1 and file3 + checkProjectActualFiles(configuredProject, [file1.path, file3.path, configFile.path]); + const inferredProject1 = projectService.inferredProjects[0]; + checkProjectActualFiles(inferredProject1, [file2.path]); + + projectService.closeClientFile(file1.path); + projectService.closeClientFile(file3.path); + assert.isFalse(configuredProject.hasOpenRef()); // No files + + configFile.content = "{}"; + host.reloadFS(files.concat(configFile)); + // Time out is not yet run so there is project update pending + assert.isTrue(configuredProject.hasOpenRef()); // Pending update and file2 might get into the project + + projectService.openClientFile(file4.path); + + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); + assert.strictEqual(projectService.configuredProjects.get(configFile.path), configuredProject); + assert.isTrue(configuredProject.hasOpenRef()); // Pending update and F2 might get into the project + assert.strictEqual(projectService.inferredProjects[0], inferredProject1); + const inferredProject2 = projectService.inferredProjects[1]; + checkProjectActualFiles(inferredProject2, [file4.path]); + + host.runQueuedTimeoutCallbacks(); + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 1 }); + assert.strictEqual(projectService.configuredProjects.get(configFile.path), configuredProject); + assert.isTrue(configuredProject.hasOpenRef()); // file2 + checkProjectActualFiles(configuredProject, [file1.path, file2.path, file3.path, configFile.path]); + assert.strictEqual(projectService.inferredProjects[0], inferredProject2); + checkProjectActualFiles(inferredProject2, [file4.path]); + }); + it("language service disabled state is updated in external projects", () => { const f1 = { path: "/a/app.js", @@ -2265,18 +2373,36 @@ namespace ts.projectSystem { projectService.openClientFile(f1.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); const project = projectService.configuredProjects.get(config.path); + assert.isTrue(project.hasOpenRef()); // f1 + assert.isFalse(project.isClosed()); projectService.closeClientFile(f1.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(config.path), project); - assert.equal(project.openRefCount, 0); + assert.isFalse(project.hasOpenRef()); // No files + assert.isFalse(project.isClosed()); for (const f of [f1, f2, f3]) { - // There shouldnt be any script info as we closed the file that resulted in creation of it + // All the script infos should be present and contain the project since it is still alive. const scriptInfo = projectService.getScriptInfoForNormalizedPath(server.toNormalizedPath(f.path)); assert.equal(scriptInfo.containingProjects.length, 1, `expect 1 containing projects for '${f.path}'`); assert.equal(scriptInfo.containingProjects[0], project, `expect configured project to be the only containing project for '${f.path}'`); } + + const f4 = { + path: "/aa.js", + content: "var x = 1" + }; + host.reloadFS([f1, f2, f3, config, f4]); + projectService.openClientFile(f4.path); + projectService.checkNumberOfProjects({ inferredProjects: 1 }); + assert.isFalse(project.hasOpenRef()); // No files + assert.isTrue(project.isClosed()); + + for (const f of [f1, f2, f3]) { + // All the script infos should not be present since the project is closed and orphan script infos are collected + assert.isUndefined(projectService.getScriptInfoForNormalizedPath(server.toNormalizedPath(f.path))); + } }); it("language service disabled events are triggered", () => { @@ -2910,17 +3036,19 @@ namespace ts.projectSystem { projectService.openClientFile(f.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); const project = projectService.configuredProjects.get(config.path); - assert.equal(project.openRefCount, 1); + assert.isTrue(project.hasOpenRef()); // f projectService.closeClientFile(f.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(config.path), project); - assert.equal(project.openRefCount, 0); + assert.isFalse(project.hasOpenRef()); // No files + assert.isFalse(project.isClosed()); projectService.openClientFile(f.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(config.path), project); - assert.equal(project.openRefCount, 1); + assert.isTrue(project.hasOpenRef()); // f + assert.isFalse(project.isClosed()); }); }); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 70598313a73..a017ac5e45e 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -554,6 +554,11 @@ namespace ts.server { }); } + /*@internal*/ + hasPendingProjectUpdate(project: Project) { + return this.pendingProjectUpdates.has(project.getProjectName()); + } + private sendProjectsUpdatedInBackgroundEvent() { if (!this.eventHandler) { return; @@ -795,8 +800,14 @@ namespace ts.server { ); } + /** Gets the config file existence info for the configured project */ + /*@internal*/ + getConfigFileExistenceInfo(project: ConfiguredProject) { + return this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath); + } + private onConfigChangedForConfiguredProject(project: ConfiguredProject, eventKind: FileWatcherEventKind) { - const configFileExistenceInfo = this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath); + const configFileExistenceInfo = this.getConfigFileExistenceInfo(project); if (eventKind === FileWatcherEventKind.Deleted) { // Update the cached status // We arent updating or removing the cached config file presence info as that will be taken care of by @@ -898,18 +909,6 @@ namespace ts.server { return project; } - private addToListOfOpenFiles(info: ScriptInfo) { - Debug.assert(!info.isOrphan()); - for (const p of info.containingProjects) { - // file is the part of configured project, addref the project - if (p.projectKind === ProjectKind.Configured) { - ((p)).addOpenRef(); - } - } - - this.openFiles.push(info); - } - /** * Remove this file from the set of open, non-configured files. * @param info The file that has been closed or newly configured @@ -932,10 +931,8 @@ namespace ts.server { if (info.hasMixedContent) { info.registerFileUpdate(); } - // Delete the reference to the open configured projects but - // do not remove the project so that we can reuse this project + // Do not remove the project so that we can reuse this project // if it would need to be re-created with next file open - (p).deleteOpenRef(); } else if (p.projectKind === ProjectKind.Inferred && p.isRoot(info)) { // If this was the open root file of inferred project @@ -1025,7 +1022,7 @@ namespace ts.server { } private setConfigFileExistenceByNewConfiguredProject(project: ConfiguredProject) { - const configFileExistenceInfo = this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath); + const configFileExistenceInfo = this.getConfigFileExistenceInfo(project); if (configFileExistenceInfo) { Debug.assert(configFileExistenceInfo.exists); // close existing watcher @@ -1054,7 +1051,7 @@ namespace ts.server { } private setConfigFileExistenceInfoByClosedConfiguredProject(closedProject: ConfiguredProject) { - const configFileExistenceInfo = this.configFileExistenceInfoCache.get(closedProject.canonicalConfigFilePath); + const configFileExistenceInfo = this.getConfigFileExistenceInfo(closedProject); Debug.assert(!!configFileExistenceInfo); if (configFileExistenceInfo.openFilesImpactedByConfigFile.size) { const configFileName = closedProject.getConfigFilePath(); @@ -1943,7 +1940,8 @@ namespace ts.server { this.assignOrphanScriptInfoToInferredProject(info, projectRootPath); } - this.addToListOfOpenFiles(info); + Debug.assert(!info.isOrphan()); + this.openFiles.push(info); if (sendConfigFileDiagEvent) { configFileErrors = project.getAllProjectErrors(); @@ -2043,11 +2041,14 @@ namespace ts.server { } } - private closeConfiguredProject(configFile: NormalizedPath): boolean { + private closeConfiguredProjectReferencedFromExternalProject(configFile: NormalizedPath): boolean { const configuredProject = this.findConfiguredProjectByProjectName(configFile); - if (configuredProject && configuredProject.deleteOpenRef() === 0) { - this.removeProject(configuredProject); - return true; + if (configuredProject) { + configuredProject.deleteExternalProjectReference(); + if (!configuredProject.hasOpenRef()) { + this.removeProject(configuredProject); + return true; + } } return false; } @@ -2058,7 +2059,7 @@ namespace ts.server { if (configFiles) { let shouldRefreshInferredProjects = false; for (const configFile of configFiles) { - if (this.closeConfiguredProject(configFile)) { + if (this.closeConfiguredProjectReferencedFromExternalProject(configFile)) { shouldRefreshInferredProjects = true; } } @@ -2253,7 +2254,7 @@ namespace ts.server { const newConfig = tsConfigFiles[iNew]; const oldConfig = oldConfigFiles[iOld]; if (oldConfig < newConfig) { - this.closeConfiguredProject(oldConfig); + this.closeConfiguredProjectReferencedFromExternalProject(oldConfig); iOld++; } else if (oldConfig > newConfig) { @@ -2268,7 +2269,7 @@ namespace ts.server { } for (let i = iOld; i < oldConfigFiles.length; i++) { // projects for all remaining old config files should be closed - this.closeConfiguredProject(oldConfigFiles[i]); + this.closeConfiguredProjectReferencedFromExternalProject(oldConfigFiles[i]); } } } @@ -2283,7 +2284,7 @@ namespace ts.server { } if (project && !contains(exisingConfigFiles, tsconfigFile)) { // keep project alive even if no documents are opened - its lifetime is bound to the lifetime of containing external project - project.addOpenRef(); + project.addExternalProjectReference(); } } } diff --git a/src/server/project.ts b/src/server/project.ts index 7653fbf93cf..395da1bd643 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -892,9 +892,7 @@ namespace ts.server { } getScriptInfoForNormalizedPath(fileName: NormalizedPath) { - const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath( - fileName, /*scriptKind*/ undefined, /*hasMixedContent*/ undefined, this.directoryStructureHost - ); + const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(fileName); if (scriptInfo && !scriptInfo.isAttached(this)) { return Errors.ThrowProjectDoesNotContainDocument(fileName, this); } @@ -902,7 +900,7 @@ namespace ts.server { } getScriptInfo(uncheckedFileName: string) { - return this.getScriptInfoForNormalizedPath(toNormalizedPath(uncheckedFileName)); + return this.projectService.getScriptInfo(uncheckedFileName); } filesToString(writeProjectFileNames: boolean) { @@ -1130,8 +1128,8 @@ namespace ts.server { private plugins: PluginModule[] = []; - /** Used for configured projects which may have multiple open roots */ - openRefCount = 0; + /** Ref count to the project when opened from external project */ + private externalProjectRefCount = 0; private projectErrors: Diagnostic[]; @@ -1342,17 +1340,43 @@ namespace ts.server { super.close(); } - addOpenRef() { - this.openRefCount++; + /* @internal */ + addExternalProjectReference() { + this.externalProjectRefCount++; } - deleteOpenRef() { - this.openRefCount--; - return this.openRefCount; + /* @internal */ + deleteExternalProjectReference() { + this.externalProjectRefCount--; } + /** Returns true if the project is needed by any of the open script info/external project */ + /* @internal */ hasOpenRef() { - return !!this.openRefCount; + if (!!this.externalProjectRefCount) { + return true; + } + + // Closed project doesnt have any reference + if (this.isClosed()) { + return false; + } + + const configFileExistenceInfo = this.projectService.getConfigFileExistenceInfo(this); + if (this.projectService.hasPendingProjectUpdate(this)) { + // If there is pending update for this project, + // we dont know if this project would be needed by any of the open files impacted by this config file + // In that case keep the project alive if there are open files impacted by this project + return !!configFileExistenceInfo.openFilesImpactedByConfigFile.size; + } + + // If there is no pending update for this project, + // We know exact set of open files that get impacted by this configured project as the files in the project + // The project is referenced only if open files impacted by this project are present in this project + return forEachEntry( + configFileExistenceInfo.openFilesImpactedByConfigFile, + (_value, infoPath) => this.containsScriptInfo(this.projectService.getScriptInfoForPath(infoPath as Path)) + ) || false; } getEffectiveTypeRoots() { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 151c948602d..204c718fabd 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7211,8 +7211,8 @@ declare namespace ts.server { private directoriesWatchedForWildcards; readonly canonicalConfigFilePath: NormalizedPath; private plugins; - /** Used for configured projects which may have multiple open roots */ - openRefCount: number; + /** Ref count to the project when opened from external project */ + private externalProjectRefCount; private projectErrors; /** * If the project has reload from disk pending, it reloads (and then updates graph as part of that) instead of just updating the graph @@ -7236,9 +7236,6 @@ declare namespace ts.server { getTypeAcquisition(): TypeAcquisition; getExternalFiles(): SortedReadonlyArray; close(): void; - addOpenRef(): void; - deleteOpenRef(): number; - hasOpenRef(): boolean; getEffectiveTypeRoots(): string[]; } /** @@ -7468,7 +7465,6 @@ declare namespace ts.server { */ private onConfigFileChangeForOpenScriptInfo(configFileName, eventKind); private removeProject(project); - private addToListOfOpenFiles(info); /** * Remove this file from the set of open, non-configured files. * @param info The file that has been closed or newly configured @@ -7576,7 +7572,7 @@ declare namespace ts.server { */ closeClientFile(uncheckedFileName: string): void; private collectChanges(lastKnownProjectVersions, currentProjects, result); - private closeConfiguredProject(configFile); + private closeConfiguredProjectReferencedFromExternalProject(configFile); closeExternalProject(uncheckedFileName: string, suppressRefresh?: boolean): void; openExternalProjects(projects: protocol.ExternalProject[]): void; /** Makes a filename safe to insert in a RegExp */ From 1cb2d24c5d218a8119655d584bd61d749b18dec2 Mon Sep 17 00:00:00 2001 From: Armando Aguirre Date: Thu, 12 Oct 2017 17:18:38 -0700 Subject: [PATCH 016/405] Added DefinitionAndBoundSpan command --- src/harness/harnessLanguageService.ts | 3 +++ src/harness/unittests/session.ts | 5 +++-- src/server/client.ts | 6 +++++- src/server/protocol.ts | 2 ++ src/server/session.ts | 20 +++++++++++++++++-- src/services/services.ts | 14 +++++++++++-- src/services/types.ts | 1 + .../reference/api/tsserverlibrary.d.ts | 18 +++++++++-------- tests/baselines/reference/api/typescript.d.ts | 7 ++++--- 9 files changed, 58 insertions(+), 18 deletions(-) diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index ad79c96d833..34043195429 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -490,6 +490,9 @@ namespace Harness.LanguageService { getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): ts.TextSpan { return unwrapJSONCallResult(this.shim.getSpanOfEnclosingComment(fileName, position, onlyMultiLine)); } + getSpanForPosition(): ts.TextSpan { + throw new Error("Not supportred on the shim."); + } getCodeFixesAtPosition(): ts.CodeAction[] { throw new Error("Not supported on the shim."); } diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index 3b5efc2d6de..2ce5ef530e4 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -117,7 +117,7 @@ namespace ts.server { body: undefined }); }); - it ("should handle literal types in request", () => { + it("should handle literal types in request", () => { const configureRequest: protocol.ConfigureRequest = { command: CommandNames.Configure, seq: 0, @@ -175,6 +175,7 @@ namespace ts.server { CommandNames.Configure, CommandNames.Definition, CommandNames.DefinitionFull, + CommandNames.DefinitionAndBoundSpan, CommandNames.Implementation, CommandNames.ImplementationFull, CommandNames.Exit, @@ -341,7 +342,7 @@ namespace ts.server { session.addProtocolHandler(command, () => resp); expect(() => session.addProtocolHandler(command, () => resp)) - .to.throw(`Protocol handler already exists for command "${command}"`); + .to.throw(`Protocol handler already exists for command "${command}"`); }); }); diff --git a/src/server/client.ts b/src/server/client.ts index d08d1e13d2e..f467f7f9224 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -322,7 +322,7 @@ namespace ts.server { } getSyntacticDiagnostics(file: string): Diagnostic[] { - const args: protocol.SyntacticDiagnosticsSyncRequestArgs = { file, includeLinePosition: true }; + const args: protocol.SyntacticDiagnosticsSyncRequestArgs = { file, includeLinePosition: true }; const request = this.processRequest(CommandNames.SyntacticDiagnosticsSync, args); const response = this.processResponse(request); @@ -531,6 +531,10 @@ namespace ts.server { return notImplemented(); } + getSpanForPosition(_fileName: string, _position: number): TextSpan { + return notImplemented(); + } + getCodeFixesAtPosition(file: string, start: number, end: number, errorCodes: number[]): CodeAction[] { const args: protocol.CodeFixRequestArgs = { ...this.createFileRangeRequestArgs(file, start, end), errorCodes }; diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 3d07392bbe6..0685728c3b0 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -21,6 +21,8 @@ namespace ts.server.protocol { Definition = "definition", /* @internal */ DefinitionFull = "definition-full", + /* @internal */ + DefinitionAndBoundSpan = "definitionAndBoundSpan", Implementation = "implementation", /* @internal */ ImplementationFull = "implementation-full", diff --git a/src/server/session.ts b/src/server/session.ts index 800d09ff6c2..5a8426f23b3 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -167,7 +167,7 @@ namespace ts.server { private timerHandle: any; private immediateId: number | undefined; - constructor(private readonly operationHost: MultistepOperationHost) {} + constructor(private readonly operationHost: MultistepOperationHost) { } public startNew(action: (next: NextStep) => void) { this.complete(); @@ -579,7 +579,7 @@ namespace ts.server { private getDiagnosticsWorker( args: protocol.FileRequestArgs, isSemantic: boolean, selector: (project: Project, file: string) => ReadonlyArray, includeLinePosition: boolean - ): ReadonlyArray | ReadonlyArray { + ): ReadonlyArray | ReadonlyArray { const { project, file } = this.getFileAndProject(args); if (isSemantic && isDeclarationFileInJSOnlyNonConfiguredProject(project, file)) { return emptyArray; @@ -1081,6 +1081,13 @@ namespace ts.server { } } + private getSpanForLocation(args: protocol.FileLocationRequestArgs): TextSpan { + const { file, project } = this.getFileAndProject(args); + const scriptInfo = project.getScriptInfoForNormalizedPath(file); + + return project.getLanguageService().getSpanForPosition(file, this.getPosition(args, scriptInfo)); + } + private getFormattingEditsForRange(args: protocol.FormatRequestArgs): protocol.CodeEdit[] { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file); @@ -1707,6 +1714,15 @@ namespace ts.server { [CommandNames.DefinitionFull]: (request: protocol.DefinitionRequest) => { return this.requiredResponse(this.getDefinition(request.arguments, /*simplifiedResult*/ false)); }, + [CommandNames.DefinitionAndBoundSpan]: (request: protocol.DefinitionRequest) => { + const definitions = this.getDefinition(request.arguments, /*simplifiedResult*/ false); + const textSpan = definitions.length !== 0 ? this.getSpanForLocation(request.arguments) : {}; + + return this.requiredResponse({ + definitions, + textSpan + }); + }, [CommandNames.TypeDefinition]: (request: protocol.FileLocationRequest) => { return this.requiredResponse(this.getTypeDefinition(request.arguments)); }, diff --git a/src/services/services.ts b/src/services/services.ts index 6bdc96d8b4d..5b24fa1947e 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -724,9 +724,9 @@ namespace ts { case SyntaxKind.BinaryExpression: if (getSpecialPropertyAssignmentKind(node as BinaryExpression) !== SpecialPropertyAssignmentKind.None) { - addDeclaration(node as BinaryExpression); + addDeclaration(node as BinaryExpression); } - // falls through + // falls through default: forEachChild(node, visit); @@ -1807,6 +1807,15 @@ namespace ts { return range && createTextSpanFromRange(range); } + function getSpanForPosition(fileName: string, position: number): TextSpan { + synchronizeHostData(); + + const sourceFile = getValidSourceFile(fileName); + const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocCcomment*/ false); + + return createTextSpan(node.getStart(), node.getWidth()); + } + function getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] { // Note: while getting todo comments seems like a syntactic operation, we actually // treat it as a semantic operation here. This is because we expect our host to call @@ -2032,6 +2041,7 @@ namespace ts { getDocCommentTemplateAtPosition, isValidBraceCompletionAtPosition, getSpanOfEnclosingComment, + getSpanForPosition, getCodeFixesAtPosition, getEmitOutput, getNonBoundSourceFile, diff --git a/src/services/types.ts b/src/services/types.ts index e853eb7b96c..034b45100e0 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -273,6 +273,7 @@ namespace ts { isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; + getSpanForPosition(fileName: string, position: number): TextSpan; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[]; getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 151c948602d..1cf429546de 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -44,9 +44,9 @@ declare namespace ts { value: T; done: false; } | { - value: never; - done: true; - }; + value: never; + done: true; + }; } /** Array that is only intended to be pushed to, never read. */ interface Push { @@ -3942,6 +3942,7 @@ declare namespace ts { getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; + getSpanForPosition(fileName: string, position: number): TextSpan; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[]; getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined; @@ -4609,12 +4610,12 @@ declare namespace ts.server { module: {}; error: undefined; } | { - module: undefined; - error: { - stack?: string; - message?: string; + module: undefined; + error: { + stack?: string; + message?: string; + }; }; - }; interface ServerHost extends System { setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; clearTimeout(timeoutId: any): void; @@ -6887,6 +6888,7 @@ declare namespace ts.server { private getNameOrDottedNameSpan(args); private isValidBraceCompletion(args); private getQuickInfoWorker(args, simplifiedResult); + private getSpanForLocation(args); private getFormattingEditsForRange(args); private getFormattingEditsForRangeFull(args); private getFormattingEditsForDocumentFull(args); diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 14fae7d0d77..8350b2d7a9d 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -44,9 +44,9 @@ declare namespace ts { value: T; done: false; } | { - value: never; - done: true; - }; + value: never; + done: true; + }; } /** Array that is only intended to be pushed to, never read. */ interface Push { @@ -3942,6 +3942,7 @@ declare namespace ts { getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; + getSpanForPosition(fileName: string, position: number): TextSpan; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[]; getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined; From c6a8a32b710a3c8c3581c1792e7858c97e22318a Mon Sep 17 00:00:00 2001 From: Armando Aguirre Date: Fri, 13 Oct 2017 16:36:25 -0700 Subject: [PATCH 017/405] Fixed api reference tests --- .../baselines/reference/api/tsserverlibrary.d.ts | 16 ++++++++-------- tests/baselines/reference/api/typescript.d.ts | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 1cf429546de..8beb5ff60e4 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -44,9 +44,9 @@ declare namespace ts { value: T; done: false; } | { - value: never; - done: true; - }; + value: never; + done: true; + }; } /** Array that is only intended to be pushed to, never read. */ interface Push { @@ -4610,12 +4610,12 @@ declare namespace ts.server { module: {}; error: undefined; } | { - module: undefined; - error: { - stack?: string; - message?: string; - }; + module: undefined; + error: { + stack?: string; + message?: string; }; + }; interface ServerHost extends System { setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; clearTimeout(timeoutId: any): void; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 8350b2d7a9d..2733bb20e56 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -44,9 +44,9 @@ declare namespace ts { value: T; done: false; } | { - value: never; - done: true; - }; + value: never; + done: true; + }; } /** Array that is only intended to be pushed to, never read. */ interface Push { From 30c51ed3249a1701c5d1faeb169717ff009d6ad5 Mon Sep 17 00:00:00 2001 From: kingwl <805037171@163.com> Date: Mon, 16 Oct 2017 10:39:55 +0800 Subject: [PATCH 018/405] fix super call from class that has no basetype but with same symbol interface (#19068) --- src/compiler/checker.ts | 8 +++++--- ...aseTypeButWithSameSymbolInterface.errors.txt | 14 ++++++++++++++ ...atHasNoBaseTypeButWithSameSymbolInterface.js | 17 +++++++++++++++++ ...NoBaseTypeButWithSameSymbolInterface.symbols | 13 +++++++++++++ ...asNoBaseTypeButWithSameSymbolInterface.types | 15 +++++++++++++++ ...atHasNoBaseTypeButWithSameSymbolInterface.ts | 7 +++++++ 6 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.errors.txt create mode 100644 tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.js create mode 100644 tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.symbols create mode 100644 tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.types create mode 100644 tests/cases/conformance/es6/classDeclaration/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 32086157552..bd97a49fa45 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13043,12 +13043,14 @@ namespace ts { // at this point the only legal case for parent is ClassLikeDeclaration const classLikeDeclaration = container.parent; + if (!getClassExtendsHeritageClauseElement(classLikeDeclaration)) { + error(node, Diagnostics.super_can_only_be_referenced_in_a_derived_class); + return unknownType; + } + const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classLikeDeclaration)); const baseClassType = classType && getBaseTypes(classType)[0]; if (!baseClassType) { - if (!getClassExtendsHeritageClauseElement(classLikeDeclaration)) { - error(node, Diagnostics.super_can_only_be_referenced_in_a_derived_class); - } return unknownType; } diff --git a/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.errors.txt b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.errors.txt new file mode 100644 index 00000000000..44963f797ea --- /dev/null +++ b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.errors.txt @@ -0,0 +1,14 @@ +tests/cases/conformance/es6/classDeclaration/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts(5,9): error TS2335: 'super' can only be referenced in a derived class. + + +==== tests/cases/conformance/es6/classDeclaration/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts (1 errors) ==== + interface Foo extends Array {} + + class Foo { + constructor() { + super(); // error + ~~~~~ +!!! error TS2335: 'super' can only be referenced in a derived class. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.js b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.js new file mode 100644 index 00000000000..e933ec9daa2 --- /dev/null +++ b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.js @@ -0,0 +1,17 @@ +//// [superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts] +interface Foo extends Array {} + +class Foo { + constructor() { + super(); // error + } +} + + +//// [superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.js] +var Foo = /** @class */ (function () { + function Foo() { + _this = _super.call(this) || this; // error + } + return Foo; +}()); diff --git a/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.symbols b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.symbols new file mode 100644 index 00000000000..a8ff0f10b4f --- /dev/null +++ b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.symbols @@ -0,0 +1,13 @@ +=== tests/cases/conformance/es6/classDeclaration/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts === +interface Foo extends Array {} +>Foo : Symbol(Foo, Decl(superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts, 0, 0), Decl(superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts, 0, 38)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +class Foo { +>Foo : Symbol(Foo, Decl(superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts, 0, 0), Decl(superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts, 0, 38)) + + constructor() { + super(); // error + } +} + diff --git a/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.types b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.types new file mode 100644 index 00000000000..f2e5ad17063 --- /dev/null +++ b/tests/baselines/reference/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.types @@ -0,0 +1,15 @@ +=== tests/cases/conformance/es6/classDeclaration/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts === +interface Foo extends Array {} +>Foo : Foo +>Array : T[] + +class Foo { +>Foo : Foo + + constructor() { + super(); // error +>super() : void +>super : any + } +} + diff --git a/tests/cases/conformance/es6/classDeclaration/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts b/tests/cases/conformance/es6/classDeclaration/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts new file mode 100644 index 00000000000..3afd8275941 --- /dev/null +++ b/tests/cases/conformance/es6/classDeclaration/superCallFromClassThatHasNoBaseTypeButWithSameSymbolInterface.ts @@ -0,0 +1,7 @@ +interface Foo extends Array {} + +class Foo { + constructor() { + super(); // error + } +} From 5e7bfad2a7c8e44c66b4599c187a738834d7dc4d Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 16 Oct 2017 09:19:46 -0700 Subject: [PATCH 019/405] Check own-constructor in abstract prop access error --- src/compiler/checker.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 32086157552..549b759b225 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14906,12 +14906,11 @@ namespace ts { } } - // Referencing Abstract Properties within Constructors is not allowed + // Referencing abstract properties within their own constructors is not allowed if ((flags & ModifierFlags.Abstract) && symbolHasNonMethodDeclaration(prop)) { const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)); - - if (declaringClassDeclaration && isNodeWithinConstructor(node, declaringClassDeclaration)) { - error(errorNode, Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), typeToString(getDeclaringClass(prop))); + if (declaringClassDeclaration && isNodeWithinConstructorOfClass(node, declaringClassDeclaration)) { + error(errorNode, Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), getTextOfIdentifierOrLiteral(declaringClassDeclaration.name)); return false; } } @@ -23227,9 +23226,9 @@ namespace ts { return result; } - function isNodeWithinConstructor(node: Node, classDeclaration: ClassLikeDeclaration) { + function isNodeWithinConstructorOfClass(node: Node, classDeclaration: ClassLikeDeclaration) { return findAncestor(node, element => { - if (isConstructorDeclaration(element) && nodeIsPresent(element.body)) { + if (isConstructorDeclaration(element) && nodeIsPresent(element.body) && element.parent === classDeclaration) { return true; } else if (element === classDeclaration || isFunctionLikeDeclaration(element)) { From fb45b49afcbc1182f4524703221f8bfe573a5de9 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 16 Oct 2017 09:20:28 -0700 Subject: [PATCH 020/405] Test:abstract prop access in non-declaring ctor --- .../abstractPropertyInConstructor.errors.txt | 9 +++++ .../abstractPropertyInConstructor.js | 18 ++++++++++ .../abstractPropertyInConstructor.symbols | 29 ++++++++++++++++ .../abstractPropertyInConstructor.types | 34 +++++++++++++++++++ .../compiler/abstractPropertyInConstructor.ts | 9 +++++ 5 files changed, 99 insertions(+) diff --git a/tests/baselines/reference/abstractPropertyInConstructor.errors.txt b/tests/baselines/reference/abstractPropertyInConstructor.errors.txt index 461dd713d3b..63636b35725 100644 --- a/tests/baselines/reference/abstractPropertyInConstructor.errors.txt +++ b/tests/baselines/reference/abstractPropertyInConstructor.errors.txt @@ -34,4 +34,13 @@ tests/cases/compiler/abstractPropertyInConstructor.ts(9,14): error TS2715: Abstr this.prop = this.prop + "!"; } } + + class User { + constructor(a: AbstractClass) { + a.prop; + a.cb("hi"); + a.method(12); + a.method2(); + } + } \ No newline at end of file diff --git a/tests/baselines/reference/abstractPropertyInConstructor.js b/tests/baselines/reference/abstractPropertyInConstructor.js index 18a2937a191..5bf9726b283 100644 --- a/tests/baselines/reference/abstractPropertyInConstructor.js +++ b/tests/baselines/reference/abstractPropertyInConstructor.js @@ -23,6 +23,15 @@ abstract class AbstractClass { this.prop = this.prop + "!"; } } + +class User { + constructor(a: AbstractClass) { + a.prop; + a.cb("hi"); + a.method(12); + a.method2(); + } +} //// [abstractPropertyInConstructor.js] @@ -44,3 +53,12 @@ var AbstractClass = /** @class */ (function () { }; return AbstractClass; }()); +var User = /** @class */ (function () { + function User(a) { + a.prop; + a.cb("hi"); + a.method(12); + a.method2(); + } + return User; +}()); diff --git a/tests/baselines/reference/abstractPropertyInConstructor.symbols b/tests/baselines/reference/abstractPropertyInConstructor.symbols index 0d542ffb0a8..f6e29a58487 100644 --- a/tests/baselines/reference/abstractPropertyInConstructor.symbols +++ b/tests/baselines/reference/abstractPropertyInConstructor.symbols @@ -68,3 +68,32 @@ abstract class AbstractClass { } } +class User { +>User : Symbol(User, Decl(abstractPropertyInConstructor.ts, 23, 1)) + + constructor(a: AbstractClass) { +>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 26, 16)) +>AbstractClass : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) + + a.prop; +>a.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) +>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 26, 16)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) + + a.cb("hi"); +>a.cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 15, 26)) +>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 26, 16)) +>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 15, 26)) + + a.method(12); +>a.method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 16, 37)) +>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 26, 16)) +>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 16, 37)) + + a.method2(); +>a.method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 18, 39)) +>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 26, 16)) +>method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 18, 39)) + } +} + diff --git a/tests/baselines/reference/abstractPropertyInConstructor.types b/tests/baselines/reference/abstractPropertyInConstructor.types index 0ffb5f1bdfd..a44403c1091 100644 --- a/tests/baselines/reference/abstractPropertyInConstructor.types +++ b/tests/baselines/reference/abstractPropertyInConstructor.types @@ -79,3 +79,37 @@ abstract class AbstractClass { } } +class User { +>User : User + + constructor(a: AbstractClass) { +>a : AbstractClass +>AbstractClass : AbstractClass + + a.prop; +>a.prop : string +>a : AbstractClass +>prop : string + + a.cb("hi"); +>a.cb("hi") : void +>a.cb : (s: string) => void +>a : AbstractClass +>cb : (s: string) => void +>"hi" : "hi" + + a.method(12); +>a.method(12) : void +>a.method : (num: number) => void +>a : AbstractClass +>method : (num: number) => void +>12 : 12 + + a.method2(); +>a.method2() : void +>a.method2 : () => void +>a : AbstractClass +>method2 : () => void + } +} + diff --git a/tests/cases/compiler/abstractPropertyInConstructor.ts b/tests/cases/compiler/abstractPropertyInConstructor.ts index 457fdb473b1..e58e052f8db 100644 --- a/tests/cases/compiler/abstractPropertyInConstructor.ts +++ b/tests/cases/compiler/abstractPropertyInConstructor.ts @@ -22,3 +22,12 @@ abstract class AbstractClass { this.prop = this.prop + "!"; } } + +class User { + constructor(a: AbstractClass) { + a.prop; + a.cb("hi"); + a.method(12); + a.method2(); + } +} From 49beac919cdaa6167653722e454e5acd2c041a87 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 16 Oct 2017 09:43:49 -0700 Subject: [PATCH 021/405] Abstract property access error only on this access --- src/compiler/checker.ts | 2 +- src/compiler/utilities.ts | 13 ++- .../abstractPropertyInConstructor.errors.txt | 6 +- .../abstractPropertyInConstructor.js | 11 ++- .../abstractPropertyInConstructor.symbols | 84 +++++++++++-------- .../abstractPropertyInConstructor.types | 15 +++- .../compiler/abstractPropertyInConstructor.ts | 6 +- 7 files changed, 93 insertions(+), 44 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 549b759b225..3c36a85e5d2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14907,7 +14907,7 @@ namespace ts { } // Referencing abstract properties within their own constructors is not allowed - if ((flags & ModifierFlags.Abstract) && symbolHasNonMethodDeclaration(prop)) { + if ((flags & ModifierFlags.Abstract) && isThisProperty(node) && symbolHasNonMethodDeclaration(prop)) { const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)); if (declaringClassDeclaration && isNodeWithinConstructorOfClass(node, declaringClassDeclaration)) { error(errorNode, Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), getTextOfIdentifierOrLiteral(declaringClassDeclaration.name)); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index c4d3de453ba..c29c6c45c89 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1121,7 +1121,7 @@ namespace ts { } /** - * Determines whether a node is a property or element access expression for super. + * Determines whether a node is a property or element access expression for `super`. */ export function isSuperProperty(node: Node): node is SuperProperty { const kind = node.kind; @@ -1129,7 +1129,16 @@ namespace ts { && (node).expression.kind === SyntaxKind.SuperKeyword; } - export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression { + /** + * Determines whether a node is a property or element access expression for `this`. + */ + export function isThisProperty(node: Node): boolean { + const kind = node.kind; + return (kind === SyntaxKind.PropertyAccessExpression || kind === SyntaxKind.ElementAccessExpression) + && (node).expression.kind === SyntaxKind.ThisKeyword; + } + + export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression { switch (node.kind) { case SyntaxKind.TypeReference: return (node).typeName; diff --git a/tests/baselines/reference/abstractPropertyInConstructor.errors.txt b/tests/baselines/reference/abstractPropertyInConstructor.errors.txt index 63636b35725..0798d91ce78 100644 --- a/tests/baselines/reference/abstractPropertyInConstructor.errors.txt +++ b/tests/baselines/reference/abstractPropertyInConstructor.errors.txt @@ -5,7 +5,7 @@ tests/cases/compiler/abstractPropertyInConstructor.ts(9,14): error TS2715: Abstr ==== tests/cases/compiler/abstractPropertyInConstructor.ts (3 errors) ==== abstract class AbstractClass { - constructor(str: string) { + constructor(str: string, other: AbstractClass) { this.method(parseInt(str)); let val = this.prop.toLowerCase(); ~~~~ @@ -20,9 +20,13 @@ tests/cases/compiler/abstractPropertyInConstructor.ts(9,14): error TS2715: Abstr ~~ !!! error TS2715: Abstract property 'cb' in class 'AbstractClass' cannot be accessed in the constructor. + // OK, reference is inside function const innerFunction = () => { return this.prop; } + + // OK, references are to another instance + other.cb(other.prop); } abstract prop: string; diff --git a/tests/baselines/reference/abstractPropertyInConstructor.js b/tests/baselines/reference/abstractPropertyInConstructor.js index 5bf9726b283..5a4feda110f 100644 --- a/tests/baselines/reference/abstractPropertyInConstructor.js +++ b/tests/baselines/reference/abstractPropertyInConstructor.js @@ -1,6 +1,6 @@ //// [abstractPropertyInConstructor.ts] abstract class AbstractClass { - constructor(str: string) { + constructor(str: string, other: AbstractClass) { this.method(parseInt(str)); let val = this.prop.toLowerCase(); @@ -9,9 +9,13 @@ abstract class AbstractClass { } this.cb(str); + // OK, reference is inside function const innerFunction = () => { return this.prop; } + + // OK, references are to another instance + other.cb(other.prop); } abstract prop: string; @@ -36,7 +40,7 @@ class User { //// [abstractPropertyInConstructor.js] var AbstractClass = /** @class */ (function () { - function AbstractClass(str) { + function AbstractClass(str, other) { var _this = this; this.method(parseInt(str)); var val = this.prop.toLowerCase(); @@ -44,9 +48,12 @@ var AbstractClass = /** @class */ (function () { this.prop = "Hello World"; } this.cb(str); + // OK, reference is inside function var innerFunction = function () { return _this.prop; }; + // OK, references are to another instance + other.cb(other.prop); } AbstractClass.prototype.method2 = function () { this.prop = this.prop + "!"; diff --git a/tests/baselines/reference/abstractPropertyInConstructor.symbols b/tests/baselines/reference/abstractPropertyInConstructor.symbols index f6e29a58487..42cd3bb6827 100644 --- a/tests/baselines/reference/abstractPropertyInConstructor.symbols +++ b/tests/baselines/reference/abstractPropertyInConstructor.symbols @@ -2,98 +2,110 @@ abstract class AbstractClass { >AbstractClass : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) - constructor(str: string) { + constructor(str: string, other: AbstractClass) { >str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 1, 16)) +>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 1, 28)) +>AbstractClass : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) this.method(parseInt(str)); ->this.method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 16, 37)) +>this.method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37)) >this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) ->method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 16, 37)) +>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37)) >parseInt : Symbol(parseInt, Decl(lib.d.ts, --, --)) >str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 1, 16)) let val = this.prop.toLowerCase(); >val : Symbol(val, Decl(abstractPropertyInConstructor.ts, 3, 11)) >this.prop.toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --)) ->this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) +>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) >this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) ->prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) >toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --)) if (!str) { >str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 1, 16)) this.prop = "Hello World"; ->this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) +>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) >this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) ->prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) } this.cb(str); ->this.cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 15, 26)) +>this.cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26)) >this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) ->cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 15, 26)) +>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26)) >str : Symbol(str, Decl(abstractPropertyInConstructor.ts, 1, 16)) + // OK, reference is inside function const innerFunction = () => { ->innerFunction : Symbol(innerFunction, Decl(abstractPropertyInConstructor.ts, 10, 13)) +>innerFunction : Symbol(innerFunction, Decl(abstractPropertyInConstructor.ts, 11, 13)) return this.prop; ->this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) +>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) >this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) ->prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) } + + // OK, references are to another instance + other.cb(other.prop); +>other.cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26)) +>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 1, 28)) +>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26)) +>other.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) +>other : Symbol(other, Decl(abstractPropertyInConstructor.ts, 1, 28)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) } abstract prop: string; ->prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) abstract cb: (s: string) => void; ->cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 15, 26)) ->s : Symbol(s, Decl(abstractPropertyInConstructor.ts, 16, 18)) +>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26)) +>s : Symbol(s, Decl(abstractPropertyInConstructor.ts, 20, 18)) abstract method(num: number): void; ->method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 16, 37)) ->num : Symbol(num, Decl(abstractPropertyInConstructor.ts, 18, 20)) +>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37)) +>num : Symbol(num, Decl(abstractPropertyInConstructor.ts, 22, 20)) method2() { ->method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 18, 39)) +>method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 22, 39)) this.prop = this.prop + "!"; ->this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) +>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) >this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) ->prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) ->this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) +>this.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) >this : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) ->prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) } } class User { ->User : Symbol(User, Decl(abstractPropertyInConstructor.ts, 23, 1)) +>User : Symbol(User, Decl(abstractPropertyInConstructor.ts, 27, 1)) constructor(a: AbstractClass) { ->a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 26, 16)) +>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 30, 16)) >AbstractClass : Symbol(AbstractClass, Decl(abstractPropertyInConstructor.ts, 0, 0)) a.prop; ->a.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) ->a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 26, 16)) ->prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 13, 5)) +>a.prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) +>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 30, 16)) +>prop : Symbol(AbstractClass.prop, Decl(abstractPropertyInConstructor.ts, 17, 5)) a.cb("hi"); ->a.cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 15, 26)) ->a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 26, 16)) ->cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 15, 26)) +>a.cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26)) +>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 30, 16)) +>cb : Symbol(AbstractClass.cb, Decl(abstractPropertyInConstructor.ts, 19, 26)) a.method(12); ->a.method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 16, 37)) ->a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 26, 16)) ->method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 16, 37)) +>a.method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37)) +>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 30, 16)) +>method : Symbol(AbstractClass.method, Decl(abstractPropertyInConstructor.ts, 20, 37)) a.method2(); ->a.method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 18, 39)) ->a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 26, 16)) ->method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 18, 39)) +>a.method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 22, 39)) +>a : Symbol(a, Decl(abstractPropertyInConstructor.ts, 30, 16)) +>method2 : Symbol(AbstractClass.method2, Decl(abstractPropertyInConstructor.ts, 22, 39)) } } diff --git a/tests/baselines/reference/abstractPropertyInConstructor.types b/tests/baselines/reference/abstractPropertyInConstructor.types index a44403c1091..6f8970a7702 100644 --- a/tests/baselines/reference/abstractPropertyInConstructor.types +++ b/tests/baselines/reference/abstractPropertyInConstructor.types @@ -2,8 +2,10 @@ abstract class AbstractClass { >AbstractClass : AbstractClass - constructor(str: string) { + constructor(str: string, other: AbstractClass) { >str : string +>other : AbstractClass +>AbstractClass : AbstractClass this.method(parseInt(str)); >this.method(parseInt(str)) : void @@ -41,6 +43,7 @@ abstract class AbstractClass { >cb : (s: string) => void >str : string + // OK, reference is inside function const innerFunction = () => { >innerFunction : () => string >() => { return this.prop; } : () => string @@ -50,6 +53,16 @@ abstract class AbstractClass { >this : this >prop : string } + + // OK, references are to another instance + other.cb(other.prop); +>other.cb(other.prop) : void +>other.cb : (s: string) => void +>other : AbstractClass +>cb : (s: string) => void +>other.prop : string +>other : AbstractClass +>prop : string } abstract prop: string; diff --git a/tests/cases/compiler/abstractPropertyInConstructor.ts b/tests/cases/compiler/abstractPropertyInConstructor.ts index e58e052f8db..b8386f56e1e 100644 --- a/tests/cases/compiler/abstractPropertyInConstructor.ts +++ b/tests/cases/compiler/abstractPropertyInConstructor.ts @@ -1,5 +1,5 @@ abstract class AbstractClass { - constructor(str: string) { + constructor(str: string, other: AbstractClass) { this.method(parseInt(str)); let val = this.prop.toLowerCase(); @@ -8,9 +8,13 @@ abstract class AbstractClass { } this.cb(str); + // OK, reference is inside function const innerFunction = () => { return this.prop; } + + // OK, references are to another instance + other.cb(other.prop); } abstract prop: string; From 3c27e782da3b2242c42eb0e883cb0a58444b3dcf Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 16 Oct 2017 11:22:49 -0700 Subject: [PATCH 022/405] Add getCompilerOptions method to project Fixes #19218 --- src/server/project.ts | 4 ++++ tests/baselines/reference/api/tsserverlibrary.d.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/src/server/project.ts b/src/server/project.ts index 7653fbf93cf..ca6e82ec4be 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -246,6 +246,10 @@ namespace ts.server { return this.compilerOptions; } + getCompilerOptions() { + return this.compilerOptions; + } + getNewLine() { return this.directoryStructureHost.newLine; } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 151c948602d..e983ac73b15 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7109,6 +7109,7 @@ declare namespace ts.server { getCachedUnresolvedImportsPerFile_TestOnly(): UnresolvedImportsMap; static resolveModule(moduleName: string, initialDir: string, host: ServerHost, log: (message: string) => void): {}; getCompilationSettings(): CompilerOptions; + getCompilerOptions(): CompilerOptions; getNewLine(): string; getProjectVersion(): string; getScriptFileNames(): string[]; From bac30fc1a2ab3d99c5f22891da8110d47c16e242 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 16 Oct 2017 11:41:35 -0700 Subject: [PATCH 023/405] In convertFunctionToEs6Class.ts, share code for getting symbol (#19160) --- .../refactors/convertFunctionToEs6Class.ts | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/services/refactors/convertFunctionToEs6Class.ts b/src/services/refactors/convertFunctionToEs6Class.ts index e9f229fa0d7..f5951bd26e4 100644 --- a/src/services/refactors/convertFunctionToEs6Class.ts +++ b/src/services/refactors/convertFunctionToEs6Class.ts @@ -17,16 +17,16 @@ namespace ts.refactor.convertFunctionToES6Class { return undefined; } - const start = context.startPosition; - const node = getTokenAtPosition(context.file, start, /*includeJsDocComment*/ false); - const checker = context.program.getTypeChecker(); - let symbol = checker.getSymbolAtLocation(node); + let symbol = getConstructorSymbol(context); + if (!symbol) { + return undefined; + } - if (symbol && isDeclarationOfFunctionOrClassExpression(symbol)) { + if (isDeclarationOfFunctionOrClassExpression(symbol)) { symbol = (symbol.valueDeclaration as VariableDeclaration).initializer.symbol; } - if (symbol && (symbol.flags & SymbolFlags.Function) && symbol.members && (symbol.members.size > 0)) { + if ((symbol.flags & SymbolFlags.Function) && symbol.members && (symbol.members.size > 0)) { return [ { name: convertFunctionToES6Class.name, @@ -48,11 +48,8 @@ namespace ts.refactor.convertFunctionToES6Class { return undefined; } - const start = context.startPosition; - const sourceFile = context.file; - const checker = context.program.getTypeChecker(); - const token = getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); - const ctorSymbol = checker.getSymbolAtLocation(token); + const { file: sourceFile } = context; + const ctorSymbol = getConstructorSymbol(context); const newLine = context.rulesProvider.getFormatOptions().newLineCharacter; const deletedNodes: Node[] = []; @@ -269,4 +266,10 @@ namespace ts.refactor.convertFunctionToES6Class { return filter(source.modifiers, modifier => modifier.kind === kind); } } -} + + function getConstructorSymbol({ startPosition, file, program }: RefactorContext): Symbol { + const checker = program.getTypeChecker(); + const token = getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false); + return checker.getSymbolAtLocation(token); + } +} \ No newline at end of file From 40222d1a77a32ae412df8bda49f7ff20cfd8c3ba Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 16 Oct 2017 12:57:23 -0700 Subject: [PATCH 024/405] Fix for-in emit under systemjs (#19223) --- src/compiler/transformers/module/system.ts | 5 ++++- .../reference/systemJsForInNoException.js | 19 ++++++++++++++++++ .../systemJsForInNoException.symbols | 16 +++++++++++++++ .../reference/systemJsForInNoException.types | 20 +++++++++++++++++++ .../compiler/systemJsForInNoException.ts | 5 +++++ 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/systemJsForInNoException.js create mode 100644 tests/baselines/reference/systemJsForInNoException.symbols create mode 100644 tests/baselines/reference/systemJsForInNoException.types create mode 100644 tests/cases/compiler/systemJsForInNoException.ts diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index ed943eb90ce..d674546efb9 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -826,7 +826,7 @@ namespace ts { /*needsValue*/ false, createAssignment ) - : createAssignment(node.name, visitNode(node.initializer, destructuringAndImportCallVisitor, isExpression)); + : node.initializer ? createAssignment(node.name, visitNode(node.initializer, destructuringAndImportCallVisitor, isExpression)) : node.name; } /** @@ -1296,6 +1296,9 @@ namespace ts { let expressions: Expression[]; for (const variable of node.declarations) { expressions = append(expressions, transformInitializedVariable(variable, /*isExportedDeclaration*/ false)); + if (!variable.initializer) { + hoistBindingElement(variable); + } } return expressions ? inlineExpressions(expressions) : createOmittedExpression(); diff --git a/tests/baselines/reference/systemJsForInNoException.js b/tests/baselines/reference/systemJsForInNoException.js new file mode 100644 index 00000000000..2ac31e18416 --- /dev/null +++ b/tests/baselines/reference/systemJsForInNoException.js @@ -0,0 +1,19 @@ +//// [systemJsForInNoException.ts] +export const obj = { a: 1 }; +for (var key in obj) + console.log(obj[key]); + +//// [systemJsForInNoException.js] +System.register([], function (exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + var obj, key; + return { + setters: [], + execute: function () { + exports_1("obj", obj = { a: 1 }); + for (key in obj) + console.log(obj[key]); + } + }; +}); diff --git a/tests/baselines/reference/systemJsForInNoException.symbols b/tests/baselines/reference/systemJsForInNoException.symbols new file mode 100644 index 00000000000..4d4d2e0206c --- /dev/null +++ b/tests/baselines/reference/systemJsForInNoException.symbols @@ -0,0 +1,16 @@ +=== tests/cases/compiler/systemJsForInNoException.ts === +export const obj = { a: 1 }; +>obj : Symbol(obj, Decl(systemJsForInNoException.ts, 0, 12)) +>a : Symbol(a, Decl(systemJsForInNoException.ts, 0, 20)) + +for (var key in obj) +>key : Symbol(key, Decl(systemJsForInNoException.ts, 1, 8)) +>obj : Symbol(obj, Decl(systemJsForInNoException.ts, 0, 12)) + + console.log(obj[key]); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>obj : Symbol(obj, Decl(systemJsForInNoException.ts, 0, 12)) +>key : Symbol(key, Decl(systemJsForInNoException.ts, 1, 8)) + diff --git a/tests/baselines/reference/systemJsForInNoException.types b/tests/baselines/reference/systemJsForInNoException.types new file mode 100644 index 00000000000..6d9dbbb6e7b --- /dev/null +++ b/tests/baselines/reference/systemJsForInNoException.types @@ -0,0 +1,20 @@ +=== tests/cases/compiler/systemJsForInNoException.ts === +export const obj = { a: 1 }; +>obj : { a: number; } +>{ a: 1 } : { a: number; } +>a : number +>1 : 1 + +for (var key in obj) +>key : string +>obj : { a: number; } + + console.log(obj[key]); +>console.log(obj[key]) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>obj[key] : any +>obj : { a: number; } +>key : string + diff --git a/tests/cases/compiler/systemJsForInNoException.ts b/tests/cases/compiler/systemJsForInNoException.ts new file mode 100644 index 00000000000..e35c3aa24a3 --- /dev/null +++ b/tests/cases/compiler/systemJsForInNoException.ts @@ -0,0 +1,5 @@ +// @module: system +// @lib: es6,dom +export const obj = { a: 1 }; +for (var key in obj) + console.log(obj[key]); \ No newline at end of file From 2cb0403e2d6165e1eb3731173164f307f556ef0a Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 16 Oct 2017 13:02:15 -0700 Subject: [PATCH 025/405] Support 'package.json' not in package root (#19133) * Support 'package.json' not in package root * Test "foo/@bar" * More tests, and don't use "types" from the root package.json if not loading the root module --- src/compiler/moduleNameResolver.ts | 40 +++++++++++++------ ...Resolution_packageJson_notAtPackageRoot.js | 20 ++++++++++ ...ution_packageJson_notAtPackageRoot.symbols | 8 ++++ ...on_packageJson_notAtPackageRoot.trace.json | 14 +++++++ ...olution_packageJson_notAtPackageRoot.types | 8 ++++ ...Json_notAtPackageRoot_fakeScopedPackage.js | 20 ++++++++++ ...notAtPackageRoot_fakeScopedPackage.symbols | 8 ++++ ...AtPackageRoot_fakeScopedPackage.trace.json | 14 +++++++ ...n_notAtPackageRoot_fakeScopedPackage.types | 8 ++++ ...Resolution_packageJson_yesAtPackageRoot.js | 18 +++++++++ ...ution_packageJson_yesAtPackageRoot.symbols | 4 ++ ...on_packageJson_yesAtPackageRoot.trace.json | 22 ++++++++++ ...olution_packageJson_yesAtPackageRoot.types | 4 ++ ...Json_yesAtPackageRoot_fakeScopedPackage.js | 20 ++++++++++ ...yesAtPackageRoot_fakeScopedPackage.symbols | 4 ++ ...AtPackageRoot_fakeScopedPackage.trace.json | 22 ++++++++++ ...n_yesAtPackageRoot_fakeScopedPackage.types | 4 ++ ...Resolution_packageJson_notAtPackageRoot.ts | 16 ++++++++ ...Json_notAtPackageRoot_fakeScopedPackage.ts | 16 ++++++++ ...Resolution_packageJson_yesAtPackageRoot.ts | 14 +++++++ ...Json_yesAtPackageRoot_fakeScopedPackage.ts | 16 ++++++++ 21 files changed, 288 insertions(+), 12 deletions(-) create mode 100644 tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.js create mode 100644 tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.symbols create mode 100644 tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.trace.json create mode 100644 tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.types create mode 100644 tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.js create mode 100644 tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.symbols create mode 100644 tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.trace.json create mode 100644 tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.types create mode 100644 tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.js create mode 100644 tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.symbols create mode 100644 tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.trace.json create mode 100644 tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.types create mode 100644 tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.js create mode 100644 tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.symbols create mode 100644 tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.trace.json create mode 100644 tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.types create mode 100644 tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot.ts create mode 100644 tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.ts create mode 100644 tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot.ts create mode 100644 tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.ts diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index ac83dd41311..08178d3d16a 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -77,16 +77,20 @@ namespace ts { traceEnabled: boolean; } - interface PackageJson { - name?: string; - version?: string; + /** Just the fields that we use for module resolution. */ + interface PackageJsonPathFields { typings?: string; types?: string; main?: string; } + interface PackageJson extends PackageJsonPathFields { + name?: string; + version?: string; + } + /** Reads from "main" or "types"/"typings" depending on `extensions`. */ - function tryReadPackageJsonFields(readTypes: boolean, jsonContent: PackageJson, baseDirectory: string, state: ModuleResolutionState): string | undefined { + function tryReadPackageJsonFields(readTypes: boolean, jsonContent: PackageJsonPathFields, baseDirectory: string, state: ModuleResolutionState): string | undefined { return readTypes ? tryReadFromField("typings") || tryReadFromField("types") : tryReadFromField("main"); function tryReadFromField(fieldName: "typings" | "types" | "main"): string | undefined { @@ -886,7 +890,7 @@ namespace ts { return withPackageId(packageId, loadNodeModuleFromDirectoryWorker(extensions, candidate, failedLookupLocations, onlyRecordFailures, state, packageJsonContent)); } - function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: string, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState, packageJsonContent: PackageJson | undefined): PathAndExtension | undefined { + function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: string, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState, packageJsonContent: PackageJsonPathFields | undefined): PathAndExtension | undefined { const fromPackageJson = packageJsonContent && loadModuleFromPackageJson(packageJsonContent, extensions, candidate, failedLookupLocations, state); if (fromPackageJson) { return fromPackageJson; @@ -901,7 +905,7 @@ namespace ts { failedLookupLocations: Push, onlyRecordFailures: boolean, { host, traceEnabled }: ModuleResolutionState, - ): { packageJsonContent: PackageJson | undefined, packageId: PackageId | undefined } { + ): { found: boolean, packageJsonContent: PackageJsonPathFields | undefined, packageId: PackageId | undefined } { const directoryExists = !onlyRecordFailures && directoryProbablyExists(nodeModuleDirectory, host); const packageJsonPath = pathToPackageJson(nodeModuleDirectory); if (directoryExists && host.fileExists(packageJsonPath)) { @@ -912,7 +916,7 @@ namespace ts { const packageId: PackageId = typeof packageJsonContent.name === "string" && typeof packageJsonContent.version === "string" ? { name: packageJsonContent.name, subModuleName, version: packageJsonContent.version } : undefined; - return { packageJsonContent, packageId }; + return { found: true, packageJsonContent, packageId }; } else { if (directoryExists && traceEnabled) { @@ -920,11 +924,11 @@ namespace ts { } // record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results failedLookupLocations.push(packageJsonPath); - return { packageJsonContent: undefined, packageId: undefined }; + return { found: false, packageJsonContent: undefined, packageId: undefined }; } } - function loadModuleFromPackageJson(jsonContent: PackageJson, extensions: Extensions, candidate: string, failedLookupLocations: Push, state: ModuleResolutionState): PathAndExtension | undefined { + function loadModuleFromPackageJson(jsonContent: PackageJsonPathFields, extensions: Extensions, candidate: string, failedLookupLocations: Push, state: ModuleResolutionState): PathAndExtension | undefined { const file = tryReadPackageJsonFields(extensions !== Extensions.JavaScript, jsonContent, candidate, state); if (!file) { return undefined; @@ -976,10 +980,22 @@ namespace ts { } function loadModuleFromNodeModulesFolder(extensions: Extensions, moduleName: string, nodeModulesFolder: string, nodeModulesFolderExists: boolean, failedLookupLocations: Push, state: ModuleResolutionState): Resolved | undefined { - const { packageName, rest } = getPackageName(moduleName); - const packageRootPath = combinePaths(nodeModulesFolder, packageName); - const { packageJsonContent, packageId } = getPackageJsonInfo(packageRootPath, rest, failedLookupLocations, !nodeModulesFolderExists, state); const candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName)); + // First look for a nested package.json, as in `node_modules/foo/bar/package.json`. + let packageJsonContent: PackageJsonPathFields | undefined; + let packageId: PackageId | undefined; + const packageInfo = getPackageJsonInfo(candidate, "", failedLookupLocations, /*onlyRecordFailures*/ !nodeModulesFolderExists, state); + if (packageInfo.found) { + ({ packageJsonContent, packageId } = packageInfo); + } + else { + const { packageName, rest } = getPackageName(moduleName); + if (rest !== "") { // If "rest" is empty, we just did this search above. + const packageRootPath = combinePaths(nodeModulesFolder, packageName); + // Don't use a "types" or "main" from here because we're not loading the root, but a subdirectory -- just here for the packageId. + packageId = getPackageJsonInfo(packageRootPath, rest, failedLookupLocations, !nodeModulesFolderExists, state).packageId; + } + } const pathAndExtension = loadModuleFromFile(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state) || loadNodeModuleFromDirectoryWorker(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state, packageJsonContent); return withPackageId(packageId, pathAndExtension); diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.js b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.js new file mode 100644 index 00000000000..941774f4d35 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.js @@ -0,0 +1,20 @@ +//// [tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot.ts] //// + +//// [package.json] +// Loads from a "fake" nested package.json, not from the one at the root. + +{ "types": "types.d.ts" } + +//// [package.json] +{} + +//// [types.d.ts] +export const x: number; + +//// [a.ts] +import { x } from "foo/bar"; + + +//// [a.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.symbols b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.symbols new file mode 100644 index 00000000000..57aaa9a96ef --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.symbols @@ -0,0 +1,8 @@ +=== /a.ts === +import { x } from "foo/bar"; +>x : Symbol(x, Decl(a.ts, 0, 8)) + +=== /node_modules/foo/bar/types.d.ts === +export const x: number; +>x : Symbol(x, Decl(types.d.ts, 0, 12)) + diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.trace.json b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.trace.json new file mode 100644 index 00000000000..bf5f0b0bbef --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.trace.json @@ -0,0 +1,14 @@ +[ + "======== Resolving module 'foo/bar' from '/a.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'foo/bar' from 'node_modules' folder, target file type 'TypeScript'.", + "Found 'package.json' at '/node_modules/foo/bar/package.json'.", + "File '/node_modules/foo/bar.ts' does not exist.", + "File '/node_modules/foo/bar.tsx' does not exist.", + "File '/node_modules/foo/bar.d.ts' does not exist.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'types.d.ts' that references '/node_modules/foo/bar/types.d.ts'.", + "File '/node_modules/foo/bar/types.d.ts' exist - use it as a name resolution result.", + "Resolving real path for '/node_modules/foo/bar/types.d.ts', result '/node_modules/foo/bar/types.d.ts'.", + "======== Module name 'foo/bar' was successfully resolved to '/node_modules/foo/bar/types.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.types b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.types new file mode 100644 index 00000000000..68a1585d768 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.types @@ -0,0 +1,8 @@ +=== /a.ts === +import { x } from "foo/bar"; +>x : number + +=== /node_modules/foo/bar/types.d.ts === +export const x: number; +>x : number + diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.js b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.js new file mode 100644 index 00000000000..45398289241 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.js @@ -0,0 +1,20 @@ +//// [tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.ts] //// + +//// [package.json] +// Copy of `moduleResolution_packageJson_notAtPackageRoot` with `foo/@bar` instead of `foo/bar`. Should behave identically. + +{ "types": "types.d.ts" } + +//// [package.json] +{} + +//// [types.d.ts] +export const x: number; + +//// [a.ts] +import { x } from "foo/@bar"; + + +//// [a.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.symbols b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.symbols new file mode 100644 index 00000000000..de21d67b629 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.symbols @@ -0,0 +1,8 @@ +=== /a.ts === +import { x } from "foo/@bar"; +>x : Symbol(x, Decl(a.ts, 0, 8)) + +=== /node_modules/foo/@bar/types.d.ts === +export const x: number; +>x : Symbol(x, Decl(types.d.ts, 0, 12)) + diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.trace.json b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.trace.json new file mode 100644 index 00000000000..72d413d0b2c --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.trace.json @@ -0,0 +1,14 @@ +[ + "======== Resolving module 'foo/@bar' from '/a.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'foo/@bar' from 'node_modules' folder, target file type 'TypeScript'.", + "Found 'package.json' at '/node_modules/foo/@bar/package.json'.", + "File '/node_modules/foo/@bar.ts' does not exist.", + "File '/node_modules/foo/@bar.tsx' does not exist.", + "File '/node_modules/foo/@bar.d.ts' does not exist.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'types.d.ts' that references '/node_modules/foo/@bar/types.d.ts'.", + "File '/node_modules/foo/@bar/types.d.ts' exist - use it as a name resolution result.", + "Resolving real path for '/node_modules/foo/@bar/types.d.ts', result '/node_modules/foo/@bar/types.d.ts'.", + "======== Module name 'foo/@bar' was successfully resolved to '/node_modules/foo/@bar/types.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.types b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.types new file mode 100644 index 00000000000..6d8894ebce1 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.types @@ -0,0 +1,8 @@ +=== /a.ts === +import { x } from "foo/@bar"; +>x : number + +=== /node_modules/foo/@bar/types.d.ts === +export const x: number; +>x : number + diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.js b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.js new file mode 100644 index 00000000000..ed006b0e62d --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.js @@ -0,0 +1,18 @@ +//// [tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot.ts] //// + +//// [index.js] +not read + +//// [package.json] +{ "name": "foo", "version": "1.2.3", "types": "types.d.ts" } + +//// [types.d.ts] +export const x = 0; + +//// [a.ts] +import { x } from "foo/bar"; + + +//// [a.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.symbols b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.symbols new file mode 100644 index 00000000000..c037bb343b0 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.symbols @@ -0,0 +1,4 @@ +=== /a.ts === +import { x } from "foo/bar"; +>x : Symbol(x, Decl(a.ts, 0, 8)) + diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.trace.json b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.trace.json new file mode 100644 index 00000000000..3a87769891b --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.trace.json @@ -0,0 +1,22 @@ +[ + "======== Resolving module 'foo/bar' from '/a.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'foo/bar' from 'node_modules' folder, target file type 'TypeScript'.", + "File '/node_modules/foo/bar/package.json' does not exist.", + "Found 'package.json' at '/node_modules/foo/package.json'.", + "File '/node_modules/foo/bar.ts' does not exist.", + "File '/node_modules/foo/bar.tsx' does not exist.", + "File '/node_modules/foo/bar.d.ts' does not exist.", + "File '/node_modules/foo/bar/index.ts' does not exist.", + "File '/node_modules/foo/bar/index.tsx' does not exist.", + "File '/node_modules/foo/bar/index.d.ts' does not exist.", + "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", + "Loading module 'foo/bar' from 'node_modules' folder, target file type 'JavaScript'.", + "File '/node_modules/foo/bar/package.json' does not exist.", + "Found 'package.json' at '/node_modules/foo/package.json'.", + "File '/node_modules/foo/bar.js' does not exist.", + "File '/node_modules/foo/bar.jsx' does not exist.", + "File '/node_modules/foo/bar/index.js' exist - use it as a name resolution result.", + "Resolving real path for '/node_modules/foo/bar/index.js', result '/node_modules/foo/bar/index.js'.", + "======== Module name 'foo/bar' was successfully resolved to '/node_modules/foo/bar/index.js'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.types b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.types new file mode 100644 index 00000000000..460aa4b8f05 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.types @@ -0,0 +1,4 @@ +=== /a.ts === +import { x } from "foo/bar"; +>x : any + diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.js b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.js new file mode 100644 index 00000000000..129feb6060f --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.js @@ -0,0 +1,20 @@ +//// [tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.ts] //// + +//// [index.js] +// Copy of `moduleResolution_packageJson_notAtPackageRoot` with `foo/@bar` instead of `foo/bar`. Should behave identically. + +not read + +//// [package.json] +{ "name": "foo", "version": "1.2.3", "types": "types.d.ts" } + +//// [types.d.ts] +export const x = 0; + +//// [a.ts] +import { x } from "foo/@bar"; + + +//// [a.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.symbols b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.symbols new file mode 100644 index 00000000000..d1c3839b87b --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.symbols @@ -0,0 +1,4 @@ +=== /a.ts === +import { x } from "foo/@bar"; +>x : Symbol(x, Decl(a.ts, 0, 8)) + diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.trace.json b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.trace.json new file mode 100644 index 00000000000..c28189a1f7d --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.trace.json @@ -0,0 +1,22 @@ +[ + "======== Resolving module 'foo/@bar' from '/a.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'foo/@bar' from 'node_modules' folder, target file type 'TypeScript'.", + "File '/node_modules/foo/@bar/package.json' does not exist.", + "Found 'package.json' at '/node_modules/foo/package.json'.", + "File '/node_modules/foo/@bar.ts' does not exist.", + "File '/node_modules/foo/@bar.tsx' does not exist.", + "File '/node_modules/foo/@bar.d.ts' does not exist.", + "File '/node_modules/foo/@bar/index.ts' does not exist.", + "File '/node_modules/foo/@bar/index.tsx' does not exist.", + "File '/node_modules/foo/@bar/index.d.ts' does not exist.", + "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", + "Loading module 'foo/@bar' from 'node_modules' folder, target file type 'JavaScript'.", + "File '/node_modules/foo/@bar/package.json' does not exist.", + "Found 'package.json' at '/node_modules/foo/package.json'.", + "File '/node_modules/foo/@bar.js' does not exist.", + "File '/node_modules/foo/@bar.jsx' does not exist.", + "File '/node_modules/foo/@bar/index.js' exist - use it as a name resolution result.", + "Resolving real path for '/node_modules/foo/@bar/index.js', result '/node_modules/foo/@bar/index.js'.", + "======== Module name 'foo/@bar' was successfully resolved to '/node_modules/foo/@bar/index.js'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.types b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.types new file mode 100644 index 00000000000..47b12eea7a1 --- /dev/null +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.types @@ -0,0 +1,4 @@ +=== /a.ts === +import { x } from "foo/@bar"; +>x : any + diff --git a/tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot.ts b/tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot.ts new file mode 100644 index 00000000000..a93ea832b73 --- /dev/null +++ b/tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot.ts @@ -0,0 +1,16 @@ +// @noImplicitReferences: true +// @traceResolution: true + +// Loads from a "fake" nested package.json, not from the one at the root. + +// @Filename: /node_modules/foo/bar/package.json +{ "types": "types.d.ts" } + +// @Filename: /node_modules/foo/package.json +{} + +// @Filename: /node_modules/foo/bar/types.d.ts +export const x: number; + +// @Filename: /a.ts +import { x } from "foo/bar"; diff --git a/tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.ts b/tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.ts new file mode 100644 index 00000000000..55e3963357f --- /dev/null +++ b/tests/cases/compiler/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.ts @@ -0,0 +1,16 @@ +// @noImplicitReferences: true +// @traceResolution: true + +// Copy of `moduleResolution_packageJson_notAtPackageRoot` with `foo/@bar` instead of `foo/bar`. Should behave identically. + +// @Filename: /node_modules/foo/@bar/package.json +{ "types": "types.d.ts" } + +// @Filename: /node_modules/foo/package.json +{} + +// @Filename: /node_modules/foo/@bar/types.d.ts +export const x: number; + +// @Filename: /a.ts +import { x } from "foo/@bar"; diff --git a/tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot.ts b/tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot.ts new file mode 100644 index 00000000000..64e46c4e710 --- /dev/null +++ b/tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot.ts @@ -0,0 +1,14 @@ +// @noImplicitReferences: true +// @traceResolution: true + +// @Filename: /node_modules/foo/bar/index.js +not read + +// @Filename: /node_modules/foo/package.json +{ "name": "foo", "version": "1.2.3", "types": "types.d.ts" } + +// @Filename: /node_modules/foo/types.d.ts +export const x = 0; + +// @Filename: /a.ts +import { x } from "foo/bar"; diff --git a/tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.ts b/tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.ts new file mode 100644 index 00000000000..9b9f35b41e7 --- /dev/null +++ b/tests/cases/compiler/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.ts @@ -0,0 +1,16 @@ +// @noImplicitReferences: true +// @traceResolution: true + +// Copy of `moduleResolution_packageJson_notAtPackageRoot` with `foo/@bar` instead of `foo/bar`. Should behave identically. + +// @Filename: /node_modules/foo/@bar/index.js +not read + +// @Filename: /node_modules/foo/package.json +{ "name": "foo", "version": "1.2.3", "types": "types.d.ts" } + +// @Filename: /node_modules/foo/types.d.ts +export const x = 0; + +// @Filename: /a.ts +import { x } from "foo/@bar"; From 734bda833c2236ab2360e798b9465425e80f62ab Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 16 Oct 2017 13:06:15 -0700 Subject: [PATCH 026/405] Add comments about why we need two methods that return compilerOptions --- src/server/project.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/server/project.ts b/src/server/project.ts index ca6e82ec4be..9c3fab63d23 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -242,12 +242,14 @@ namespace ts.server { this.markAsDirty(); } + // Method of LanguageServiceHost getCompilationSettings() { return this.compilerOptions; } + // Method to support public API getCompilerOptions() { - return this.compilerOptions; + return this.getCompilationSettings(); } getNewLine() { From aea7e9a7a812d02bf36fd0f36192fb81d8433afc Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 16 Oct 2017 14:17:55 -0700 Subject: [PATCH 027/405] Fix instantiated generic mixin declaration emit (#19144) * Fix #18545, dont use declared type of class expression * Accept API Baselines * Add thus far unused flag from node builder * Accept baseline update --- src/compiler/checker.ts | 2 +- .../declarationNoDanglingGenerics.js | 125 ++++++++++++++++++ .../declarationNoDanglingGenerics.symbols | 82 ++++++++++++ .../declarationNoDanglingGenerics.types | 98 ++++++++++++++ .../compiler/declarationNoDanglingGenerics.ts | 33 +++++ 5 files changed, 339 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/declarationNoDanglingGenerics.js create mode 100644 tests/baselines/reference/declarationNoDanglingGenerics.symbols create mode 100644 tests/baselines/reference/declarationNoDanglingGenerics.types create mode 100644 tests/cases/compiler/declarationNoDanglingGenerics.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 32086157552..8f8be4a10ef 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3398,7 +3398,7 @@ namespace ts { else if (flags & TypeFormatFlags.WriteClassExpressionAsTypeLiteral && type.symbol.valueDeclaration && type.symbol.valueDeclaration.kind === SyntaxKind.ClassExpression) { - writeAnonymousType(getDeclaredTypeOfClassOrInterface(type.symbol), flags); + writeAnonymousType(type, flags); } else { // Write the type reference in the format f.g.C where A and B are type arguments diff --git a/tests/baselines/reference/declarationNoDanglingGenerics.js b/tests/baselines/reference/declarationNoDanglingGenerics.js new file mode 100644 index 00000000000..9045be6827b --- /dev/null +++ b/tests/baselines/reference/declarationNoDanglingGenerics.js @@ -0,0 +1,125 @@ +//// [declarationNoDanglingGenerics.ts] +const kindCache: { [kind: string]: boolean } = {}; + +function register(kind: string): void | never { + if (kindCache[kind]) { + throw new Error(`Class with kind "${kind}" is already registered.`); + } + kindCache[kind] = true; +} + +function ClassFactory(kind: TKind) { + register(kind); + + return class { + static readonly THE_KIND: TKind = kind; + readonly kind: TKind = kind; + }; +} + +class Kinds { + static readonly A = "A"; + static readonly B = "B"; + static readonly C = "C"; +} + +export class AKind extends ClassFactory(Kinds.A) { +} + +export class BKind extends ClassFactory(Kinds.B) { +} + +export class CKind extends ClassFactory(Kinds.C) { +} + +//// [declarationNoDanglingGenerics.js] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +var kindCache = {}; +function register(kind) { + if (kindCache[kind]) { + throw new Error("Class with kind \"" + kind + "\" is already registered."); + } + kindCache[kind] = true; +} +function ClassFactory(kind) { + register(kind); + return _a = /** @class */ (function () { + function class_1() { + this.kind = kind; + } + return class_1; + }()), + _a.THE_KIND = kind, + _a; + var _a; +} +var Kinds = /** @class */ (function () { + function Kinds() { + } + Kinds.A = "A"; + Kinds.B = "B"; + Kinds.C = "C"; + return Kinds; +}()); +var AKind = /** @class */ (function (_super) { + __extends(AKind, _super); + function AKind() { + return _super !== null && _super.apply(this, arguments) || this; + } + return AKind; +}(ClassFactory(Kinds.A))); +exports.AKind = AKind; +var BKind = /** @class */ (function (_super) { + __extends(BKind, _super); + function BKind() { + return _super !== null && _super.apply(this, arguments) || this; + } + return BKind; +}(ClassFactory(Kinds.B))); +exports.BKind = BKind; +var CKind = /** @class */ (function (_super) { + __extends(CKind, _super); + function CKind() { + return _super !== null && _super.apply(this, arguments) || this; + } + return CKind; +}(ClassFactory(Kinds.C))); +exports.CKind = CKind; + + +//// [declarationNoDanglingGenerics.d.ts] +declare const AKind_base: { + new (): { + readonly kind: "A"; + }; + readonly THE_KIND: "A"; +}; +export declare class AKind extends AKind_base { +} +declare const BKind_base: { + new (): { + readonly kind: "B"; + }; + readonly THE_KIND: "B"; +}; +export declare class BKind extends BKind_base { +} +declare const CKind_base: { + new (): { + readonly kind: "C"; + }; + readonly THE_KIND: "C"; +}; +export declare class CKind extends CKind_base { +} diff --git a/tests/baselines/reference/declarationNoDanglingGenerics.symbols b/tests/baselines/reference/declarationNoDanglingGenerics.symbols new file mode 100644 index 00000000000..512bf95d4bb --- /dev/null +++ b/tests/baselines/reference/declarationNoDanglingGenerics.symbols @@ -0,0 +1,82 @@ +=== tests/cases/compiler/declarationNoDanglingGenerics.ts === +const kindCache: { [kind: string]: boolean } = {}; +>kindCache : Symbol(kindCache, Decl(declarationNoDanglingGenerics.ts, 0, 5)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 0, 20)) + +function register(kind: string): void | never { +>register : Symbol(register, Decl(declarationNoDanglingGenerics.ts, 0, 50)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 2, 18)) + + if (kindCache[kind]) { +>kindCache : Symbol(kindCache, Decl(declarationNoDanglingGenerics.ts, 0, 5)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 2, 18)) + + throw new Error(`Class with kind "${kind}" is already registered.`); +>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 2, 18)) + } + kindCache[kind] = true; +>kindCache : Symbol(kindCache, Decl(declarationNoDanglingGenerics.ts, 0, 5)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 2, 18)) +} + +function ClassFactory(kind: TKind) { +>ClassFactory : Symbol(ClassFactory, Decl(declarationNoDanglingGenerics.ts, 7, 1)) +>TKind : Symbol(TKind, Decl(declarationNoDanglingGenerics.ts, 9, 22)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 9, 44)) +>TKind : Symbol(TKind, Decl(declarationNoDanglingGenerics.ts, 9, 22)) + + register(kind); +>register : Symbol(register, Decl(declarationNoDanglingGenerics.ts, 0, 50)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 9, 44)) + + return class { + static readonly THE_KIND: TKind = kind; +>THE_KIND : Symbol((Anonymous class).THE_KIND, Decl(declarationNoDanglingGenerics.ts, 12, 16)) +>TKind : Symbol(TKind, Decl(declarationNoDanglingGenerics.ts, 9, 22)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 9, 44)) + + readonly kind: TKind = kind; +>kind : Symbol((Anonymous class).kind, Decl(declarationNoDanglingGenerics.ts, 13, 43)) +>TKind : Symbol(TKind, Decl(declarationNoDanglingGenerics.ts, 9, 22)) +>kind : Symbol(kind, Decl(declarationNoDanglingGenerics.ts, 9, 44)) + + }; +} + +class Kinds { +>Kinds : Symbol(Kinds, Decl(declarationNoDanglingGenerics.ts, 16, 1)) + + static readonly A = "A"; +>A : Symbol(Kinds.A, Decl(declarationNoDanglingGenerics.ts, 18, 13)) + + static readonly B = "B"; +>B : Symbol(Kinds.B, Decl(declarationNoDanglingGenerics.ts, 19, 26)) + + static readonly C = "C"; +>C : Symbol(Kinds.C, Decl(declarationNoDanglingGenerics.ts, 20, 26)) +} + +export class AKind extends ClassFactory(Kinds.A) { +>AKind : Symbol(AKind, Decl(declarationNoDanglingGenerics.ts, 22, 1)) +>ClassFactory : Symbol(ClassFactory, Decl(declarationNoDanglingGenerics.ts, 7, 1)) +>Kinds.A : Symbol(Kinds.A, Decl(declarationNoDanglingGenerics.ts, 18, 13)) +>Kinds : Symbol(Kinds, Decl(declarationNoDanglingGenerics.ts, 16, 1)) +>A : Symbol(Kinds.A, Decl(declarationNoDanglingGenerics.ts, 18, 13)) +} + +export class BKind extends ClassFactory(Kinds.B) { +>BKind : Symbol(BKind, Decl(declarationNoDanglingGenerics.ts, 25, 1)) +>ClassFactory : Symbol(ClassFactory, Decl(declarationNoDanglingGenerics.ts, 7, 1)) +>Kinds.B : Symbol(Kinds.B, Decl(declarationNoDanglingGenerics.ts, 19, 26)) +>Kinds : Symbol(Kinds, Decl(declarationNoDanglingGenerics.ts, 16, 1)) +>B : Symbol(Kinds.B, Decl(declarationNoDanglingGenerics.ts, 19, 26)) +} + +export class CKind extends ClassFactory(Kinds.C) { +>CKind : Symbol(CKind, Decl(declarationNoDanglingGenerics.ts, 28, 1)) +>ClassFactory : Symbol(ClassFactory, Decl(declarationNoDanglingGenerics.ts, 7, 1)) +>Kinds.C : Symbol(Kinds.C, Decl(declarationNoDanglingGenerics.ts, 20, 26)) +>Kinds : Symbol(Kinds, Decl(declarationNoDanglingGenerics.ts, 16, 1)) +>C : Symbol(Kinds.C, Decl(declarationNoDanglingGenerics.ts, 20, 26)) +} diff --git a/tests/baselines/reference/declarationNoDanglingGenerics.types b/tests/baselines/reference/declarationNoDanglingGenerics.types new file mode 100644 index 00000000000..c650839be16 --- /dev/null +++ b/tests/baselines/reference/declarationNoDanglingGenerics.types @@ -0,0 +1,98 @@ +=== tests/cases/compiler/declarationNoDanglingGenerics.ts === +const kindCache: { [kind: string]: boolean } = {}; +>kindCache : { [kind: string]: boolean; } +>kind : string +>{} : {} + +function register(kind: string): void | never { +>register : (kind: string) => void +>kind : string + + if (kindCache[kind]) { +>kindCache[kind] : boolean +>kindCache : { [kind: string]: boolean; } +>kind : string + + throw new Error(`Class with kind "${kind}" is already registered.`); +>new Error(`Class with kind "${kind}" is already registered.`) : Error +>Error : ErrorConstructor +>`Class with kind "${kind}" is already registered.` : string +>kind : string + } + kindCache[kind] = true; +>kindCache[kind] = true : true +>kindCache[kind] : boolean +>kindCache : { [kind: string]: boolean; } +>kind : string +>true : true +} + +function ClassFactory(kind: TKind) { +>ClassFactory : (kind: TKind) => typeof (Anonymous class) +>TKind : TKind +>kind : TKind +>TKind : TKind + + register(kind); +>register(kind) : void +>register : (kind: string) => void +>kind : TKind + + return class { +>class { static readonly THE_KIND: TKind = kind; readonly kind: TKind = kind; } : typeof (Anonymous class) + + static readonly THE_KIND: TKind = kind; +>THE_KIND : TKind +>TKind : TKind +>kind : TKind + + readonly kind: TKind = kind; +>kind : TKind +>TKind : TKind +>kind : TKind + + }; +} + +class Kinds { +>Kinds : Kinds + + static readonly A = "A"; +>A : "A" +>"A" : "A" + + static readonly B = "B"; +>B : "B" +>"B" : "B" + + static readonly C = "C"; +>C : "C" +>"C" : "C" +} + +export class AKind extends ClassFactory(Kinds.A) { +>AKind : AKind +>ClassFactory(Kinds.A) : ClassFactory<"A">.(Anonymous class) +>ClassFactory : (kind: TKind) => typeof (Anonymous class) +>Kinds.A : "A" +>Kinds : typeof Kinds +>A : "A" +} + +export class BKind extends ClassFactory(Kinds.B) { +>BKind : BKind +>ClassFactory(Kinds.B) : ClassFactory<"B">.(Anonymous class) +>ClassFactory : (kind: TKind) => typeof (Anonymous class) +>Kinds.B : "B" +>Kinds : typeof Kinds +>B : "B" +} + +export class CKind extends ClassFactory(Kinds.C) { +>CKind : CKind +>ClassFactory(Kinds.C) : ClassFactory<"C">.(Anonymous class) +>ClassFactory : (kind: TKind) => typeof (Anonymous class) +>Kinds.C : "C" +>Kinds : typeof Kinds +>C : "C" +} diff --git a/tests/cases/compiler/declarationNoDanglingGenerics.ts b/tests/cases/compiler/declarationNoDanglingGenerics.ts new file mode 100644 index 00000000000..baedcc8a74e --- /dev/null +++ b/tests/cases/compiler/declarationNoDanglingGenerics.ts @@ -0,0 +1,33 @@ +// @declaration: true +const kindCache: { [kind: string]: boolean } = {}; + +function register(kind: string): void | never { + if (kindCache[kind]) { + throw new Error(`Class with kind "${kind}" is already registered.`); + } + kindCache[kind] = true; +} + +function ClassFactory(kind: TKind) { + register(kind); + + return class { + static readonly THE_KIND: TKind = kind; + readonly kind: TKind = kind; + }; +} + +class Kinds { + static readonly A = "A"; + static readonly B = "B"; + static readonly C = "C"; +} + +export class AKind extends ClassFactory(Kinds.A) { +} + +export class BKind extends ClassFactory(Kinds.B) { +} + +export class CKind extends ClassFactory(Kinds.C) { +} \ No newline at end of file From 9563246993fdc4d323db60179a8bfd84a943cd70 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 16 Oct 2017 14:26:16 -0700 Subject: [PATCH 028/405] Do not reduce subtypes of awaited union type --- src/compiler/checker.ts | 2 +- .../baselines/reference/awaitUnionPromise.js | 89 +++++++++++++++++++ .../reference/awaitUnionPromise.symbols | 67 ++++++++++++++ .../reference/awaitUnionPromise.types | 76 ++++++++++++++++ tests/cases/compiler/awaitUnionPromise.ts | 19 ++++ 5 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/awaitUnionPromise.js create mode 100644 tests/baselines/reference/awaitUnionPromise.symbols create mode 100644 tests/baselines/reference/awaitUnionPromise.types create mode 100644 tests/cases/compiler/awaitUnionPromise.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9347329e624..9934793ace5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19680,7 +19680,7 @@ namespace ts { return undefined; } - return typeAsAwaitable.awaitedTypeOfType = getUnionType(types, /*subtypeReduction*/ true); + return typeAsAwaitable.awaitedTypeOfType = getUnionType(types); } const promisedType = getPromisedTypeOfPromise(type); diff --git a/tests/baselines/reference/awaitUnionPromise.js b/tests/baselines/reference/awaitUnionPromise.js new file mode 100644 index 00000000000..df4c937fc63 --- /dev/null +++ b/tests/baselines/reference/awaitUnionPromise.js @@ -0,0 +1,89 @@ +//// [awaitUnionPromise.ts] +/// @target: es2015 +// https://github.com/Microsoft/TypeScript/issues/18186 + +class AsyncEnumeratorDone { }; + +interface IAsyncEnumerator { + next1(): Promise; + next2(): Promise | Promise; + next3(): Promise; + next4(): Promise; +} + +async function main() { + const x: IAsyncEnumerator = null; + let a = await x.next1(); + let b = await x.next2(); + let c = await x.next3(); + let d = await x.next4(); +} + +//// [awaitUnionPromise.js] +/// @target: es2015 +// https://github.com/Microsoft/TypeScript/issues/18186 +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var AsyncEnumeratorDone = /** @class */ (function () { + function AsyncEnumeratorDone() { + } + return AsyncEnumeratorDone; +}()); +; +function main() { + return __awaiter(this, void 0, void 0, function () { + var x, a, b, c, d; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + x = null; + return [4 /*yield*/, x.next1()]; + case 1: + a = _a.sent(); + return [4 /*yield*/, x.next2()]; + case 2: + b = _a.sent(); + return [4 /*yield*/, x.next3()]; + case 3: + c = _a.sent(); + return [4 /*yield*/, x.next4()]; + case 4: + d = _a.sent(); + return [2 /*return*/]; + } + }); + }); +} diff --git a/tests/baselines/reference/awaitUnionPromise.symbols b/tests/baselines/reference/awaitUnionPromise.symbols new file mode 100644 index 00000000000..fb26ba1bfac --- /dev/null +++ b/tests/baselines/reference/awaitUnionPromise.symbols @@ -0,0 +1,67 @@ +=== tests/cases/compiler/awaitUnionPromise.ts === +/// @target: es2015 +// https://github.com/Microsoft/TypeScript/issues/18186 + +class AsyncEnumeratorDone { }; +>AsyncEnumeratorDone : Symbol(AsyncEnumeratorDone, Decl(awaitUnionPromise.ts, 0, 0)) + +interface IAsyncEnumerator { +>IAsyncEnumerator : Symbol(IAsyncEnumerator, Decl(awaitUnionPromise.ts, 3, 30)) +>T : Symbol(T, Decl(awaitUnionPromise.ts, 5, 27)) + + next1(): Promise; +>next1 : Symbol(IAsyncEnumerator.next1, Decl(awaitUnionPromise.ts, 5, 31)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(awaitUnionPromise.ts, 5, 27)) +>AsyncEnumeratorDone : Symbol(AsyncEnumeratorDone, Decl(awaitUnionPromise.ts, 0, 0)) + + next2(): Promise | Promise; +>next2 : Symbol(IAsyncEnumerator.next2, Decl(awaitUnionPromise.ts, 6, 46)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(awaitUnionPromise.ts, 5, 27)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --)) +>AsyncEnumeratorDone : Symbol(AsyncEnumeratorDone, Decl(awaitUnionPromise.ts, 0, 0)) + + next3(): Promise; +>next3 : Symbol(IAsyncEnumerator.next3, Decl(awaitUnionPromise.ts, 7, 55)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(awaitUnionPromise.ts, 5, 27)) + + next4(): Promise; +>next4 : Symbol(IAsyncEnumerator.next4, Decl(awaitUnionPromise.ts, 8, 29)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(awaitUnionPromise.ts, 5, 27)) +>x : Symbol(x, Decl(awaitUnionPromise.ts, 9, 26)) +} + +async function main() { +>main : Symbol(main, Decl(awaitUnionPromise.ts, 10, 1)) + + const x: IAsyncEnumerator = null; +>x : Symbol(x, Decl(awaitUnionPromise.ts, 13, 9)) +>IAsyncEnumerator : Symbol(IAsyncEnumerator, Decl(awaitUnionPromise.ts, 3, 30)) + + let a = await x.next1(); +>a : Symbol(a, Decl(awaitUnionPromise.ts, 14, 7)) +>x.next1 : Symbol(IAsyncEnumerator.next1, Decl(awaitUnionPromise.ts, 5, 31)) +>x : Symbol(x, Decl(awaitUnionPromise.ts, 13, 9)) +>next1 : Symbol(IAsyncEnumerator.next1, Decl(awaitUnionPromise.ts, 5, 31)) + + let b = await x.next2(); +>b : Symbol(b, Decl(awaitUnionPromise.ts, 15, 7)) +>x.next2 : Symbol(IAsyncEnumerator.next2, Decl(awaitUnionPromise.ts, 6, 46)) +>x : Symbol(x, Decl(awaitUnionPromise.ts, 13, 9)) +>next2 : Symbol(IAsyncEnumerator.next2, Decl(awaitUnionPromise.ts, 6, 46)) + + let c = await x.next3(); +>c : Symbol(c, Decl(awaitUnionPromise.ts, 16, 7)) +>x.next3 : Symbol(IAsyncEnumerator.next3, Decl(awaitUnionPromise.ts, 7, 55)) +>x : Symbol(x, Decl(awaitUnionPromise.ts, 13, 9)) +>next3 : Symbol(IAsyncEnumerator.next3, Decl(awaitUnionPromise.ts, 7, 55)) + + let d = await x.next4(); +>d : Symbol(d, Decl(awaitUnionPromise.ts, 17, 7)) +>x.next4 : Symbol(IAsyncEnumerator.next4, Decl(awaitUnionPromise.ts, 8, 29)) +>x : Symbol(x, Decl(awaitUnionPromise.ts, 13, 9)) +>next4 : Symbol(IAsyncEnumerator.next4, Decl(awaitUnionPromise.ts, 8, 29)) +} diff --git a/tests/baselines/reference/awaitUnionPromise.types b/tests/baselines/reference/awaitUnionPromise.types new file mode 100644 index 00000000000..f1d91c038de --- /dev/null +++ b/tests/baselines/reference/awaitUnionPromise.types @@ -0,0 +1,76 @@ +=== tests/cases/compiler/awaitUnionPromise.ts === +/// @target: es2015 +// https://github.com/Microsoft/TypeScript/issues/18186 + +class AsyncEnumeratorDone { }; +>AsyncEnumeratorDone : AsyncEnumeratorDone + +interface IAsyncEnumerator { +>IAsyncEnumerator : IAsyncEnumerator +>T : T + + next1(): Promise; +>next1 : () => Promise +>Promise : Promise +>T : T +>AsyncEnumeratorDone : AsyncEnumeratorDone + + next2(): Promise | Promise; +>next2 : () => Promise | Promise +>Promise : Promise +>T : T +>Promise : Promise +>AsyncEnumeratorDone : AsyncEnumeratorDone + + next3(): Promise; +>next3 : () => Promise<{} | T> +>Promise : Promise +>T : T + + next4(): Promise; +>next4 : () => Promise +>Promise : Promise +>T : T +>x : string +} + +async function main() { +>main : () => Promise + + const x: IAsyncEnumerator = null; +>x : IAsyncEnumerator +>IAsyncEnumerator : IAsyncEnumerator +>null : null + + let a = await x.next1(); +>a : number | AsyncEnumeratorDone +>await x.next1() : number | AsyncEnumeratorDone +>x.next1() : Promise +>x.next1 : () => Promise +>x : IAsyncEnumerator +>next1 : () => Promise + + let b = await x.next2(); +>b : number | AsyncEnumeratorDone +>await x.next2() : number | AsyncEnumeratorDone +>x.next2() : Promise | Promise +>x.next2 : () => Promise | Promise +>x : IAsyncEnumerator +>next2 : () => Promise | Promise + + let c = await x.next3(); +>c : number | {} +>await x.next3() : number | {} +>x.next3() : Promise +>x.next3 : () => Promise +>x : IAsyncEnumerator +>next3 : () => Promise + + let d = await x.next4(); +>d : number | { x: string; } +>await x.next4() : number | { x: string; } +>x.next4() : Promise +>x.next4 : () => Promise +>x : IAsyncEnumerator +>next4 : () => Promise +} diff --git a/tests/cases/compiler/awaitUnionPromise.ts b/tests/cases/compiler/awaitUnionPromise.ts new file mode 100644 index 00000000000..2c8470e97a6 --- /dev/null +++ b/tests/cases/compiler/awaitUnionPromise.ts @@ -0,0 +1,19 @@ +/// @target: es2015 +// https://github.com/Microsoft/TypeScript/issues/18186 + +class AsyncEnumeratorDone { }; + +interface IAsyncEnumerator { + next1(): Promise; + next2(): Promise | Promise; + next3(): Promise; + next4(): Promise; +} + +async function main() { + const x: IAsyncEnumerator = null; + let a = await x.next1(); + let b = await x.next2(); + let c = await x.next3(); + let d = await x.next4(); +} \ No newline at end of file From eebb0447ab3ad06adf252ed9eb81a16e54832a51 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 16 Oct 2017 14:47:43 -0700 Subject: [PATCH 029/405] Fix generated name scope when emitting async functions --- src/compiler/transformers/es2017.ts | 2 +- .../asyncFunctionTempVariableScoping.js | 64 +++++++++++++++++++ .../asyncFunctionTempVariableScoping.symbols | 10 +++ .../asyncFunctionTempVariableScoping.types | 13 ++++ .../asyncFunctionTempVariableScoping.ts | 5 ++ 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/asyncFunctionTempVariableScoping.js create mode 100644 tests/baselines/reference/asyncFunctionTempVariableScoping.symbols create mode 100644 tests/baselines/reference/asyncFunctionTempVariableScoping.types create mode 100644 tests/cases/compiler/asyncFunctionTempVariableScoping.ts diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index d98f227e8c7..9fa39da2d23 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -463,7 +463,7 @@ namespace ts { ); // Mark this node as originally an async function - (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= EmitFlags.AsyncFunctionBody; + (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope; return createCall( getHelperName("__awaiter"), diff --git a/tests/baselines/reference/asyncFunctionTempVariableScoping.js b/tests/baselines/reference/asyncFunctionTempVariableScoping.js new file mode 100644 index 00000000000..b4f8caa6508 --- /dev/null +++ b/tests/baselines/reference/asyncFunctionTempVariableScoping.js @@ -0,0 +1,64 @@ +//// [asyncFunctionTempVariableScoping.ts] +// https://github.com/Microsoft/TypeScript/issues/19187 + +async ({ foo, bar, ...rest }) => bar(await foo); + +//// [asyncFunctionTempVariableScoping.js] +// https://github.com/Microsoft/TypeScript/issues/19187 +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __rest = (this && this.__rest) || function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) + t[p[i]] = s[p[i]]; + return t; +}; +var _this = this; +(function (_a) { return __awaiter(_this, void 0, void 0, function () { + var foo = _a.foo, bar = _a.bar, rest = __rest(_a, ["foo", "bar"]); + var _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + _b = bar; + return [4 /*yield*/, foo]; + case 1: return [2 /*return*/, _b.apply(void 0, [_c.sent()])]; + } + }); +}); }); diff --git a/tests/baselines/reference/asyncFunctionTempVariableScoping.symbols b/tests/baselines/reference/asyncFunctionTempVariableScoping.symbols new file mode 100644 index 00000000000..578cda3ac77 --- /dev/null +++ b/tests/baselines/reference/asyncFunctionTempVariableScoping.symbols @@ -0,0 +1,10 @@ +=== tests/cases/compiler/asyncFunctionTempVariableScoping.ts === +// https://github.com/Microsoft/TypeScript/issues/19187 + +async ({ foo, bar, ...rest }) => bar(await foo); +>foo : Symbol(foo, Decl(asyncFunctionTempVariableScoping.ts, 2, 8)) +>bar : Symbol(bar, Decl(asyncFunctionTempVariableScoping.ts, 2, 13)) +>rest : Symbol(rest, Decl(asyncFunctionTempVariableScoping.ts, 2, 18)) +>bar : Symbol(bar, Decl(asyncFunctionTempVariableScoping.ts, 2, 13)) +>foo : Symbol(foo, Decl(asyncFunctionTempVariableScoping.ts, 2, 8)) + diff --git a/tests/baselines/reference/asyncFunctionTempVariableScoping.types b/tests/baselines/reference/asyncFunctionTempVariableScoping.types new file mode 100644 index 00000000000..30b23994903 --- /dev/null +++ b/tests/baselines/reference/asyncFunctionTempVariableScoping.types @@ -0,0 +1,13 @@ +=== tests/cases/compiler/asyncFunctionTempVariableScoping.ts === +// https://github.com/Microsoft/TypeScript/issues/19187 + +async ({ foo, bar, ...rest }) => bar(await foo); +>async ({ foo, bar, ...rest }) => bar(await foo) : ({ foo, bar, ...rest }: { [x: string]: any; foo: any; bar: any; }) => Promise +>foo : any +>bar : any +>rest : { [x: string]: any; } +>bar(await foo) : any +>bar : any +>await foo : any +>foo : any + diff --git a/tests/cases/compiler/asyncFunctionTempVariableScoping.ts b/tests/cases/compiler/asyncFunctionTempVariableScoping.ts new file mode 100644 index 00000000000..c1d52d6da17 --- /dev/null +++ b/tests/cases/compiler/asyncFunctionTempVariableScoping.ts @@ -0,0 +1,5 @@ +// @target: es5 +// @lib: es2015 +// https://github.com/Microsoft/TypeScript/issues/19187 + +async ({ foo, bar, ...rest }) => bar(await foo); \ No newline at end of file From fd86cd5a2ed120127f41a8a3c62dde9dd38d6a5e Mon Sep 17 00:00:00 2001 From: csigs Date: Mon, 16 Oct 2017 22:10:47 +0000 Subject: [PATCH 030/405] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 6 + .../diagnosticMessages.generated.json.lcl | 17094 ++++++++-------- 2 files changed, 8592 insertions(+), 8508 deletions(-) diff --git a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl index a2963d878f6..ec0503ee41f 100644 --- a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3990,12 +3990,18 @@ + + + + + + diff --git a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl index affa7a48347..bcd7c4e2982 100644 --- a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,8509 +1,8587 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - veya - biçiminde olmalıdır. Örneğin, '{0}' veya '{1}'.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - türü olmalıdır.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()' kullanın.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + veya - biçiminde olmalıdır. Örneğin, '{0}' veya '{1}'.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + türü olmalıdır.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()' kullanın.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 3c452057c2fb88098691bb16a7c490f91d17d6f2 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 16 Oct 2017 16:09:16 -0700 Subject: [PATCH 031/405] Add release-2.6 to covered branches --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 27b14739d8b..d24e155b580 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,7 @@ branches: only: - master - release-2.5 + - release-2.6 install: - npm uninstall typescript --no-save From b86153da8806a0b9ee7aaa76cc549ee37b2dc3bc Mon Sep 17 00:00:00 2001 From: Armando Aguirre Date: Mon, 16 Oct 2017 17:50:35 -0700 Subject: [PATCH 032/405] Changed command designed based on review input --- src/harness/harnessLanguageService.ts | 6 +- src/harness/unittests/session.ts | 1 + src/server/client.ts | 8 +-- src/server/protocol.ts | 8 ++- src/server/session.ts | 71 +++++++++++++------ src/services/services.ts | 25 ++++--- src/services/types.ts | 7 +- .../reference/api/tsserverlibrary.d.ts | 15 +++- tests/baselines/reference/api/typescript.d.ts | 6 +- 9 files changed, 103 insertions(+), 44 deletions(-) diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 34043195429..2ec40a8981d 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -432,6 +432,9 @@ namespace Harness.LanguageService { getDefinitionAtPosition(fileName: string, position: number): ts.DefinitionInfo[] { return unwrapJSONCallResult(this.shim.getDefinitionAtPosition(fileName, position)); } + getDefinitionAndBoundSpan(): ts.DefinitionInfoAndBoundSpan { + throw new Error("Not supported on the shim."); + } getTypeDefinitionAtPosition(fileName: string, position: number): ts.DefinitionInfo[] { return unwrapJSONCallResult(this.shim.getTypeDefinitionAtPosition(fileName, position)); } @@ -490,9 +493,6 @@ namespace Harness.LanguageService { getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): ts.TextSpan { return unwrapJSONCallResult(this.shim.getSpanOfEnclosingComment(fileName, position, onlyMultiLine)); } - getSpanForPosition(): ts.TextSpan { - throw new Error("Not supportred on the shim."); - } getCodeFixesAtPosition(): ts.CodeAction[] { throw new Error("Not supported on the shim."); } diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index 2ce5ef530e4..fd278dc3c3a 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -176,6 +176,7 @@ namespace ts.server { CommandNames.Definition, CommandNames.DefinitionFull, CommandNames.DefinitionAndBoundSpan, + CommandNames.DefinitionAndBoundSpanFull, CommandNames.Implementation, CommandNames.ImplementationFull, CommandNames.Exit, diff --git a/src/server/client.ts b/src/server/client.ts index f467f7f9224..0fe5f48ed31 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -268,6 +268,10 @@ namespace ts.server { })); } + getDefinitionAndBoundSpan(_fileName: string, _position: number): DefinitionInfoAndBoundSpan { + return notImplemented(); + } + getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { const args: protocol.FileLocationRequestArgs = this.createFileLocationRequestArgs(fileName, position); @@ -531,10 +535,6 @@ namespace ts.server { return notImplemented(); } - getSpanForPosition(_fileName: string, _position: number): TextSpan { - return notImplemented(); - } - getCodeFixesAtPosition(file: string, start: number, end: number, errorCodes: number[]): CodeAction[] { const args: protocol.CodeFixRequestArgs = { ...this.createFileRangeRequestArgs(file, start, end), errorCodes }; diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 0685728c3b0..327c351ba6f 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -21,8 +21,9 @@ namespace ts.server.protocol { Definition = "definition", /* @internal */ DefinitionFull = "definition-full", - /* @internal */ DefinitionAndBoundSpan = "definitionAndBoundSpan", + /* @internal */ + DefinitionAndBoundSpanFull = "definitionAndBoundSpan-full", Implementation = "implementation", /* @internal */ ImplementationFull = "implementation-full", @@ -690,6 +691,11 @@ namespace ts.server.protocol { file: string; } + export interface DefinitionInfoAndBoundSpan { + definitions: ReadonlyArray; + textSpan: TextSpan; + } + /** * Definition response message. Gives text range for definition. */ diff --git a/src/server/session.ts b/src/server/session.ts index 5a8426f23b3..54ac3082c18 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -601,20 +601,57 @@ namespace ts.server { } if (simplifiedResult) { - return definitions.map(def => { - const defScriptInfo = project.getScriptInfo(def.fileName); - return { - file: def.fileName, - start: defScriptInfo.positionToLineOffset(def.textSpan.start), - end: defScriptInfo.positionToLineOffset(textSpanEnd(def.textSpan)) - }; - }); + return this.getSimplifiedDefinition(definitions, project); } else { return definitions; } } + private getDefinitionAndBoundSpan(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.DefinitionInfoAndBoundSpan | DefinitionInfoAndBoundSpan { + const { file, project } = this.getFileAndProject(args); + const position = this.getPositionInFile(args, file); + const scriptInfo = project.getScriptInfo(file); + + const definitionAndBoundSpan = project.getLanguageService().getDefinitionAndBoundSpan(file, position); + + if (!definitionAndBoundSpan || !definitionAndBoundSpan.definitions) { + return { + definitions: emptyArray, + textSpan: undefined + }; + } + + if (simplifiedResult) { + return { + definitions: this.getSimplifiedDefinition(definitionAndBoundSpan.definitions, project), + textSpan: this.getSimplifiedTextSpan(definitionAndBoundSpan.textSpan, scriptInfo) + }; + } + + return definitionAndBoundSpan; + } + + private getSimplifiedDefinition(definitions: ReadonlyArray, project: Project): ReadonlyArray { + return definitions.map(def => { + const defScriptInfo = project.getScriptInfo(def.fileName); + const simplifiedTextSpan = this.getSimplifiedTextSpan(def.textSpan, defScriptInfo); + + return { + file: def.fileName, + start: simplifiedTextSpan.start, + end: simplifiedTextSpan.end + }; + }); + } + + private getSimplifiedTextSpan(textSpan: TextSpan, scriptInfo: ScriptInfo): protocol.TextSpan { + return { + start: scriptInfo.positionToLineOffset(textSpan.start), + end: scriptInfo.positionToLineOffset(textSpanEnd(textSpan)) + }; + } + private getTypeDefinition(args: protocol.FileLocationRequestArgs): ReadonlyArray { const { file, project } = this.getFileAndProject(args); const position = this.getPositionInFile(args, file); @@ -1081,13 +1118,6 @@ namespace ts.server { } } - private getSpanForLocation(args: protocol.FileLocationRequestArgs): TextSpan { - const { file, project } = this.getFileAndProject(args); - const scriptInfo = project.getScriptInfoForNormalizedPath(file); - - return project.getLanguageService().getSpanForPosition(file, this.getPosition(args, scriptInfo)); - } - private getFormattingEditsForRange(args: protocol.FormatRequestArgs): protocol.CodeEdit[] { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file); @@ -1715,13 +1745,10 @@ namespace ts.server { return this.requiredResponse(this.getDefinition(request.arguments, /*simplifiedResult*/ false)); }, [CommandNames.DefinitionAndBoundSpan]: (request: protocol.DefinitionRequest) => { - const definitions = this.getDefinition(request.arguments, /*simplifiedResult*/ false); - const textSpan = definitions.length !== 0 ? this.getSpanForLocation(request.arguments) : {}; - - return this.requiredResponse({ - definitions, - textSpan - }); + return this.requiredResponse(this.getDefinitionAndBoundSpan(request.arguments, /*simplifiedResult*/ true)); + }, + [CommandNames.DefinitionAndBoundSpanFull]: (request: protocol.DefinitionRequest) => { + return this.requiredResponse(this.getDefinitionAndBoundSpan(request.arguments, /*simplifiedResult*/ false)); }, [CommandNames.TypeDefinition]: (request: protocol.FileLocationRequest) => { return this.requiredResponse(this.getTypeDefinition(request.arguments)); diff --git a/src/services/services.ts b/src/services/services.ts index 5b24fa1947e..f2702082470 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1411,6 +1411,20 @@ namespace ts { return GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position); } + function getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan { + const definitions = getDefinitionAtPosition(fileName, position); + + if (!definitions) { + return undefined; + } + + const sourceFile = getValidSourceFile(fileName); + const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true); + const textSpan = createTextSpan(node.getStart(), node.getWidth()); + + return { definitions, textSpan }; + } + function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { synchronizeHostData(); return GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position); @@ -1807,15 +1821,6 @@ namespace ts { return range && createTextSpanFromRange(range); } - function getSpanForPosition(fileName: string, position: number): TextSpan { - synchronizeHostData(); - - const sourceFile = getValidSourceFile(fileName); - const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocCcomment*/ false); - - return createTextSpan(node.getStart(), node.getWidth()); - } - function getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] { // Note: while getting todo comments seems like a syntactic operation, we actually // treat it as a semantic operation here. This is because we expect our host to call @@ -2018,6 +2023,7 @@ namespace ts { getSignatureHelpItems, getQuickInfoAtPosition, getDefinitionAtPosition, + getDefinitionAndBoundSpan, getImplementationAtPosition, getTypeDefinitionAtPosition, getReferencesAtPosition, @@ -2041,7 +2047,6 @@ namespace ts { getDocCommentTemplateAtPosition, isValidBraceCompletionAtPosition, getSpanOfEnclosingComment, - getSpanForPosition, getCodeFixesAtPosition, getEmitOutput, getNonBoundSourceFile, diff --git a/src/services/types.ts b/src/services/types.ts index 034b45100e0..c6ab8c876f0 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -245,6 +245,7 @@ namespace ts { findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[]; getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; + getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan; getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[]; @@ -273,7 +274,6 @@ namespace ts { isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; - getSpanForPosition(fileName: string, position: number): TextSpan; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[]; getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; @@ -549,6 +549,11 @@ namespace ts { containerName: string; } + export interface DefinitionInfoAndBoundSpan { + definitions: ReadonlyArray; + textSpan: TextSpan; + } + export interface ReferencedSymbolDefinitionInfo extends DefinitionInfo { displayParts: SymbolDisplayPart[]; } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 8beb5ff60e4..b69b44e98a0 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3922,6 +3922,7 @@ declare namespace ts { getRenameInfo(fileName: string, position: number): RenameInfo; findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[]; getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; + getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan; getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[]; getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[]; @@ -3942,7 +3943,6 @@ declare namespace ts { getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; - getSpanForPosition(fileName: string, position: number): TextSpan; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[]; getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined; @@ -4174,6 +4174,10 @@ declare namespace ts { containerKind: ScriptElementKind; containerName: string; } + interface DefinitionInfoAndBoundSpan { + definitions: ReadonlyArray; + textSpan: TextSpan; + } interface ReferencedSymbolDefinitionInfo extends DefinitionInfo { displayParts: SymbolDisplayPart[]; } @@ -4793,6 +4797,7 @@ declare namespace ts.server.protocol { CompileOnSaveEmitFile = "compileOnSaveEmitFile", Configure = "configure", Definition = "definition", + DefinitionAndBoundSpan = "definitionAndBoundSpan", Implementation = "implementation", Exit = "exit", Format = "format", @@ -5298,6 +5303,10 @@ declare namespace ts.server.protocol { */ file: string; } + interface DefinitionInfoAndBoundSpan { + definitions: ReadonlyArray; + textSpan: TextSpan; + } /** * Definition response message. Gives text range for definition. */ @@ -6855,6 +6864,9 @@ declare namespace ts.server { private convertToDiagnosticsWithLinePosition(diagnostics, scriptInfo); private getDiagnosticsWorker(args, isSemantic, selector, includeLinePosition); private getDefinition(args, simplifiedResult); + private getDefinitionAndBoundSpan(args, simplifiedResult); + private getSimplifiedDefinition(definitions, project); + private getSimplifiedTextSpan(textSpan, scriptInfo); private getTypeDefinition(args); private getImplementation(args, simplifiedResult); private getOccurrences(args); @@ -6888,7 +6900,6 @@ declare namespace ts.server { private getNameOrDottedNameSpan(args); private isValidBraceCompletion(args); private getQuickInfoWorker(args, simplifiedResult); - private getSpanForLocation(args); private getFormattingEditsForRange(args); private getFormattingEditsForRangeFull(args); private getFormattingEditsForDocumentFull(args); diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 2733bb20e56..9f9319fd7fa 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3922,6 +3922,7 @@ declare namespace ts { getRenameInfo(fileName: string, position: number): RenameInfo; findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[]; getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; + getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan; getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[]; getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[]; @@ -3942,7 +3943,6 @@ declare namespace ts { getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; - getSpanForPosition(fileName: string, position: number): TextSpan; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[]; getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined; @@ -4174,6 +4174,10 @@ declare namespace ts { containerKind: ScriptElementKind; containerName: string; } + interface DefinitionInfoAndBoundSpan { + definitions: ReadonlyArray; + textSpan: TextSpan; + } interface ReferencedSymbolDefinitionInfo extends DefinitionInfo { displayParts: SymbolDisplayPart[]; } From 50628e73c57185b59e12fecde15ce1654fa95e56 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 16 Oct 2017 16:53:33 -0700 Subject: [PATCH 033/405] Do not watch root folders for failed lookup locations and effective type roots Fixes #19170 --- src/compiler/resolutionCache.ts | 72 +++++++-- src/harness/unittests/tscWatchMode.ts | 4 +- .../unittests/tsserverProjectSystem.ts | 142 +++++++++++------- 3 files changed, 148 insertions(+), 70 deletions(-) diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index 84fffbe6f5e..b988da0fd5f 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -64,6 +64,7 @@ namespace ts { interface DirectoryOfFailedLookupWatch { dir: string; dirPath: Path; + ignore?: true; } export const maxNumberOfFilesToIterateForInvalidation = 256; @@ -319,6 +320,33 @@ namespace ts { return endsWith(dirPath, "/node_modules"); } + function isDirectoryAtleastAtLevelFromFSRoot(dirPath: Path, minLevels: number) { + for (let searchIndex = getRootLength(dirPath); minLevels > 0; minLevels--) { + searchIndex = dirPath.indexOf(directorySeparator, searchIndex) + 1; + if (searchIndex === 0) { + // Folder isnt at expected minimun levels + return false; + } + } + return true; + } + + function canWatchDirectory(dirPath: Path) { + return isDirectoryAtleastAtLevelFromFSRoot(dirPath, + // When root is "/" do not watch directories like: + // "/", "/user", "/user/username", "/user/username/folderAtRoot" + // When root is "c:/" do not watch directories like: + // "c:/", "c:/folderAtRoot" + dirPath.charCodeAt(0) === CharacterCodes.slash ? 3 : 1); + } + + function filterFSRootDirectoriesToWatch(watchPath: DirectoryOfFailedLookupWatch, dirPath: Path): DirectoryOfFailedLookupWatch { + if (!canWatchDirectory(dirPath)) { + watchPath.ignore = true; + } + return watchPath; + } + function getDirectoryToWatchFailedLookupLocation(failedLookupLocation: string, failedLookupLocationPath: Path): DirectoryOfFailedLookupWatch { if (isInDirectoryPath(rootPath, failedLookupLocationPath)) { return { dir: rootDir, dirPath: rootPath }; @@ -335,7 +363,7 @@ namespace ts { // If the directory is node_modules use it to watch if (isNodeModulesDirectory(dirPath)) { - return { dir, dirPath }; + return filterFSRootDirectoriesToWatch({ dir, dirPath }, getDirectoryPath(dirPath)); } // Use some ancestor of the root directory @@ -350,7 +378,7 @@ namespace ts { } } - return { dir, dirPath }; + return filterFSRootDirectoriesToWatch({ dir, dirPath }, dirPath); } function isPathWithDefaultFailedLookupExtension(path: Path) { @@ -391,13 +419,15 @@ namespace ts { const refCount = customFailedLookupPaths.get(failedLookupLocationPath) || 0; customFailedLookupPaths.set(failedLookupLocationPath, refCount + 1); } - const { dir, dirPath } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath); - const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); - if (dirWatcher) { - dirWatcher.refCount++; - } - else { - directoryWatchesOfFailedLookups.set(dirPath, { watcher: createDirectoryWatcher(dir, dirPath), refCount: 1 }); + const { dir, dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath); + if (!ignore) { + const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); + if (dirWatcher) { + dirWatcher.refCount++; + } + else { + directoryWatchesOfFailedLookups.set(dirPath, { watcher: createDirectoryWatcher(dir, dirPath), refCount: 1 }); + } } } } @@ -422,10 +452,12 @@ namespace ts { customFailedLookupPaths.set(failedLookupLocationPath, refCount - 1); } } - const { dirPath } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath); - const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); - // Do not close the watcher yet since it might be needed by other failed lookup locations. - dirWatcher.refCount--; + const { dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath); + if (!ignore) { + const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); + // Do not close the watcher yet since it might be needed by other failed lookup locations. + dirWatcher.refCount--; + } } } @@ -577,7 +609,8 @@ namespace ts { } // we need to assume the directories exist to ensure that we can get all the type root directories that get included - const typeRoots = getEffectiveTypeRoots(options, { directoryExists: returnTrue, getCurrentDirectory }); + // But filter directories that are at root level to say directory doesnt exist, so that we arent watching them + const typeRoots = getEffectiveTypeRoots(options, { directoryExists: directoryExistsForTypeRootWatch, getCurrentDirectory }); if (typeRoots) { mutateMap( typeRootsWatches, @@ -592,5 +625,16 @@ namespace ts { closeTypeRootsWatch(); } } + + /** + * Use this function to return if directory exists to get type roots to watch + * If we return directory exists then only the paths will be added to type roots + * Hence return true for all directories except root directories which are filtered from watching + */ + function directoryExistsForTypeRootWatch(nodeTypesDirectory: string) { + const dir = getDirectoryPath(getDirectoryPath(nodeTypesDirectory)); + const dirPath = resolutionHost.toPath(dir); + return dirPath === rootPath || canWatchDirectory(dirPath); + } } } diff --git a/src/harness/unittests/tscWatchMode.ts b/src/harness/unittests/tscWatchMode.ts index b25a7b1eb53..24052bd1add 100644 --- a/src/harness/unittests/tscWatchMode.ts +++ b/src/harness/unittests/tscWatchMode.ts @@ -254,7 +254,7 @@ namespace ts.tscWatch { checkProgramRootFiles(watch(), [file1.path, file2.path]); checkWatchedFiles(host, [configFile.path, file1.path, file2.path, libFile.path]); const configDir = getDirectoryPath(configFile.path); - checkWatchedDirectories(host, projectSystem.getTypeRootsFromLocation(configDir).concat(configDir), /*recursive*/ true); + checkWatchedDirectories(host, [configDir, combinePaths(configDir, projectSystem.nodeModulesAtTypes)], /*recursive*/ true); }); // TODO: if watching for config file creation @@ -269,7 +269,7 @@ namespace ts.tscWatch { const host = createWatchedSystem([commonFile1, libFile, configFile]); const watch = createWatchModeWithConfigFile(configFile.path, host); const configDir = getDirectoryPath(configFile.path); - checkWatchedDirectories(host, projectSystem.getTypeRootsFromLocation(configDir).concat(configDir), /*recursive*/ true); + checkWatchedDirectories(host, [configDir, combinePaths(configDir, projectSystem.nodeModulesAtTypes)], /*recursive*/ true); checkProgramRootFiles(watch(), [commonFile1.path]); diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 4929cbfbaa5..175b579103f 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -323,14 +323,31 @@ namespace ts.projectSystem { checkFileNames(`${server.ProjectKind[project.projectKind]} project, rootFileNames`, project.getRootFiles(), expectedFiles); } - function getNodeModuleDirectories(dir: string) { + function mapCombinedPathsInAncestor(dir: string, path2: string, mapAncestor: (ancestor: string) => boolean) { + dir = normalizePath(dir); const result: string[] = []; forEachAncestorDirectory(dir, ancestor => { - result.push(combinePaths(ancestor, "node_modules")); + if (mapAncestor(ancestor)) { + result.push(combinePaths(ancestor, path2)); + } }); return result; } + function getRootsToWatchWithAncestorDirectory(dir: string, path2: string) { + return mapCombinedPathsInAncestor(dir, path2, ancestor => ancestor.split(directorySeparator).length > 4); + } + + const nodeModules = "node_modules"; + function getNodeModuleDirectories(dir: string) { + return getRootsToWatchWithAncestorDirectory(dir, nodeModules); + } + + export const nodeModulesAtTypes = "node_modules/@types"; + export function getTypeRootsFromLocation(currentDirectory: string) { + return getRootsToWatchWithAncestorDirectory(currentDirectory, nodeModulesAtTypes); + } + function getNumberOfWatchesInvokedForRecursiveWatches(recursiveWatchedDirs: string[], file: string) { return countWhere(recursiveWatchedDirs, dir => file.length > dir.length && startsWith(file, dir) && file[dir.length] === directorySeparator); } @@ -413,15 +430,6 @@ namespace ts.projectSystem { verifyDiagnostics(actual, []); } - export function getTypeRootsFromLocation(currentDirectory: string) { - currentDirectory = normalizePath(currentDirectory); - const result: string[] = []; - forEachAncestorDirectory(currentDirectory, ancestor => { - result.push(combinePaths(ancestor, "node_modules/@types")); - }); - return result; - } - describe("tsserverProjectSystem", () => { const commonFile1: FileOrFolder = { path: "/a/b/commonFile1.ts", @@ -460,7 +468,7 @@ namespace ts.projectSystem { const configFiles = flatMap(configFileLocations, location => [location + "tsconfig.json", location + "jsconfig.json"]); checkWatchedFiles(host, configFiles.concat(libFile.path, moduleFile.path)); checkWatchedDirectories(host, [], /*recursive*/ false); - checkWatchedDirectories(host, ["/a/b/c", ...getTypeRootsFromLocation(getDirectoryPath(appFile.path))], /*recursive*/ true); + checkWatchedDirectories(host, ["/a/b/c", combinePaths(getDirectoryPath(appFile.path), nodeModulesAtTypes)], /*recursive*/ true); }); it("can handle tsconfig file name with difference casing", () => { @@ -532,7 +540,7 @@ namespace ts.projectSystem { // watching all files except one that was open checkWatchedFiles(host, [configFile.path, file2.path, libFile.path]); const configFileDirectory = getDirectoryPath(configFile.path); - checkWatchedDirectories(host, getTypeRootsFromLocation(configFileDirectory).concat(configFileDirectory), /*recursive*/ true); + checkWatchedDirectories(host, [configFileDirectory, combinePaths(configFileDirectory, nodeModulesAtTypes)], /*recursive*/ true); }); it("create configured project with the file list", () => { @@ -621,7 +629,7 @@ namespace ts.projectSystem { const projectService = createProjectService(host); projectService.openClientFile(commonFile1.path); const configFileDir = getDirectoryPath(configFile.path); - checkWatchedDirectories(host, getTypeRootsFromLocation(configFileDir).concat(configFileDir), /*recursive*/ true); + checkWatchedDirectories(host, [configFileDir, combinePaths(configFileDir, nodeModulesAtTypes)], /*recursive*/ true); checkNumberOfConfiguredProjects(projectService, 1); const project = configuredProjectAt(projectService, 0); @@ -2433,7 +2441,7 @@ namespace ts.projectSystem { checkProjectActualFiles(project, map(files, file => file.path)); checkWatchedFiles(host, mapDefined(files, file => file === file1 ? undefined : file.path)); checkWatchedDirectories(host, [], /*recursive*/ false); - const watchedRecursiveDirectories = getTypeRootsFromLocation("/a/b"); + const watchedRecursiveDirectories = ["/a/b/node_modules/@types"]; watchedRecursiveDirectories.push("/a/b"); checkWatchedDirectories(host, watchedRecursiveDirectories, /*recursive*/ true); @@ -2459,7 +2467,8 @@ namespace ts.projectSystem { }); - it("Failed lookup locations are uses parent most node_modules directory", () => { + it("Failed lookup locations uses parent most node_modules directory", () => { + const root = "/user/username/rootfolder"; const file1: FileOrFolder = { path: "/a/b/src/file1.ts", content: 'import { classc } from "module1"' @@ -2479,9 +2488,11 @@ namespace ts.projectSystem { }; const configFile: FileOrFolder = { path: "/a/b/src/tsconfig.json", - content: JSON.stringify({ files: [file1.path] }) + content: JSON.stringify({ files: ["file1.ts"] }) }; - const files = [file1, module1, module2, module3, configFile, libFile]; + const nonLibFiles = [file1, module1, module2, module3, configFile]; + nonLibFiles.forEach(f => f.path = root + f.path); + const files = nonLibFiles.concat(libFile); const host = createServerHost(files); const projectService = createProjectService(host); projectService.openClientFile(file1.path); @@ -2491,8 +2502,8 @@ namespace ts.projectSystem { checkProjectActualFiles(project, [file1.path, libFile.path, module1.path, module2.path, configFile.path]); checkWatchedFiles(host, [libFile.path, module1.path, module2.path, configFile.path]); checkWatchedDirectories(host, [], /*recursive*/ false); - const watchedRecursiveDirectories = getTypeRootsFromLocation("/a/b/src"); - watchedRecursiveDirectories.push("/a/b/src", "/a/b/node_modules"); + const watchedRecursiveDirectories = getTypeRootsFromLocation(root + "/a/b/src"); + watchedRecursiveDirectories.push(`${root}/a/b/src`, `${root}/a/b/node_modules`); checkWatchedDirectories(host, watchedRecursiveDirectories, /*recursive*/ true); }); }); @@ -4682,7 +4693,6 @@ namespace ts.projectSystem { } const f2Lookups = getLocationsForModuleLookup("f2"); callsTrackingHost.verifyCalledOnEachEntryNTimes(CalledMapsWithSingleArg.fileExists, f2Lookups, 1); - const typeRootLocations = getTypeRootsFromLocation(getDirectoryPath(root.path)); const f2DirLookups = getLocationsForDirectoryLookup(); callsTrackingHost.verifyCalledOnEachEntry(CalledMapsWithSingleArg.directoryExists, f2DirLookups); callsTrackingHost.verifyNoCall(CalledMapsWithSingleArg.getDirectories); @@ -4693,7 +4703,7 @@ namespace ts.projectSystem { verifyImportedDiagnostics(); const f1Lookups = f2Lookups.map(s => s.replace("f2", "f1")); f1Lookups.length = f1Lookups.indexOf(imported.path) + 1; - const f1DirLookups = ["/c/d", "/c", ...typeRootLocations]; + const f1DirLookups = ["/c/d", "/c", ...mapCombinedPathsInAncestor(getDirectoryPath(root.path), nodeModulesAtTypes, returnTrue)]; vertifyF1Lookups(); // setting compiler options discards module resolution cache @@ -4744,13 +4754,12 @@ namespace ts.projectSystem { function getLocationsForDirectoryLookup() { const result = createMap(); - // Type root - typeRootLocations.forEach(location => result.set(location, 1)); forEachAncestorDirectory(getDirectoryPath(root.path), ancestor => { // To resolve modules result.set(ancestor, 2); // for type roots - result.set(combinePaths(ancestor, `node_modules`), 1); + result.set(combinePaths(ancestor, nodeModules), 1); + result.set(combinePaths(ancestor, nodeModulesAtTypes), 1); }); return result; } @@ -4990,15 +4999,20 @@ namespace ts.projectSystem { describe("Verify npm install in directory with tsconfig file works when", () => { function verifyNpmInstall(timeoutDuringPartialInstallation: boolean) { - const app: FileOrFolder = { + const root = "/user/username/rootfolder/otherfolder"; + const getRootedFileOrFolder = (fileOrFolder: FileOrFolder) => { + fileOrFolder.path = root + fileOrFolder.path; + return fileOrFolder; + }; + const app: FileOrFolder = getRootedFileOrFolder({ path: "/a/b/app.ts", content: "import _ from 'lodash';" - }; - const tsconfigJson: FileOrFolder = { + }); + const tsconfigJson: FileOrFolder = getRootedFileOrFolder({ path: "/a/b/tsconfig.json", content: '{ "compilerOptions": { } }' - }; - const packageJson: FileOrFolder = { + }); + const packageJson: FileOrFolder = getRootedFileOrFolder({ path: "/a/b/package.json", content: ` { @@ -5022,7 +5036,7 @@ namespace ts.projectSystem { "license": "ISC" } ` - }; + }); const appFolder = getDirectoryPath(app.path); const projectFiles = [app, libFile, tsconfigJson]; const typeRootDirectories = getTypeRootsFromLocation(getDirectoryPath(tsconfigJson.path)); @@ -5053,16 +5067,16 @@ namespace ts.projectSystem { { "path": "/a/b/node_modules/.staging/symbol-observable-24bcbbff/index.d.ts", "content": "declare const observableSymbol: symbol;\nexport default observableSymbol;\n" }, { "path": "/a/b/node_modules/.staging/symbol-observable-24bcbbff/lib" }, { "path": "/a/b/node_modules/.staging/symbol-observable-24bcbbff/lib/index.js", "content": "'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _ponyfill = require('./ponyfill');\n\nvar _ponyfill2 = _interopRequireDefault(_ponyfill);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }\n\nvar root; /* global window */\n\n\nif (typeof self !== 'undefined') {\n root = self;\n} else if (typeof window !== 'undefined') {\n root = window;\n} else if (typeof global !== 'undefined') {\n root = global;\n} else if (typeof module !== 'undefined') {\n root = module;\n} else {\n root = Function('return this')();\n}\n\nvar result = (0, _ponyfill2['default'])(root);\nexports['default'] = result;" }, - ]; + ].map(getRootedFileOrFolder); verifyAfterPartialOrCompleteNpmInstall(2); - filesAndFoldersToAdd.push( + filesAndFoldersToAdd.push(...[ { "path": "/a/b/node_modules/.staging/typescript-8493ea5d/lib" }, { "path": "/a/b/node_modules/.staging/rxjs-22375c61/add/operator" }, { "path": "/a/b/node_modules/.staging/@types/lodash-e56c4fe7/package.json", "content": "{\n \"name\": \"@types/lodash\",\n \"version\": \"4.14.74\",\n \"description\": \"TypeScript definitions for Lo-Dash\",\n \"license\": \"MIT\",\n \"contributors\": [\n {\n \"name\": \"Brian Zengel\",\n \"url\": \"https://github.com/bczengel\"\n },\n {\n \"name\": \"Ilya Mochalov\",\n \"url\": \"https://github.com/chrootsu\"\n },\n {\n \"name\": \"Stepan Mikhaylyuk\",\n \"url\": \"https://github.com/stepancar\"\n },\n {\n \"name\": \"Eric L Anderson\",\n \"url\": \"https://github.com/ericanderson\"\n },\n {\n \"name\": \"AJ Richardson\",\n \"url\": \"https://github.com/aj-r\"\n },\n {\n \"name\": \"Junyoung Clare Jang\",\n \"url\": \"https://github.com/ailrun\"\n }\n ],\n \"main\": \"\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://www.github.com/DefinitelyTyped/DefinitelyTyped.git\"\n },\n \"scripts\": {},\n \"dependencies\": {},\n \"typesPublisherContentHash\": \"12af578ffaf8d86d2df37e591857906a86b983fa9258414326544a0fe6af0de8\",\n \"typeScriptVersion\": \"2.2\"\n}" }, { "path": "/a/b/node_modules/.staging/lodash-b0733faa/index.js", "content": "module.exports = require('./lodash');" }, { "path": "/a/b/node_modules/.staging/typescript-8493ea5d/package.json.3017591594" } - ); + ].map(getRootedFileOrFolder)); // Since we didnt add any supported extension file, there wont be any timeout scheduled verifyAfterPartialOrCompleteNpmInstall(0); @@ -5070,27 +5084,27 @@ namespace ts.projectSystem { filesAndFoldersToAdd.length--; verifyAfterPartialOrCompleteNpmInstall(0); - filesAndFoldersToAdd.push( + filesAndFoldersToAdd.push(...[ { "path": "/a/b/node_modules/.staging/rxjs-22375c61/bundles" }, { "path": "/a/b/node_modules/.staging/rxjs-22375c61/operator" }, { "path": "/a/b/node_modules/.staging/rxjs-22375c61/src/add/observable/dom" }, { "path": "/a/b/node_modules/.staging/@types/lodash-e56c4fe7/index.d.ts", "content": "\n// Stub for lodash\nexport = _;\nexport as namespace _;\ndeclare var _: _.LoDashStatic;\ndeclare namespace _ {\n interface LoDashStatic {\n someProp: string;\n }\n class SomeClass {\n someMethod(): void;\n }\n}" } - ); + ].map(getRootedFileOrFolder)); verifyAfterPartialOrCompleteNpmInstall(2); - filesAndFoldersToAdd.push( + filesAndFoldersToAdd.push(...[ { "path": "/a/b/node_modules/.staging/rxjs-22375c61/src/scheduler" }, { "path": "/a/b/node_modules/.staging/rxjs-22375c61/src/util" }, { "path": "/a/b/node_modules/.staging/rxjs-22375c61/symbol" }, { "path": "/a/b/node_modules/.staging/rxjs-22375c61/testing" }, { "path": "/a/b/node_modules/.staging/rxjs-22375c61/package.json.2252192041", "content": "{\n \"_args\": [\n [\n {\n \"raw\": \"rxjs@^5.4.2\",\n \"scope\": null,\n \"escapedName\": \"rxjs\",\n \"name\": \"rxjs\",\n \"rawSpec\": \"^5.4.2\",\n \"spec\": \">=5.4.2 <6.0.0\",\n \"type\": \"range\"\n },\n \"C:\\\\Users\\\\shkamat\\\\Desktop\\\\app\"\n ]\n ],\n \"_from\": \"rxjs@>=5.4.2 <6.0.0\",\n \"_id\": \"rxjs@5.4.3\",\n \"_inCache\": true,\n \"_location\": \"/rxjs\",\n \"_nodeVersion\": \"7.7.2\",\n \"_npmOperationalInternal\": {\n \"host\": \"s3://npm-registry-packages\",\n \"tmp\": \"tmp/rxjs-5.4.3.tgz_1502407898166_0.6800217325799167\"\n },\n \"_npmUser\": {\n \"name\": \"blesh\",\n \"email\": \"ben@benlesh.com\"\n },\n \"_npmVersion\": \"5.3.0\",\n \"_phantomChildren\": {},\n \"_requested\": {\n \"raw\": \"rxjs@^5.4.2\",\n \"scope\": null,\n \"escapedName\": \"rxjs\",\n \"name\": \"rxjs\",\n \"rawSpec\": \"^5.4.2\",\n \"spec\": \">=5.4.2 <6.0.0\",\n \"type\": \"range\"\n },\n \"_requiredBy\": [\n \"/\"\n ],\n \"_resolved\": \"https://registry.npmjs.org/rxjs/-/rxjs-5.4.3.tgz\",\n \"_shasum\": \"0758cddee6033d68e0fd53676f0f3596ce3d483f\",\n \"_shrinkwrap\": null,\n \"_spec\": \"rxjs@^5.4.2\",\n \"_where\": \"C:\\\\Users\\\\shkamat\\\\Desktop\\\\app\",\n \"author\": {\n \"name\": \"Ben Lesh\",\n \"email\": \"ben@benlesh.com\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/ReactiveX/RxJS/issues\"\n },\n \"config\": {\n \"commitizen\": {\n \"path\": \"cz-conventional-changelog\"\n }\n },\n \"contributors\": [\n {\n \"name\": \"Ben Lesh\",\n \"email\": \"ben@benlesh.com\"\n },\n {\n \"name\": \"Paul Taylor\",\n \"email\": \"paul.e.taylor@me.com\"\n },\n {\n \"name\": \"Jeff Cross\",\n \"email\": \"crossj@google.com\"\n },\n {\n \"name\": \"Matthew Podwysocki\",\n \"email\": \"matthewp@microsoft.com\"\n },\n {\n \"name\": \"OJ Kwon\",\n \"email\": \"kwon.ohjoong@gmail.com\"\n },\n {\n \"name\": \"Andre Staltz\",\n \"email\": \"andre@staltz.com\"\n }\n ],\n \"dependencies\": {\n \"symbol-observable\": \"^1.0.1\"\n },\n \"description\": \"Reactive Extensions for modern JavaScript\",\n \"devDependencies\": {\n \"babel-polyfill\": \"^6.23.0\",\n \"benchmark\": \"^2.1.0\",\n \"benchpress\": \"2.0.0-beta.1\",\n \"chai\": \"^3.5.0\",\n \"color\": \"^0.11.1\",\n \"colors\": \"1.1.2\",\n \"commitizen\": \"^2.8.6\",\n \"coveralls\": \"^2.11.13\",\n \"cz-conventional-changelog\": \"^1.2.0\",\n \"danger\": \"^1.1.0\",\n \"doctoc\": \"^1.0.0\",\n \"escape-string-regexp\": \"^1.0.5 \",\n \"esdoc\": \"^0.4.7\",\n \"eslint\": \"^3.8.0\",\n \"fs-extra\": \"^2.1.2\",\n \"get-folder-size\": \"^1.0.0\",\n \"glob\": \"^7.0.3\",\n \"gm\": \"^1.22.0\",\n \"google-closure-compiler-js\": \"^20170218.0.0\",\n \"gzip-size\": \"^3.0.0\",\n \"http-server\": \"^0.9.0\",\n \"husky\": \"^0.13.3\",\n \"lint-staged\": \"3.2.5\",\n \"lodash\": \"^4.15.0\",\n \"madge\": \"^1.4.3\",\n \"markdown-doctest\": \"^0.9.1\",\n \"minimist\": \"^1.2.0\",\n \"mkdirp\": \"^0.5.1\",\n \"mocha\": \"^3.0.2\",\n \"mocha-in-sauce\": \"0.0.1\",\n \"npm-run-all\": \"^4.0.2\",\n \"npm-scripts-info\": \"^0.3.4\",\n \"nyc\": \"^10.2.0\",\n \"opn-cli\": \"^3.1.0\",\n \"platform\": \"^1.3.1\",\n \"promise\": \"^7.1.1\",\n \"protractor\": \"^3.1.1\",\n \"rollup\": \"0.36.3\",\n \"rollup-plugin-inject\": \"^2.0.0\",\n \"rollup-plugin-node-resolve\": \"^2.0.0\",\n \"rx\": \"latest\",\n \"rxjs\": \"latest\",\n \"shx\": \"^0.2.2\",\n \"sinon\": \"^2.1.0\",\n \"sinon-chai\": \"^2.9.0\",\n \"source-map-support\": \"^0.4.0\",\n \"tslib\": \"^1.5.0\",\n \"tslint\": \"^4.4.2\",\n \"typescript\": \"~2.0.6\",\n \"typings\": \"^2.0.0\",\n \"validate-commit-msg\": \"^2.14.0\",\n \"watch\": \"^1.0.1\",\n \"webpack\": \"^1.13.1\",\n \"xmlhttprequest\": \"1.8.0\"\n },\n \"directories\": {},\n \"dist\": {\n \"integrity\": \"sha512-fSNi+y+P9ss+EZuV0GcIIqPUK07DEaMRUtLJvdcvMyFjc9dizuDjere+A4V7JrLGnm9iCc+nagV/4QdMTkqC4A==\",\n \"shasum\": \"0758cddee6033d68e0fd53676f0f3596ce3d483f\",\n \"tarball\": \"https://registry.npmjs.org/rxjs/-/rxjs-5.4.3.tgz\"\n },\n \"engines\": {\n \"npm\": \">=2.0.0\"\n },\n \"homepage\": \"https://github.com/ReactiveX/RxJS\",\n \"keywords\": [\n \"Rx\",\n \"RxJS\",\n \"ReactiveX\",\n \"ReactiveExtensions\",\n \"Streams\",\n \"Observables\",\n \"Observable\",\n \"Stream\",\n \"ES6\",\n \"ES2015\"\n ],\n \"license\": \"Apache-2.0\",\n \"lint-staged\": {\n \"*.@(js)\": [\n \"eslint --fix\",\n \"git add\"\n ],\n \"*.@(ts)\": [\n \"tslint --fix\",\n \"git add\"\n ]\n },\n \"main\": \"Rx.js\",\n \"maintainers\": [\n {\n \"name\": \"blesh\",\n \"email\": \"ben@benlesh.com\"\n }\n ],\n \"name\": \"rxjs\",\n \"optionalDependencies\": {},\n \"readme\": \"ERROR: No README data found!\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+ssh://git@github.com/ReactiveX/RxJS.git\"\n },\n \"scripts-info\": {\n \"info\": \"List available script\",\n \"build_all\": \"Build all packages (ES6, CJS, UMD) and generate packages\",\n \"build_cjs\": \"Build CJS package with clean up existing build, copy source into dist\",\n \"build_es6\": \"Build ES6 package with clean up existing build, copy source into dist\",\n \"build_closure_core\": \"Minify Global core build using closure compiler\",\n \"build_global\": \"Build Global package, then minify build\",\n \"build_perf\": \"Build CJS & Global build, run macro performance test\",\n \"build_test\": \"Build CJS package & test spec, execute mocha test runner\",\n \"build_cover\": \"Run lint to current code, build CJS & test spec, execute test coverage\",\n \"build_docs\": \"Build ES6 & global package, create documentation using it\",\n \"build_spec\": \"Build test specs\",\n \"check_circular_dependencies\": \"Check codebase has circular dependencies\",\n \"clean_spec\": \"Clean up existing test spec build output\",\n \"clean_dist_cjs\": \"Clean up existing CJS package output\",\n \"clean_dist_es6\": \"Clean up existing ES6 package output\",\n \"clean_dist_global\": \"Clean up existing Global package output\",\n \"commit\": \"Run git commit wizard\",\n \"compile_dist_cjs\": \"Compile codebase into CJS module\",\n \"compile_module_es6\": \"Compile codebase into ES6\",\n \"cover\": \"Execute test coverage\",\n \"lint_perf\": \"Run lint against performance test suite\",\n \"lint_spec\": \"Run lint against test spec\",\n \"lint_src\": \"Run lint against source\",\n \"lint\": \"Run lint against everything\",\n \"perf\": \"Run macro performance benchmark\",\n \"perf_micro\": \"Run micro performance benchmark\",\n \"test_mocha\": \"Execute mocha test runner against existing test spec build\",\n \"test_browser\": \"Execute mocha test runner on browser against existing test spec build\",\n \"test\": \"Clean up existing test spec build, build test spec and execute mocha test runner\",\n \"tests2png\": \"Generate marble diagram image from test spec\",\n \"watch\": \"Watch codebase, trigger compile when source code changes\"\n },\n \"typings\": \"Rx.d.ts\",\n \"version\": \"5.4.3\"\n}\n" } - ); + ].map(getRootedFileOrFolder)); verifyAfterPartialOrCompleteNpmInstall(0); // remove /a/b/node_modules/.staging/rxjs-22375c61/package.json.2252192041 filesAndFoldersToAdd.length--; // and add few more folders/files - filesAndFoldersToAdd.push( + filesAndFoldersToAdd.push(...[ { "path": "/a/b/node_modules/symbol-observable" }, { "path": "/a/b/node_modules/@types" }, { "path": "/a/b/node_modules/@types/lodash" }, @@ -5098,7 +5112,7 @@ namespace ts.projectSystem { { "path": "/a/b/node_modules/rxjs" }, { "path": "/a/b/node_modules/typescript" }, { "path": "/a/b/node_modules/.bin" } - ); + ].map(getRootedFileOrFolder)); // From the type root update verifyAfterPartialOrCompleteNpmInstall(2); @@ -5108,7 +5122,7 @@ namespace ts.projectSystem { .replace(/[\-\.][\d\w][\d\w][\d\w][\d\w][\d\w][\d\w][\d\w][\d\w]/g, ""); }); - const lodashIndexPath = "/a/b/node_modules/@types/lodash/index.d.ts"; + const lodashIndexPath = root + "/a/b/node_modules/@types/lodash/index.d.ts"; projectFiles.push(find(filesAndFoldersToAdd, f => f.path === lodashIndexPath)); // we would now not have failed lookup in the parent of appFolder since lodash is available recursiveWatchedDirectories.length = 1; @@ -5570,27 +5584,32 @@ namespace ts.projectSystem { }); describe("resolution when resolution cache size", () => { - function verifyWithMaxCacheLimit(limitHit: boolean) { + function verifyWithMaxCacheLimit(limitHit: boolean, useSlashRootAsSomeNotRootFolderInUserDirectory: boolean) { + const rootFolder = useSlashRootAsSomeNotRootFolderInUserDirectory ? "/user/username/rootfolder/otherfolder/" : "/"; const file1: FileOrFolder = { - path: "/a/b/project/file1.ts", + path: rootFolder + "a/b/project/file1.ts", content: 'import a from "file2"' }; const file2: FileOrFolder = { - path: "/a/b/node_modules/file2.d.ts", + path: rootFolder + "a/b/node_modules/file2.d.ts", content: "export class a { }" }; const file3: FileOrFolder = { - path: "/a/b/project/file3.ts", + path: rootFolder + "a/b/project/file3.ts", content: "export class c { }" }; const configFile: FileOrFolder = { - path: "/a/b/project/tsconfig.json", + path: rootFolder + "a/b/project/tsconfig.json", content: JSON.stringify({ compilerOptions: { typeRoots: [] } }) }; const projectFiles = [file1, file3, libFile, configFile]; const openFiles = [file1.path]; - const watchedRecursiveDirectories = ["/a/b/project", "/a/b/node_modules", "/a/node_modules", "/node_modules"]; + const watchedRecursiveDirectories = useSlashRootAsSomeNotRootFolderInUserDirectory ? + // Folders of node_modules lookup not in changedRoot + ["a/b/project", "a/b/node_modules", "a/node_modules", "node_modules"].map(v => rootFolder + v) : + // Folder of tsconfig + ["/a/b/project"]; const host = createServerHost(projectFiles); const { session, verifyInitialOpen, verifyProjectsUpdatedInBackgroundEventHandler } = createSession(host); const projectService = session.getProjectService(); @@ -5618,15 +5637,22 @@ namespace ts.projectSystem { projectFiles.push(file2); host.reloadFS(projectFiles); host.runQueuedTimeoutCallbacks(); - watchedRecursiveDirectories.length = 2; + if (useSlashRootAsSomeNotRootFolderInUserDirectory) { + watchedRecursiveDirectories.length = 2; + } + else { + // file2 addition wont be detected + projectFiles.pop(); + assert.isTrue(host.fileExists(file2.path)); + } verifyProject(); - verifyProjectsUpdatedInBackgroundEventHandler([{ + verifyProjectsUpdatedInBackgroundEventHandler(useSlashRootAsSomeNotRootFolderInUserDirectory ? [{ eventName: server.ProjectsUpdatedInBackgroundEvent, data: { openFiles } - }]); + }] : []); function verifyProject() { checkProjectActualFiles(project, map(projectFiles, file => file.path)); @@ -5635,12 +5661,20 @@ namespace ts.projectSystem { } } - it("limit not hit", () => { - verifyWithMaxCacheLimit(/*limitHit*/ false); + it("limit not hit and project is not at root level", () => { + verifyWithMaxCacheLimit(/*limitHit*/ false, /*useSlashRootAsSomeNotRootFolderInUserDirectory*/ true); }); - it("limit hit", () => { - verifyWithMaxCacheLimit(/*limitHit*/ true); + it("limit hit and project is not at root level", () => { + verifyWithMaxCacheLimit(/*limitHit*/ true, /*useSlashRootAsSomeNotRootFolderInUserDirectory*/ true); + }); + + it("limit not hit and project is at root level", () => { + verifyWithMaxCacheLimit(/*limitHit*/ false, /*useSlashRootAsSomeNotRootFolderInUserDirectory*/ false); + }); + + it("limit hit and project is at root level", () => { + verifyWithMaxCacheLimit(/*limitHit*/ true, /*useSlashRootAsSomeNotRootFolderInUserDirectory*/ false); }); }); } From 92d191990adee9cef63f6407ff2e2bd171a3a7a0 Mon Sep 17 00:00:00 2001 From: csigs Date: Tue, 17 Oct 2017 04:10:06 +0000 Subject: [PATCH 034/405] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 17048 ++++++++-------- 1 file changed, 8563 insertions(+), 8485 deletions(-) diff --git a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl index 79859d9bae2..38946acf472 100644 --- a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1,8486 +1,8564 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - or -. For example '{0}' or '{1}'.]]> - - oder - erforderlich, z. B. "{0}" oder "{1}".]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - type.]]> - - " sein.]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ()' instead.]]> - - ()".]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + or -. For example '{0}' or '{1}'.]]> + + oder - erforderlich, z. B. "{0}" oder "{1}".]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + type.]]> + + " sein.]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ()' instead.]]> + + ()".]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 1af25ae9f1d3ee9076af6439444c93ab21b57f69 Mon Sep 17 00:00:00 2001 From: csigs Date: Tue, 17 Oct 2017 16:10:05 +0000 Subject: [PATCH 035/405] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 74 ++++++++++++++---- .../diagnosticMessages.generated.json.lcl | 74 ++++++++++++++---- .../diagnosticMessages.generated.json.lcl | 74 ++++++++++++++---- .../diagnosticMessages.generated.json.lcl | 75 ++++++++++++++++--- .../diagnosticMessages.generated.json.lcl | 74 ++++++++++++++---- 5 files changed, 307 insertions(+), 64 deletions(-) diff --git a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl index 075923ea438..d27b3a500b8 100644 --- a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -801,6 +801,12 @@ + + + + + + @@ -1338,6 +1344,18 @@ + + + + + + + + + + + + @@ -1485,6 +1503,12 @@ + + + + + + @@ -1892,12 +1916,12 @@ - - + + - + @@ -2013,6 +2037,12 @@ + + + + + + @@ -3795,6 +3825,18 @@ + + + + + + + + + + + + @@ -3987,21 +4029,15 @@ - + - - - - + - + - - - - + @@ -7263,6 +7299,12 @@ + + + + + + @@ -7743,6 +7785,12 @@ + + + + + + diff --git a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl index 026f10b37be..43073f7cab3 100644 --- a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -801,6 +801,12 @@ + + + + + + @@ -1338,6 +1344,18 @@ + + + + + + + + + + + + @@ -1485,6 +1503,12 @@ + + + + + + @@ -1892,12 +1916,12 @@ - - + + - + @@ -2013,6 +2037,12 @@ + + + + + + @@ -3795,6 +3825,18 @@ + + + + + + + + + + + + @@ -3987,21 +4029,15 @@ - + - - - - + - + - - - - + @@ -7263,6 +7299,12 @@ + + + + + + @@ -7743,6 +7785,12 @@ + + + + + + diff --git a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl index b978802c564..727bf964abf 100644 --- a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -792,6 +792,12 @@ + + + + + + @@ -1329,6 +1335,18 @@ + + + + + + + + + + + + @@ -1476,6 +1494,12 @@ + + + + + + @@ -1883,12 +1907,12 @@ - - + + - + @@ -2004,6 +2028,12 @@ + + + + + + @@ -3786,6 +3816,18 @@ + + + + + + + + + + + + @@ -3978,21 +4020,15 @@ - + - - - - + - + - - - - + @@ -7254,6 +7290,12 @@ + + + + + + @@ -7734,6 +7776,12 @@ + + + + + + diff --git a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 3a8512e54b2..4ae9e7d5e56 100644 --- a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -782,6 +782,12 @@ + + + + + + @@ -1313,6 +1319,18 @@ + + + + + + + + + + + + @@ -1460,6 +1478,12 @@ + + + + + + @@ -1867,10 +1891,13 @@ - - + + + + + @@ -1982,6 +2009,12 @@ + + + + + + @@ -3758,6 +3791,18 @@ + + + + + + + + + + + + @@ -3950,21 +3995,15 @@ - + - - - - + - + - - - - + @@ -7217,6 +7256,12 @@ + + + + + + @@ -7697,6 +7742,12 @@ + + + + + + diff --git a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl index aac4d18cd67..b0e6c4b3495 100644 --- a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -791,6 +791,12 @@ + + + + + + @@ -1328,6 +1334,18 @@ + + + + + + + + + + + + @@ -1475,6 +1493,12 @@ + + + + + + @@ -1882,12 +1906,12 @@ - - + + - + @@ -2003,6 +2027,12 @@ + + + + + + @@ -3785,6 +3815,18 @@ + + + + + + + + + + + + @@ -3977,21 +4019,15 @@ - + - - - - + - + - - - - + @@ -7253,6 +7289,12 @@ + + + + + + @@ -7733,6 +7775,12 @@ + + + + + + From abb3f58db29e4b9889f4fcc784f5ebf9d35f5263 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Fri, 13 Oct 2017 17:14:56 -0700 Subject: [PATCH 036/405] Add support for JSX fragment syntax --- src/compiler/binder.ts | 3 ++ src/compiler/checker.ts | 73 ++++++++++++++++++---------- src/compiler/diagnosticMessages.json | 8 +++ src/compiler/emitter.ts | 40 ++++++++++----- src/compiler/factory.ts | 53 ++++++++++++++++++-- src/compiler/parser.ts | 69 +++++++++++++++++++++----- src/compiler/scanner.ts | 5 ++ src/compiler/transformers/jsx.ts | 26 ++++++++++ src/compiler/types.ts | 27 +++++++++- src/compiler/utilities.ts | 18 ++++++- src/compiler/visitor.ts | 12 +++++ tests/cases/compiler/jsxFragment.tsx | 4 ++ 12 files changed, 282 insertions(+), 56 deletions(-) create mode 100644 tests/cases/compiler/jsxFragment.tsx diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 35a62a644d8..ce02d461ed5 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -3296,6 +3296,9 @@ namespace ts { case SyntaxKind.JsxOpeningElement: case SyntaxKind.JsxText: case SyntaxKind.JsxClosingElement: + case SyntaxKind.JsxFragment: + case SyntaxKind.JsxOpeningFragment: + case SyntaxKind.JsxClosingFragment: case SyntaxKind.JsxAttribute: case SyntaxKind.JsxAttributes: case SyntaxKind.JsxSpreadAttribute: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 69a46ed6cb2..8a0e369789d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13467,32 +13467,37 @@ namespace ts { function getContextualTypeForJsxExpression(node: JsxExpression): Type { // JSX expression can appear in two position : JSX Element's children or JSX attribute - const jsxAttributes = isJsxAttributeLike(node.parent) ? + const jsxAttributes: JsxAttributes = isJsxAttributeLike(node.parent) ? node.parent.parent : - node.parent.openingElement.attributes; // node.parent is JsxElement + isJsxElement(node.parent) ? + node.parent.openingElement.attributes : + undefined; // node.parent is JsxFragment with no attributes - // When we trying to resolve JsxOpeningLikeElement as a stateless function element, we will already give its attributes a contextual type - // which is a type of the parameter of the signature we are trying out. - // If there is no contextual type (e.g. we are trying to resolve stateful component), get attributes type from resolving element's tagName - const attributesType = getContextualType(jsxAttributes); + if (jsxAttributes) { + // When we trying to resolve JsxOpeningLikeElement as a stateless function element, we will already give its attributes a contextual type + // which is a type of the parameter of the signature we are trying out. + // If there is no contextual type (e.g. we are trying to resolve stateful component), get attributes type from resolving element's tagName + const attributesType = getContextualType(jsxAttributes); - if (!attributesType || isTypeAny(attributesType)) { - return undefined; - } + if (!attributesType || isTypeAny(attributesType)) { + return undefined; + } - if (isJsxAttribute(node.parent)) { - // JSX expression is in JSX attribute - return getTypeOfPropertyOfContextualType(attributesType, node.parent.name.escapedText); - } - else if (node.parent.kind === SyntaxKind.JsxElement) { - // JSX expression is in children of JSX Element, we will look for an "children" atttribute (we get the name from JSX.ElementAttributesProperty) - const jsxChildrenPropertyName = getJsxElementChildrenPropertyname(); - return jsxChildrenPropertyName && jsxChildrenPropertyName !== "" ? getTypeOfPropertyOfContextualType(attributesType, jsxChildrenPropertyName) : anyType; - } - else { - // JSX expression is in JSX spread attribute - return attributesType; + if (isJsxAttribute(node.parent)) { + // JSX expression is in JSX attribute + return getTypeOfPropertyOfContextualType(attributesType, node.parent.name.escapedText); + } + else if (node.parent.kind === SyntaxKind.JsxElement) { + // JSX expression is in children of JSX Element, we will look for an "children" atttribute (we get the name from JSX.ElementAttributesProperty) + const jsxChildrenPropertyName = getJsxElementChildrenPropertyname(); + return jsxChildrenPropertyName && jsxChildrenPropertyName !== "" ? getTypeOfPropertyOfContextualType(attributesType, jsxChildrenPropertyName) : anyType; + } + else { + // JSX expression is in JSX spread attribute + return attributesType; + } } + return anyType; // don't check children of a fragment } function getContextualTypeForJsxAttribute(attribute: JsxAttribute | JsxSpreadAttribute) { @@ -14049,13 +14054,13 @@ namespace ts { } function checkJsxSelfClosingElement(node: JsxSelfClosingElement): Type { - checkJsxOpeningLikeElement(node); + checkJsxOpeningLikeElementOrOpeningFragment(node); return getJsxGlobalElementType() || anyType; } function checkJsxElement(node: JsxElement): Type { // Check attributes - checkJsxOpeningLikeElement(node.openingElement); + checkJsxOpeningLikeElementOrOpeningFragment(node.openingElement); // Perform resolution on the closing tag so that rename/go to definition/etc work if (isJsxIntrinsicIdentifier(node.closingElement.tagName)) { @@ -14068,6 +14073,11 @@ namespace ts { return getJsxGlobalElementType() || anyType; } + function checkJsxFragment(node: JsxFragment): Type { + checkJsxOpeningLikeElementOrOpeningFragment(node.openingFragment); + return getJsxGlobalElementType() || anyType; + } + /** * Returns true iff the JSX element name would be a valid JS identifier, ignoring restrictions about keywords not being identifiers */ @@ -14731,14 +14741,19 @@ namespace ts { } } - function checkJsxOpeningLikeElement(node: JsxOpeningLikeElement) { - checkGrammarJsxElement(node); + function checkJsxOpeningLikeElementOrOpeningFragment(node: JsxOpeningLikeElement | JsxOpeningFragment) { + const isNodeOpeningLikeElement = isJsxOpeningLikeElement(node); + + if (isNodeOpeningLikeElement) { + checkGrammarJsxElement(node); + } checkJsxPreconditions(node); // The reactNamespace/jsxFactory's root symbol should be marked as 'used' so we don't incorrectly elide its import. // And if there is no reactNamespace/jsxFactory's symbol in scope when targeting React emit, we should issue an error. const reactRefErr = diagnostics && compilerOptions.jsx === JsxEmit.React ? Diagnostics.Cannot_find_name_0 : undefined; const reactNamespace = getJsxNamespace(); - const reactSym = resolveName(node.tagName, reactNamespace, SymbolFlags.Value, reactRefErr, reactNamespace, /*isUse*/ true); + const reactLocation = isNodeOpeningLikeElement ? (node).tagName : node; + const reactSym = resolveName(reactLocation, reactNamespace, SymbolFlags.Value, reactRefErr, reactNamespace, /*isUse*/ true); if (reactSym) { // Mark local symbol as referenced here because it might not have been marked // if jsx emit was not react as there wont be error being emitted @@ -14750,7 +14765,9 @@ namespace ts { } } - checkJsxAttributesAssignableToTagNameAttributes(node); + if (isNodeOpeningLikeElement) { + checkJsxAttributesAssignableToTagNameAttributes(node); + } } /** @@ -18518,6 +18535,8 @@ namespace ts { return checkJsxElement(node); case SyntaxKind.JsxSelfClosingElement: return checkJsxSelfClosingElement(node); + case SyntaxKind.JsxFragment: + return checkJsxFragment(node); case SyntaxKind.JsxAttributes: return checkJsxAttributes(node, checkMode); case SyntaxKind.JsxOpeningElement: diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 8cd5088049c..68cc5a7309e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3607,6 +3607,14 @@ "category": "Error", "code": 17013 }, + "JSX fragment has no corresponding closing tag.": { + "category": "Error", + "code": 17014 + }, + "Expected corresponding JSX fragment closing tag.": { + "category": "Error", + "code": 17015 + }, "Circularity detected while resolving configuration: {0}": { "category": "Error", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 9ce220e723f..ced57157b26 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -699,9 +699,11 @@ namespace ts { case SyntaxKind.JsxText: return emitJsxText(node); case SyntaxKind.JsxOpeningElement: - return emitJsxOpeningElement(node); + case SyntaxKind.JsxOpeningFragment: + return emitJsxOpeningElementOrFragment(node); case SyntaxKind.JsxClosingElement: - return emitJsxClosingElement(node); + case SyntaxKind.JsxClosingFragment: + return emitJsxClosingElementOrFragment(node); case SyntaxKind.JsxAttribute: return emitJsxAttribute(node); case SyntaxKind.JsxAttributes: @@ -836,6 +838,8 @@ namespace ts { return emitJsxElement(node); case SyntaxKind.JsxSelfClosingElement: return emitJsxSelfClosingElement(node); + case SyntaxKind.JsxFragment: + return emitJsxFragment(node); // Transformation nodes case SyntaxKind.PartiallyEmittedExpression: @@ -2060,7 +2064,7 @@ namespace ts { function emitJsxElement(node: JsxElement) { emit(node.openingElement); - emitList(node, node.children, ListFormat.JsxElementChildren); + emitList(node, node.children, ListFormat.JsxElementOrFragmentChildren); emit(node.closingElement); } @@ -2075,14 +2079,24 @@ namespace ts { write("/>"); } - function emitJsxOpeningElement(node: JsxOpeningElement) { + function emitJsxFragment(node: JsxFragment) { + emit(node.openingFragment); + emitList(node, node.children, ListFormat.JsxElementOrFragmentChildren); + emit(node.closingFragment); + } + + function emitJsxOpeningElementOrFragment(node: JsxOpeningElement | JsxOpeningFragment) { write("<"); - emitJsxTagName(node.tagName); - writeIfAny(node.attributes.properties, " "); - // We are checking here so we won't re-enter the emitting pipeline and emit extra sourcemap - if (node.attributes.properties && node.attributes.properties.length > 0) { - emit(node.attributes); + + if (isJsxOpeningElement(node)) { + emitJsxTagName(node.tagName); + writeIfAny(node.attributes.properties, " "); + // We are checking here so we won't re-enter the emitting pipeline and emit extra sourcemap + if (node.attributes.properties && node.attributes.properties.length > 0) { + emit(node.attributes); + } } + write(">"); } @@ -2090,9 +2104,11 @@ namespace ts { writer.writeLiteral(getTextOfNode(node, /*includeTrivia*/ true)); } - function emitJsxClosingElement(node: JsxClosingElement) { + function emitJsxClosingElementOrFragment(node: JsxClosingElement | JsxClosingFragment) { write(""); } @@ -3176,7 +3192,7 @@ namespace ts { EnumMembers = CommaDelimited | Indented | MultiLine, CaseBlockClauses = Indented | MultiLine, NamedImportsOrExportsElements = CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | SingleLine | SpaceBetweenBraces, - JsxElementChildren = SingleLine | NoInterveningComments, + JsxElementOrFragmentChildren = SingleLine | NoInterveningComments, JsxElementAttributes = SingleLine | SpaceBetweenSiblings | NoInterveningComments, CaseOrDefaultClauseStatements = Indented | MultiLine | NoTrailingNewLine | OptionalIfEmpty, HeritageClauseTypes = CommaDelimited | SpaceBetweenSiblings | SingleLine, diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 65c1c92f366..8d66608c226 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2115,6 +2115,22 @@ namespace ts { : node; } + export function createJsxFragment(openingFragment: JsxOpeningFragment, children: ReadonlyArray, closingFragment: JsxClosingFragment) { + const node = createSynthesizedNode(SyntaxKind.JsxFragment); + node.openingFragment = openingFragment; + node.children = createNodeArray(children); + node.closingFragment = closingFragment; + return node; + } + + export function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: ReadonlyArray, closingFragment: JsxClosingFragment) { + return node.openingFragment !== openingFragment + || node.children !== children + || node.closingFragment !== closingFragment + ? updateNode(createJsxFragment(openingFragment, children, closingFragment), node) + : node; + } + export function createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression) { const node = createSynthesizedNode(SyntaxKind.JsxAttribute); node.name = name; @@ -2951,7 +2967,7 @@ namespace ts { ); } - function createReactNamespace(reactNamespace: string, parent: JsxOpeningLikeElement) { + function createReactNamespace(reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment) { // To ensure the emit resolver can properly resolve the namespace, we need to // treat this identifier as if it were a source tree node by clearing the `Synthesized` // flag and setting a parent node. @@ -2963,7 +2979,7 @@ namespace ts { return react; } - function createJsxFactoryExpressionFromEntityName(jsxFactory: EntityName, parent: JsxOpeningLikeElement): Expression { + function createJsxFactoryExpressionFromEntityName(jsxFactory: EntityName, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { if (isQualifiedName(jsxFactory)) { const left = createJsxFactoryExpressionFromEntityName(jsxFactory.left, parent); const right = createIdentifier(idText(jsxFactory.right)); @@ -2975,7 +2991,7 @@ namespace ts { } } - function createJsxFactoryExpression(jsxFactoryEntity: EntityName, reactNamespace: string, parent: JsxOpeningLikeElement): Expression { + function createJsxFactoryExpression(jsxFactoryEntity: EntityName, reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { return jsxFactoryEntity ? createJsxFactoryExpressionFromEntityName(jsxFactoryEntity, parent) : createPropertyAccess( @@ -3016,6 +3032,37 @@ namespace ts { ); } + export function createExpressionForJsxFragment(jsxFactoryEntity: EntityName, reactNamespace: string, children: Expression[], parentElement: JsxOpeningFragment, location: TextRange): LeftHandSideExpression { + const tagName = createPropertyAccess( + createReactNamespace(reactNamespace, parentElement), + "Fragment" + ); + + const argumentsList = [tagName]; + argumentsList.push(createNull()); + + if (children && children.length > 0) { + if (children.length > 1) { + for (const child of children) { + child.startsOnNewLine = true; + argumentsList.push(child); + } + } + else { + argumentsList.push(children[0]); + } + } + + return setTextRange( + createCall( + createJsxFactoryExpression(jsxFactoryEntity, reactNamespace, parentElement), + /*typeArguments*/ undefined, + argumentsList + ), + location + ); + } + // Helpers export function getHelperName(name: string) { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index e2bae71e6bf..28329791045 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -377,6 +377,10 @@ namespace ts { return visitNode(cbNode, (node).openingElement) || visitNodes(cbNode, cbNodes, (node).children) || visitNode(cbNode, (node).closingElement); + case SyntaxKind.JsxFragment: + return visitNode(cbNode, (node).openingFragment) || + visitNodes(cbNode, cbNodes, (node).children) || + visitNode(cbNode, (node).closingFragment); case SyntaxKind.JsxSelfClosingElement: case SyntaxKind.JsxOpeningElement: return visitNode(cbNode, (node).tagName) || @@ -1423,6 +1427,11 @@ namespace ts { return tokenIsIdentifierOrKeyword(token()); } + function nextTokenIsIdentifierOrKeywordOrGreaterThan() { + nextToken(); + return tokenIsIdentifierOrKeywordOrGreaterThan(token()); + } + function isHeritageClauseExtendsOrImplementsKeyword(): boolean { if (token() === SyntaxKind.ImplementsKeyword || token() === SyntaxKind.ExtendsKeyword) { @@ -3802,9 +3811,9 @@ namespace ts { node.operand = parseLeftHandSideExpressionOrHigher(); return finishNode(node); } - else if (sourceFile.languageVariant === LanguageVariant.JSX && token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsIdentifierOrKeyword)) { + else if (sourceFile.languageVariant === LanguageVariant.JSX && token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { // JSXElement is part of primaryExpression - return parseJsxElementOrSelfClosingElement(/*inExpressionContext*/ true); + return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); } const expression = parseLeftHandSideExpressionOrHigher(); @@ -3959,14 +3968,14 @@ namespace ts { } - function parseJsxElementOrSelfClosingElement(inExpressionContext: boolean): JsxElement | JsxSelfClosingElement { - const opening = parseJsxOpeningOrSelfClosingElement(inExpressionContext); - let result: JsxElement | JsxSelfClosingElement; + function parseJsxElementOrSelfClosingElementOrFragment(inExpressionContext: boolean): JsxElement | JsxSelfClosingElement | JsxFragment { + const opening = parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext); + let result: JsxElement | JsxSelfClosingElement | JsxFragment; if (opening.kind === SyntaxKind.JsxOpeningElement) { const node = createNode(SyntaxKind.JsxElement, opening.pos); node.openingElement = opening; - node.children = parseJsxChildren(node.openingElement.tagName); + node.children = parseJsxChildren(node.openingElement); node.closingElement = parseJsxClosingElement(inExpressionContext); if (!tagNamesAreEquivalent(node.openingElement.tagName, node.closingElement.tagName)) { @@ -3975,6 +3984,15 @@ namespace ts { result = finishNode(node); } + else if (opening.kind === SyntaxKind.JsxOpeningFragment) { + const node = createNode(SyntaxKind.JsxFragment, opening.pos); + node.openingFragment = opening; + + node.children = parseJsxChildren(node.openingFragment); + node.closingFragment = parseJsxClosingFragment(inExpressionContext); + + result = finishNode(node); + } else { Debug.assert(opening.kind === SyntaxKind.JsxSelfClosingElement); // Nothing else to do for self-closing elements @@ -3989,7 +4007,7 @@ namespace ts { // Since JSX elements are invalid < operands anyway, this lookahead parse will only occur in error scenarios // of one sort or another. if (inExpressionContext && token() === SyntaxKind.LessThanToken) { - const invalidElement = tryParse(() => parseJsxElementOrSelfClosingElement(/*inExpressionContext*/ true)); + const invalidElement = tryParse(() => parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true)); if (invalidElement) { parseErrorAtCurrentToken(Diagnostics.JSX_expressions_must_have_one_parent_element); const badNode = createNode(SyntaxKind.BinaryExpression, result.pos); @@ -4020,12 +4038,12 @@ namespace ts { case SyntaxKind.OpenBraceToken: return parseJsxExpression(/*inExpressionContext*/ false); case SyntaxKind.LessThanToken: - return parseJsxElementOrSelfClosingElement(/*inExpressionContext*/ false); + return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ false); } Debug.fail("Unknown JSX child kind " + token()); } - function parseJsxChildren(openingTagName: LeftHandSideExpression): NodeArray { + function parseJsxChildren(openingTag: JsxOpeningElement | JsxOpeningFragment): NodeArray { const list = []; const listPos = getNodePos(); const saveParsingContext = parsingContext; @@ -4040,7 +4058,13 @@ namespace ts { else if (token() === SyntaxKind.EndOfFileToken) { // If we hit EOF, issue the error at the tag that lacks the closing element // rather than at the end of the file (which is useless) - parseErrorAtPosition(openingTagName.pos, openingTagName.end - openingTagName.pos, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTagName)); + if (isJsxOpeningElement(openingTag)) { + const openingTagName = openingTag.tagName; + parseErrorAtPosition(openingTagName.pos, openingTagName.end - openingTagName.pos, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTagName)); + } + else { + parseErrorAtPosition(openingTag.pos, openingTag.end - openingTag.pos, Diagnostics.JSX_fragment_has_no_corresponding_closing_tag); + } break; } else if (token() === SyntaxKind.ConflictMarkerTrivia) { @@ -4063,11 +4087,17 @@ namespace ts { return finishNode(jsxAttributes); } - function parseJsxOpeningOrSelfClosingElement(inExpressionContext: boolean): JsxOpeningElement | JsxSelfClosingElement { + function parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext: boolean): JsxOpeningElement | JsxSelfClosingElement | JsxOpeningFragment { const fullStart = scanner.getStartPos(); parseExpected(SyntaxKind.LessThanToken); + if (token() === SyntaxKind.GreaterThanToken) { + parseExpected(SyntaxKind.GreaterThanToken); + const node: JsxOpeningFragment = createNode(SyntaxKind.JsxOpeningFragment, fullStart); + return finishNode(node); + } + const tagName = parseJsxElementName(); const attributes = parseJsxAttributes(); @@ -4179,6 +4209,23 @@ namespace ts { return finishNode(node); } + function parseJsxClosingFragment(inExpressionContext: boolean): JsxClosingFragment { + const node = createNode(SyntaxKind.JsxClosingFragment); + parseExpected(SyntaxKind.LessThanSlashToken); + if (tokenIsIdentifierOrKeyword(token())) { + const unexpectedTagName = parseJsxElementName(); + parseErrorAtPosition(unexpectedTagName.pos, unexpectedTagName.end - unexpectedTagName.pos, Diagnostics.Expected_corresponding_JSX_fragment_closing_tag); + } + if (inExpressionContext) { + parseExpected(SyntaxKind.GreaterThanToken); + } + else { + parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false); + scanJsxText(); + } + return finishNode(node); + } + function parseTypeAssertion(): TypeAssertion { const node = createNode(SyntaxKind.TypeAssertionExpression); parseExpected(SyntaxKind.LessThanToken); diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index b19a1466328..67d83f262c8 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -11,6 +11,11 @@ namespace ts { return token >= SyntaxKind.Identifier; } + /* @internal */ + export function tokenIsIdentifierOrKeywordOrGreaterThan(token: SyntaxKind): boolean { + return token === SyntaxKind.GreaterThanToken || token >= SyntaxKind.Identifier; + } + export interface Scanner { getStartPos(): number; getToken(): SyntaxKind; diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index bbe05afe878..2be6cdef0bc 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -41,6 +41,9 @@ namespace ts { case SyntaxKind.JsxSelfClosingElement: return visitJsxSelfClosingElement(node, /*isChild*/ false); + case SyntaxKind.JsxFragment: + return visitJsxFragment(node, /*isChild*/ false); + case SyntaxKind.JsxExpression: return visitJsxExpression(node); @@ -63,6 +66,9 @@ namespace ts { case SyntaxKind.JsxSelfClosingElement: return visitJsxSelfClosingElement(node, /*isChild*/ true); + case SyntaxKind.JsxFragment: + return visitJsxFragment(node, /*isChild*/ true); + default: Debug.failBadSyntaxKind(node); return undefined; @@ -77,6 +83,10 @@ namespace ts { return visitJsxOpeningLikeElement(node, /*children*/ undefined, isChild, /*location*/ node); } + function visitJsxFragment(node: JsxFragment, isChild: boolean) { + return visitJsxOpeningFragment(node.openingFragment, node.children, isChild, /*location*/ node); + } + function visitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: ReadonlyArray, isChild: boolean, location: TextRange) { const tagName = getTagName(node); let objectProperties: Expression; @@ -126,6 +136,22 @@ namespace ts { return element; } + function visitJsxOpeningFragment(node: JsxOpeningFragment, children: ReadonlyArray, isChild: boolean, location: TextRange) { + const element = createExpressionForJsxFragment( + context.getEmitResolver().getJsxFactoryEntity(), + compilerOptions.reactNamespace, + mapDefined(children, transformJsxChildToExpression), + node, + location + ); + + if (isChild) { + startOnNewLine(element); + } + + return element; + } + function transformJsxSpreadAttributeToExpression(node: JsxSpreadAttribute) { return visitNode(node.expression, visitor, isExpression); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 42e8292b13b..27cba8ef777 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -328,6 +328,9 @@ namespace ts { JsxSelfClosingElement, JsxOpeningElement, JsxClosingElement, + JsxFragment, + JsxOpeningFragment, + JsxClosingFragment, JsxAttribute, JsxAttributes, JsxSpreadAttribute, @@ -1618,7 +1621,7 @@ namespace ts { closingElement: JsxClosingElement; } - /// Either the opening tag in a ... pair, or the lone in a self-closing form + /// Either the opening tag in a ... pair, the opening tag in a <>... pair, or the lone in a self-closing form export type JsxOpeningLikeElement = JsxSelfClosingElement | JsxOpeningElement; export type JsxAttributeLike = JsxAttribute | JsxSpreadAttribute; @@ -1644,6 +1647,26 @@ namespace ts { attributes: JsxAttributes; } + /// A JSX expression of the form <>... + export interface JsxFragment extends PrimaryExpression { + kind: SyntaxKind.JsxFragment; + openingFragment: JsxOpeningFragment; + children: NodeArray; + closingFragment: JsxClosingFragment; + } + + /// The opening element of a <>... JsxFragment + export interface JsxOpeningFragment extends Expression { + kind: SyntaxKind.JsxOpeningFragment; + parent?: JsxFragment; + } + + /// The closing element of a <>... JsxFragment + export interface JsxClosingFragment extends Expression { + kind: SyntaxKind.JsxClosingFragment; + parent?: JsxFragment; + } + export interface JsxAttribute extends ObjectLiteralElement { kind: SyntaxKind.JsxAttribute; parent?: JsxAttributes; @@ -1677,7 +1700,7 @@ namespace ts { parent?: JsxElement; } - export type JsxChild = JsxText | JsxExpression | JsxElement | JsxSelfClosingElement; + export type JsxChild = JsxText | JsxExpression | JsxElement | JsxSelfClosingElement | JsxFragment; export interface Statement extends Node { _statementBrand: any; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index c4d3de453ba..bfb9e488c92 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1251,6 +1251,7 @@ namespace ts { case SyntaxKind.OmittedExpression: case SyntaxKind.JsxElement: case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxFragment: case SyntaxKind.YieldExpression: case SyntaxKind.AwaitExpression: case SyntaxKind.MetaProperty: @@ -2136,6 +2137,7 @@ namespace ts { case SyntaxKind.ClassExpression: case SyntaxKind.JsxElement: case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxFragment: case SyntaxKind.RegularExpressionLiteral: case SyntaxKind.NoSubstitutionTemplateLiteral: case SyntaxKind.TemplateExpression: @@ -4760,6 +4762,18 @@ namespace ts { return node.kind === SyntaxKind.JsxClosingElement; } + export function isJsxFragment(node: Node): node is JsxFragment { + return node.kind === SyntaxKind.JsxFragment; + } + + export function isJsxOpeningFragment(node: Node): node is JsxOpeningFragment { + return node.kind === SyntaxKind.JsxOpeningFragment; + } + + export function isJsxClosingFragment(node: Node): node is JsxClosingFragment { + return node.kind === SyntaxKind.JsxClosingFragment; + } + export function isJsxAttribute(node: Node): node is JsxAttribute { return node.kind === SyntaxKind.JsxAttribute; } @@ -5285,6 +5299,7 @@ namespace ts { case SyntaxKind.CallExpression: case SyntaxKind.JsxElement: case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxFragment: case SyntaxKind.TaggedTemplateExpression: case SyntaxKind.ArrayLiteralExpression: case SyntaxKind.ParenthesizedExpression: @@ -5606,7 +5621,8 @@ namespace ts { return kind === SyntaxKind.JsxElement || kind === SyntaxKind.JsxExpression || kind === SyntaxKind.JsxSelfClosingElement - || kind === SyntaxKind.JsxText; + || kind === SyntaxKind.JsxText + || kind === SyntaxKind.JsxFragment; } /* @internal */ diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 7d46630e227..0428d2d2d2e 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -819,6 +819,12 @@ namespace ts { return updateJsxClosingElement(node, visitNode((node).tagName, visitor, isJsxTagNameExpression)); + case SyntaxKind.JsxFragment: + return updateJsxFragment(node, + visitNode((node).openingFragment, visitor, isJsxOpeningFragment), + nodesVisitor((node).children, visitor, isJsxChild), + visitNode((node).closingFragment, visitor, isJsxClosingFragment)); + case SyntaxKind.JsxAttribute: return updateJsxAttribute(node, visitNode((node).name, visitor, isIdentifier), @@ -1334,6 +1340,12 @@ namespace ts { result = reduceNode((node).closingElement, cbNode, result); break; + case SyntaxKind.JsxFragment: + result = reduceNode((node).openingFragment, cbNode, result); + result = reduceLeft((node).children, cbNode, result); + result = reduceNode((node).closingFragment, cbNode, result); + break; + case SyntaxKind.JsxSelfClosingElement: case SyntaxKind.JsxOpeningElement: result = reduceNode((node).tagName, cbNode, result); diff --git a/tests/cases/compiler/jsxFragment.tsx b/tests/cases/compiler/jsxFragment.tsx new file mode 100644 index 00000000000..82e093327be --- /dev/null +++ b/tests/cases/compiler/jsxFragment.tsx @@ -0,0 +1,4 @@ +//@jsx: react + +declare var React: any; +
; \ No newline at end of file From 269d37a2e6c1e41a002fa5c0f18e23654b73cbfc Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Mon, 16 Oct 2017 16:51:39 -0700 Subject: [PATCH 037/405] Update tests --- tests/cases/compiler/jsxFragment.tsx | 4 -- .../jsx/checkJsxChildrenProperty14.tsx | 48 +++++++++++++++++++ .../conformance/jsx/tsxFragmentErrors.tsx | 14 ++++++ .../jsx/tsxFragmentPreserveEmit.tsx | 17 +++++++ .../conformance/jsx/tsxFragmentReactEmit.tsx | 17 +++++++ 5 files changed, 96 insertions(+), 4 deletions(-) delete mode 100644 tests/cases/compiler/jsxFragment.tsx create mode 100644 tests/cases/conformance/jsx/checkJsxChildrenProperty14.tsx create mode 100644 tests/cases/conformance/jsx/tsxFragmentErrors.tsx create mode 100644 tests/cases/conformance/jsx/tsxFragmentPreserveEmit.tsx create mode 100644 tests/cases/conformance/jsx/tsxFragmentReactEmit.tsx diff --git a/tests/cases/compiler/jsxFragment.tsx b/tests/cases/compiler/jsxFragment.tsx deleted file mode 100644 index 82e093327be..00000000000 --- a/tests/cases/compiler/jsxFragment.tsx +++ /dev/null @@ -1,4 +0,0 @@ -//@jsx: react - -declare var React: any; -
; \ No newline at end of file diff --git a/tests/cases/conformance/jsx/checkJsxChildrenProperty14.tsx b/tests/cases/conformance/jsx/checkJsxChildrenProperty14.tsx new file mode 100644 index 00000000000..65dfc720003 --- /dev/null +++ b/tests/cases/conformance/jsx/checkJsxChildrenProperty14.tsx @@ -0,0 +1,48 @@ +// @filename: file.tsx +// @jsx: preserve +// @noLib: true +// @skipLibCheck: true +// @libFiles: react.d.ts,lib.d.ts + +import React = require('react'); + +interface Prop { + a: number, + b: string, + children: JSX.Element | JSX.Element[]; +} + +class Button extends React.Component { + render() { + return (
My Button
) + } +} + +function AnotherButton(p: any) { + return

Just Another Button

; +} + +function Comp(p: Prop) { + return
{p.b}
; +} + +// OK +let k1 = <>