From 1f77317b6459641212efcf3fd6b9b6aa005ba968 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sun, 13 Aug 2017 15:12:11 +0800 Subject: [PATCH 01/73] 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 02/73] 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 dcd2ddd0b71f6682c3d020ada0e9ac482b9b3d33 Mon Sep 17 00:00:00 2001 From: Yuval Greenfield Date: Tue, 26 Sep 2017 12:09:58 -0700 Subject: [PATCH 03/73] 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 da63c2c57977840cf0b349c84ab139a92e6f4787 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 27 Oct 2017 16:24:12 -0700 Subject: [PATCH 04/73] Exclude legacy safelist files in external projects --- src/compiler/core.ts | 7 ++++ src/server/editorServices.ts | 33 +++++++++++++++---- src/services/jsTyping.ts | 2 +- .../reference/api/tsserverlibrary.d.ts | 7 ++-- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 12b8dd2f87e..c9b644b22ce 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2413,6 +2413,13 @@ namespace ts { return (removeFileExtension(path) + newExtension); } + /** + * Takes a string like "jquery-min.4.2.3" and returns "jquery" + */ + export function removeMinAndVersionNumbers(fileName: string) { + return fileName.replace(/((?:\.|-)min(?=\.|$))|((?:-|\.)\d+)/g, ""); + } + export interface ObjectAllocator { getNodeConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Node; getTokenConstructor(): new (kind: TKind, pos?: number, end?: number) => Token; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index b7617e1fa17..eb2ae0f3cd9 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -110,7 +110,7 @@ namespace ts.server { export interface TypesMapFile { typesMap: SafeList; - simpleMap: string[]; + simpleMap: { [libName: string]: string }; } /** @@ -374,6 +374,7 @@ namespace ts.server { private readonly hostConfiguration: HostConfiguration; private safelist: SafeList = defaultTypeSafeList; + private legacySafelist: { [key: string]: string } = {}; private changedFiles: ScriptInfo[]; private pendingProjectUpdates = createMap(); @@ -426,9 +427,12 @@ namespace ts.server { this.toCanonicalFileName = createGetCanonicalFileName(this.host.useCaseSensitiveFileNames); this.throttledOperations = new ThrottledOperations(this.host, this.logger); - if (opts.typesMapLocation) { + if (this.typesMapLocation) { this.loadTypesMap(); } + else { + this.logger.info("No types map provided; using the default"); + } this.typingsInstaller.attach(this); @@ -518,10 +522,12 @@ namespace ts.server { } // raw is now fixed and ready this.safelist = raw.typesMap; + this.legacySafelist = raw.simpleMap; } catch (e) { this.logger.info(`Error loading types map: ${e}`); this.safelist = defaultTypeSafeList; + this.legacySafelist = {}; } } @@ -1393,7 +1399,7 @@ namespace ts.server { return false; } - private createExternalProject(projectFileName: string, files: protocol.ExternalFile[], options: protocol.ExternalProjectCompilerOptions, typeAcquisition: TypeAcquisition) { + private createExternalProject(projectFileName: string, files: protocol.ExternalFile[], options: protocol.ExternalProjectCompilerOptions, typeAcquisition: TypeAcquisition, excludedFiles: NormalizedPath[]) { const compilerOptions = convertCompilerOptions(options); const project = new ExternalProject( projectFileName, @@ -1402,6 +1408,7 @@ namespace ts.server { compilerOptions, /*languageServiceEnabled*/ !this.exceededTotalSizeLimitForNonTsFiles(projectFileName, compilerOptions, files, externalFilePropertyReader), options.compileOnSave === undefined ? true : options.compileOnSave); + project.excludedFiles = excludedFiles; this.addFilesToNonInferredProjectAndUpdateGraph(project, files, externalFilePropertyReader, typeAcquisition); this.externalProjects.push(project); @@ -2204,7 +2211,22 @@ namespace ts.server { excludedFiles.push(normalizedNames[i]); } else { - filesToKeep.push(proj.rootFiles[i]); + let exclude = false; + if (typeAcquisition && (typeAcquisition.enable || typeAcquisition.enableAutoDiscovery)) { + const baseName = getBaseFileName(normalizedNames[i].toLowerCase()); + if (fileExtensionIs(baseName, "js")) { + const inferredTypingName = removeFileExtension(baseName); + const cleanedTypingName = removeMinAndVersionNumbers(inferredTypingName); + if (this.legacySafelist[cleanedTypingName]) { + this.logger.info(`Excluded '${normalizedNames[i]}'`); + excludedFiles.push(normalizedNames[i]); + exclude = true; + } + } + } + if (!exclude) { + filesToKeep.push(proj.rootFiles[i]); + } } } proj.rootFiles = filesToKeep; @@ -2312,8 +2334,7 @@ namespace ts.server { else { // no config files - remove the item from the collection this.externalProjectToConfiguredProjectMap.delete(proj.projectFileName); - const newProj = this.createExternalProject(proj.projectFileName, rootFiles, proj.options, proj.typeAcquisition); - newProj.excludedFiles = excludedFiles; + this.createExternalProject(proj.projectFileName, rootFiles, proj.options, proj.typeAcquisition, excludedFiles); } if (!suppressRefreshOfInferredProjects) { this.ensureProjectStructuresUptoDate(/*refreshInferredProjects*/ true); diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index 572858dd2fd..e31201b951f 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -180,7 +180,7 @@ namespace ts.JsTyping { if (!hasJavaScriptFileExtension(j)) return undefined; const inferredTypingName = removeFileExtension(getBaseFileName(j.toLowerCase())); - const cleanedTypingName = inferredTypingName.replace(/((?:\.|-)min(?=\.|$))|((?:-|\.)\d+)/g, ""); + const cleanedTypingName = removeMinAndVersionNumbers(inferredTypingName); return safeList.get(cleanedTypingName); }); if (fromFileNames.length) { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 5d439e840b0..44c8095b9fb 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7391,7 +7391,9 @@ declare namespace ts.server { } interface TypesMapFile { typesMap: SafeList; - simpleMap: string[]; + simpleMap: { + [libName: string]: string; + }; } function convertFormatOptions(protocolOptions: protocol.FormatCodeSettings): FormatCodeSettings; function convertCompilerOptions(protocolOptions: protocol.ExternalProjectCompilerOptions): CompilerOptions & protocol.CompileOnSaveMixin; @@ -7468,6 +7470,7 @@ declare namespace ts.server { private readonly throttledOperations; private readonly hostConfiguration; private safelist; + private legacySafelist; private changedFiles; private pendingProjectUpdates; private pendingInferredProjectUpdate; @@ -7576,7 +7579,7 @@ declare namespace ts.server { private findExternalProjectByProjectName(projectFileName); private convertConfigFileContentToProjectOptions(configFilename, cachedDirectoryStructureHost); private exceededTotalSizeLimitForNonTsFiles(name, options, fileNames, propertyReader); - private createExternalProject(projectFileName, files, options, typeAcquisition); + private createExternalProject(projectFileName, files, options, typeAcquisition, excludedFiles); private sendProjectTelemetry(projectKey, project, projectOptions?); private addFilesToNonInferredProjectAndUpdateGraph(project, files, propertyReader, typeAcquisition); private createConfiguredProject(configFileName); From 5830bb9b19f400994f77bdb1df0b5aff888dbdc3 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 27 Oct 2017 17:07:04 -0700 Subject: [PATCH 05/73] Improved logging --- src/server/editorServices.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index eb2ae0f3cd9..0bd02f32d95 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -2152,7 +2152,7 @@ namespace ts.server { const rule = this.safelist[name]; for (const root of normalizedNames) { if (rule.match.test(root)) { - this.logger.info(`Excluding files based on rule ${name}`); + this.logger.info(`Excluding files based on rule ${name} matching file '${root}'`); // If the file matches, collect its types packages and exclude rules if (rule.types) { @@ -2218,7 +2218,7 @@ namespace ts.server { const inferredTypingName = removeFileExtension(baseName); const cleanedTypingName = removeMinAndVersionNumbers(inferredTypingName); if (this.legacySafelist[cleanedTypingName]) { - this.logger.info(`Excluded '${normalizedNames[i]}'`); + this.logger.info(`Excluded '${normalizedNames[i]}' because it matched ${cleanedTypingName} from the legacy safelist`); excludedFiles.push(normalizedNames[i]); exclude = true; } From 5395d0ddb872acb83c2cca3ec31240572082db05 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 30 Oct 2017 10:44:51 -0700 Subject: [PATCH 06/73] Add test --- .../unittests/tsserverProjectSystem.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index bc8b476ceb9..fb2bbec6741 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -1496,6 +1496,26 @@ namespace ts.projectSystem { } }); + it("ignores files excluded by a legacy safe type list", () => { + const file1 = { + path: "/a/b/bliss.js", + content: "let x = 5" + }; + const file2 = { + path: "/a/b/foo.js", + content: "" + }; + const host = createServerHost([file1, file2, customTypesMap]); + const projectService = createProjectService(host); + try { + projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path, file2.path]), typeAcquisition: { enable: true } }); + const proj = projectService.externalProjects[0]; + assert.deepEqual(proj.getFileNames(), [file2.path]); + } finally { + projectService.resetSafeList(); + } + }); + it("open file become a part of configured project if it is referenced from root file", () => { const file1 = { path: "/a/b/f1.ts", From 5dc02ef5ccf267c0f4a07f4571d0b8d603a9eefa Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 31 Oct 2017 18:38:00 -0700 Subject: [PATCH 07/73] Use a different RegEx --- src/compiler/core.ts | 8 ++++++- .../unittests/tsserverProjectSystem.ts | 22 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index c9b644b22ce..626480035b1 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2417,7 +2417,13 @@ namespace ts { * Takes a string like "jquery-min.4.2.3" and returns "jquery" */ export function removeMinAndVersionNumbers(fileName: string) { - return fileName.replace(/((?:\.|-)min(?=\.|$))|((?:-|\.)\d+)/g, ""); + const match = /((\w|(-(?!min)))+)(\.|-)?.*/.exec(fileName); + if (match) { + return match[1]; + } + else { + return fileName; + } } export interface ObjectAllocator { diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index fb2bbec6741..c72a27e173e 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -1496,6 +1496,28 @@ namespace ts.projectSystem { } }); + it("removes version numbers correctly", () => { + const testData: [string, string][] = [ + ["jquery-max", "jquery-max"], + ["jquery.min", "jquery"], + ["jquery-min.4.2.3", "jquery"], + ["jquery.4.2-test.js", "jquery"], + ["jquery.min.4.2.1", "jquery"], + ["jquery.7.min.js", "jquery"], + ["jquery.7.min-beta", "jquery"], + ["minimum", "minimum"], + ["min", "min"], + ["min.3.2", "min"], + ["jquery", "jquery"] + ]; + const suffixes = [".js", ".jsx", ""]; + for (const t of testData) { + for (const suf of suffixes) { + assert.equal(removeMinAndVersionNumbers(t[0] + suf), t[1]); + } + } + }); + it("ignores files excluded by a legacy safe type list", () => { const file1 = { path: "/a/b/bliss.js", From 5d7e87a9c21df96a31925b3bafab2e0267ffe02a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 1 Nov 2017 11:52:52 -0700 Subject: [PATCH 08/73] Add "strictTuples" to list of strict flags --- src/compiler/core.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 23493b3087d..eed627079b9 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1684,7 +1684,7 @@ namespace ts { return moduleResolution; } - export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "alwaysStrict"; + export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "strictTuples" | "alwaysStrict"; export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean { return compilerOptions[flag] === undefined ? compilerOptions.strict : compilerOptions[flag]; From defd32f01580fb85a72593efd15089f98c444c71 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 1 Nov 2017 11:38:14 -0700 Subject: [PATCH 09/73] Move strict tuple test and add a couple of cases --- .../reference/strictTupleLength.errors.txt | 37 +++++++++++ .../{tupleLength.js => strictTupleLength.js} | 17 +++-- .../reference/strictTupleLength.symbols | 66 +++++++++++++++++++ ...leLength.types => strictTupleLength.types} | 23 ++++++- .../reference/tupleLength.errors.txt | 26 -------- tests/baselines/reference/tupleLength.symbols | 51 -------------- .../types/tuple/strictTupleLength.ts} | 7 +- 7 files changed, 139 insertions(+), 88 deletions(-) create mode 100644 tests/baselines/reference/strictTupleLength.errors.txt rename tests/baselines/reference/{tupleLength.js => strictTupleLength.js} (58%) create mode 100644 tests/baselines/reference/strictTupleLength.symbols rename tests/baselines/reference/{tupleLength.types => strictTupleLength.types} (61%) delete mode 100644 tests/baselines/reference/tupleLength.errors.txt delete mode 100644 tests/baselines/reference/tupleLength.symbols rename tests/cases/{compiler/tupleLength.ts => conformance/types/tuple/strictTupleLength.ts} (70%) diff --git a/tests/baselines/reference/strictTupleLength.errors.txt b/tests/baselines/reference/strictTupleLength.errors.txt new file mode 100644 index 00000000000..c31064f6b6b --- /dev/null +++ b/tests/baselines/reference/strictTupleLength.errors.txt @@ -0,0 +1,37 @@ +tests/cases/conformance/types/tuple/strictTupleLength.ts(1,9): error TS1122: A tuple type element list cannot be empty. +tests/cases/conformance/types/tuple/strictTupleLength.ts(11,5): error TS2403: Subsequent variable declarations must have the same type. Variable 't1' has type '[number]' at tests/cases/conformance/types/tuple/strictTupleLength.ts 1:4, but here has type '[number, number]'. +tests/cases/conformance/types/tuple/strictTupleLength.ts(12,5): error TS2403: Subsequent variable declarations must have the same type. Variable 't2' has type '[number, number]' at tests/cases/conformance/types/tuple/strictTupleLength.ts 2:4, but here has type '[number]'. +tests/cases/conformance/types/tuple/strictTupleLength.ts(18,1): error TS2322: Type 'number[]' is not assignable to type '[number]'. + Property '0' is missing in type 'number[]'. + + +==== tests/cases/conformance/types/tuple/strictTupleLength.ts (4 errors) ==== + var t0: []; + ~~ +!!! error TS1122: A tuple type element list cannot be empty. + 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' has type '[number]' at tests/cases/conformance/types/tuple/strictTupleLength.ts 1:4, but here has type '[number, number]'. + var t2 = t1; // error + ~~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 't2' has type '[number, number]' at tests/cases/conformance/types/tuple/strictTupleLength.ts 2:4, but here has type '[number]'. + + type A = T['length']; + var b: A<[boolean]>; + var c: 1 = b; + + t1 = arr; // error with or without strict + ~~ +!!! error TS2322: Type 'number[]' is not assignable to type '[number]'. +!!! error TS2322: Property '0' is missing in type 'number[]'. + arr = t1; // ok with or without strict + \ No newline at end of file diff --git a/tests/baselines/reference/tupleLength.js b/tests/baselines/reference/strictTupleLength.js similarity index 58% rename from tests/baselines/reference/tupleLength.js rename to tests/baselines/reference/strictTupleLength.js index 3893305421b..e4ae65f2fde 100644 --- a/tests/baselines/reference/tupleLength.js +++ b/tests/baselines/reference/strictTupleLength.js @@ -1,10 +1,10 @@ -//// [tupleLength.ts] -// var t0: []; +//// [strictTupleLength.ts] +var t0: []; var t1: [number]; var t2: [number, number]; var arr: number[]; -// var len0: 0 = t0.length; +var len0: 0 = t0.length; var len1: 1 = t1.length; var len2: 2 = t2.length; var lena: number = arr.length; @@ -15,14 +15,17 @@ var t2 = t1; // error type A = T['length']; var b: A<[boolean]>; var c: 1 = b; + +t1 = arr; // error with or without strict +arr = t1; // ok with or without strict -//// [tupleLength.js] -// var t0: []; +//// [strictTupleLength.js] +var t0; var t1; var t2; var arr; -// var len0: 0 = t0.length; +var len0 = t0.length; var len1 = t1.length; var len2 = t2.length; var lena = arr.length; @@ -30,3 +33,5 @@ var t1 = t2; // error var t2 = t1; // error var b; var c = b; +t1 = arr; // error with or without strict +arr = t1; // ok with or without strict diff --git a/tests/baselines/reference/strictTupleLength.symbols b/tests/baselines/reference/strictTupleLength.symbols new file mode 100644 index 00000000000..e81697b84bf --- /dev/null +++ b/tests/baselines/reference/strictTupleLength.symbols @@ -0,0 +1,66 @@ +=== tests/cases/conformance/types/tuple/strictTupleLength.ts === +var t0: []; +>t0 : Symbol(t0, Decl(strictTupleLength.ts, 0, 3)) + +var t1: [number]; +>t1 : Symbol(t1, Decl(strictTupleLength.ts, 1, 3), Decl(strictTupleLength.ts, 10, 3)) + +var t2: [number, number]; +>t2 : Symbol(t2, Decl(strictTupleLength.ts, 2, 3), Decl(strictTupleLength.ts, 11, 3)) + +var arr: number[]; +>arr : Symbol(arr, Decl(strictTupleLength.ts, 3, 3)) + +var len0: 0 = t0.length; +>len0 : Symbol(len0, Decl(strictTupleLength.ts, 5, 3)) +>t0.length : Symbol(length) +>t0 : Symbol(t0, Decl(strictTupleLength.ts, 0, 3)) +>length : Symbol(length) + +var len1: 1 = t1.length; +>len1 : Symbol(len1, Decl(strictTupleLength.ts, 6, 3)) +>t1.length : Symbol(length) +>t1 : Symbol(t1, Decl(strictTupleLength.ts, 1, 3), Decl(strictTupleLength.ts, 10, 3)) +>length : Symbol(length) + +var len2: 2 = t2.length; +>len2 : Symbol(len2, Decl(strictTupleLength.ts, 7, 3)) +>t2.length : Symbol(length) +>t2 : Symbol(t2, Decl(strictTupleLength.ts, 2, 3), Decl(strictTupleLength.ts, 11, 3)) +>length : Symbol(length) + +var lena: number = arr.length; +>lena : Symbol(lena, Decl(strictTupleLength.ts, 8, 3)) +>arr.length : Symbol(Array.length, Decl(lib.d.ts, --, --)) +>arr : Symbol(arr, Decl(strictTupleLength.ts, 3, 3)) +>length : Symbol(Array.length, Decl(lib.d.ts, --, --)) + +var t1 = t2; // error +>t1 : Symbol(t1, Decl(strictTupleLength.ts, 1, 3), Decl(strictTupleLength.ts, 10, 3)) +>t2 : Symbol(t2, Decl(strictTupleLength.ts, 2, 3), Decl(strictTupleLength.ts, 11, 3)) + +var t2 = t1; // error +>t2 : Symbol(t2, Decl(strictTupleLength.ts, 2, 3), Decl(strictTupleLength.ts, 11, 3)) +>t1 : Symbol(t1, Decl(strictTupleLength.ts, 1, 3), Decl(strictTupleLength.ts, 10, 3)) + +type A = T['length']; +>A : Symbol(A, Decl(strictTupleLength.ts, 11, 12)) +>T : Symbol(T, Decl(strictTupleLength.ts, 13, 7)) +>T : Symbol(T, Decl(strictTupleLength.ts, 13, 7)) + +var b: A<[boolean]>; +>b : Symbol(b, Decl(strictTupleLength.ts, 14, 3)) +>A : Symbol(A, Decl(strictTupleLength.ts, 11, 12)) + +var c: 1 = b; +>c : Symbol(c, Decl(strictTupleLength.ts, 15, 3)) +>b : Symbol(b, Decl(strictTupleLength.ts, 14, 3)) + +t1 = arr; // error with or without strict +>t1 : Symbol(t1, Decl(strictTupleLength.ts, 1, 3), Decl(strictTupleLength.ts, 10, 3)) +>arr : Symbol(arr, Decl(strictTupleLength.ts, 3, 3)) + +arr = t1; // ok with or without strict +>arr : Symbol(arr, Decl(strictTupleLength.ts, 3, 3)) +>t1 : Symbol(t1, Decl(strictTupleLength.ts, 1, 3), Decl(strictTupleLength.ts, 10, 3)) + diff --git a/tests/baselines/reference/tupleLength.types b/tests/baselines/reference/strictTupleLength.types similarity index 61% rename from tests/baselines/reference/tupleLength.types rename to tests/baselines/reference/strictTupleLength.types index ce1c88d2a70..917c2f7db23 100644 --- a/tests/baselines/reference/tupleLength.types +++ b/tests/baselines/reference/strictTupleLength.types @@ -1,5 +1,7 @@ -=== tests/cases/compiler/tupleLength.ts === -// var t0: []; +=== tests/cases/conformance/types/tuple/strictTupleLength.ts === +var t0: []; +>t0 : [] + var t1: [number]; >t1 : [number] @@ -9,7 +11,12 @@ var t2: [number, number]; var arr: number[]; >arr : number[] -// var len0: 0 = t0.length; +var len0: 0 = t0.length; +>len0 : 0 +>t0.length : 0 +>t0 : [] +>length : 0 + var len1: 1 = t1.length; >len1 : 1 >t1.length : 1 @@ -49,3 +56,13 @@ var c: 1 = b; >c : 1 >b : 1 +t1 = arr; // error with or without strict +>t1 = arr : number[] +>t1 : [number] +>arr : number[] + +arr = t1; // ok with or without strict +>arr = t1 : [number] +>arr : number[] +>t1 : [number] + diff --git a/tests/baselines/reference/tupleLength.errors.txt b/tests/baselines/reference/tupleLength.errors.txt deleted file mode 100644 index 9b4b7fa52bc..00000000000 --- a/tests/baselines/reference/tupleLength.errors.txt +++ /dev/null @@ -1,26 +0,0 @@ -tests/cases/compiler/tupleLength.ts(11,5): error TS2403: Subsequent variable declarations must have the same type. Variable 't1' has type '[number]' at tests/cases/compiler/tupleLength.ts 1:4, 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' has type '[number, number]' at tests/cases/compiler/tupleLength.ts 2:4, 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' has type '[number]' at tests/cases/compiler/tupleLength.ts 1:4, but here has type '[number, number]'. - var t2 = t1; // error - ~~ -!!! error TS2403: Subsequent variable declarations must have the same type. Variable 't2' has type '[number, number]' at tests/cases/compiler/tupleLength.ts 2:4, 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.symbols b/tests/baselines/reference/tupleLength.symbols deleted file mode 100644 index f488185306d..00000000000 --- a/tests/baselines/reference/tupleLength.symbols +++ /dev/null @@ -1,51 +0,0 @@ -=== tests/cases/compiler/tupleLength.ts === -// var t0: []; -var t1: [number]; ->t1 : Symbol(t1, Decl(tupleLength.ts, 1, 3), Decl(tupleLength.ts, 10, 3)) - -var t2: [number, number]; ->t2 : Symbol(t2, Decl(tupleLength.ts, 2, 3), Decl(tupleLength.ts, 11, 3)) - -var arr: number[]; ->arr : Symbol(arr, Decl(tupleLength.ts, 3, 3)) - -// var len0: 0 = t0.length; -var len1: 1 = t1.length; ->len1 : Symbol(len1, Decl(tupleLength.ts, 6, 3)) ->t1.length : Symbol(length) ->t1 : Symbol(t1, Decl(tupleLength.ts, 1, 3), Decl(tupleLength.ts, 10, 3)) ->length : Symbol(length) - -var len2: 2 = t2.length; ->len2 : Symbol(len2, Decl(tupleLength.ts, 7, 3)) ->t2.length : Symbol(length) ->t2 : Symbol(t2, Decl(tupleLength.ts, 2, 3), Decl(tupleLength.ts, 11, 3)) ->length : Symbol(length) - -var lena: number = arr.length; ->lena : Symbol(lena, Decl(tupleLength.ts, 8, 3)) ->arr.length : Symbol(Array.length, Decl(lib.d.ts, --, --)) ->arr : Symbol(arr, Decl(tupleLength.ts, 3, 3)) ->length : Symbol(Array.length, Decl(lib.d.ts, --, --)) - -var t1 = t2; // error ->t1 : Symbol(t1, Decl(tupleLength.ts, 1, 3), Decl(tupleLength.ts, 10, 3)) ->t2 : Symbol(t2, Decl(tupleLength.ts, 2, 3), Decl(tupleLength.ts, 11, 3)) - -var t2 = t1; // error ->t2 : Symbol(t2, Decl(tupleLength.ts, 2, 3), Decl(tupleLength.ts, 11, 3)) ->t1 : Symbol(t1, Decl(tupleLength.ts, 1, 3), Decl(tupleLength.ts, 10, 3)) - -type A = T['length']; ->A : Symbol(A, Decl(tupleLength.ts, 11, 12)) ->T : Symbol(T, Decl(tupleLength.ts, 13, 7)) ->T : Symbol(T, Decl(tupleLength.ts, 13, 7)) - -var b: A<[boolean]>; ->b : Symbol(b, Decl(tupleLength.ts, 14, 3)) ->A : Symbol(A, Decl(tupleLength.ts, 11, 12)) - -var c: 1 = b; ->c : Symbol(c, Decl(tupleLength.ts, 15, 3)) ->b : Symbol(b, Decl(tupleLength.ts, 14, 3)) - diff --git a/tests/cases/compiler/tupleLength.ts b/tests/cases/conformance/types/tuple/strictTupleLength.ts similarity index 70% rename from tests/cases/compiler/tupleLength.ts rename to tests/cases/conformance/types/tuple/strictTupleLength.ts index 3c6db1a034a..bfae662cd7c 100644 --- a/tests/cases/compiler/tupleLength.ts +++ b/tests/cases/conformance/types/tuple/strictTupleLength.ts @@ -1,11 +1,11 @@ // @strictTuples: true -// var t0: []; +var t0: []; var t1: [number]; var t2: [number, number]; var arr: number[]; -// var len0: 0 = t0.length; +var len0: 0 = t0.length; var len1: 1 = t1.length; var len2: 2 = t2.length; var lena: number = arr.length; @@ -16,3 +16,6 @@ var t2 = t1; // error type A = T['length']; var b: A<[boolean]>; var c: 1 = b; + +t1 = arr; // error with or without strict +arr = t1; // ok with or without strict From 8cfabcaeb4ecf26bec2543b445c9a394e089061d Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 2 Nov 2017 10:07:47 -0700 Subject: [PATCH 10/73] Remove strictTuple flag and Tuple.length readonly --- src/compiler/checker.ts | 10 +++------- src/compiler/commandLineParser.ts | 7 ------- src/compiler/core.ts | 2 +- src/compiler/diagnosticMessages.json | 4 ---- src/compiler/types.ts | 1 - 5 files changed, 4 insertions(+), 20 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 83220ed6c42..8bfd60e5659 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -67,7 +67,6 @@ namespace ts { const allowSyntheticDefaultImports = typeof compilerOptions.allowSyntheticDefaultImports !== "undefined" ? compilerOptions.allowSyntheticDefaultImports : modulekind === ModuleKind.System; const strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks"); const strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes"); - const strictTuples = getStrictOptionValue(compilerOptions, "strictTuples"); const noImplicitAny = getStrictOptionValue(compilerOptions, "noImplicitAny"); const noImplicitThis = getStrictOptionValue(compilerOptions, "noImplicitThis"); @@ -7303,12 +7302,9 @@ 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 lengthSymbol = createSymbol(SymbolFlags.Property, "length" as __String); + lengthSymbol.type = getLiteralType(arity); + 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 2b6f4c266a1..b7003fbffd9 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -276,13 +276,6 @@ namespace ts { category: Diagnostics.Strict_Type_Checking_Options, description: Diagnostics.Enable_strict_checking_of_function_types }, - { - 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/core.ts b/src/compiler/core.ts index eed627079b9..23493b3087d 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1684,7 +1684,7 @@ namespace ts { return moduleResolution; } - export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "strictTuples" | "alwaysStrict"; + export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "alwaysStrict"; export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean { return compilerOptions[flag] === undefined ? compilerOptions.strict : compilerOptions[flag]; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 252ed7f77e7..8f855347bd8 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3326,10 +3326,6 @@ "category": "Message", "code": 6186 }, - "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 95b87ab3853..549c0f8d52f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3785,7 +3785,6 @@ namespace ts { strict?: boolean; strictFunctionTypes?: boolean; // Always combine with strict property strictNullChecks?: boolean; // Always combine with strict property - strictTuples?: boolean; /* @internal */ stripInternal?: boolean; suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; From a980d61f86c4df8f90c11f4ae47000232b2f19a0 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 3 Nov 2017 09:56:39 -0700 Subject: [PATCH 11/73] Add a few tuple tests and update baselines --- .../reference/api/tsserverlibrary.d.ts | 1 - tests/baselines/reference/api/typescript.d.ts | 1 - .../arityAndOrderCompatibility01.errors.txt | 98 ++++++++-------- .../reference/arityAndOrderCompatibility01.js | 2 + .../arityAndOrderCompatibility01.symbols | 106 +++++++++--------- .../arityAndOrderCompatibility01.types | 18 +-- ...teralExpressionContextualTyping.errors.txt | 28 +++-- .../reference/arrayLiterals3.errors.txt | 12 +- .../reference/castingTuple.errors.txt | 34 +++++- tests/baselines/reference/castingTuple.js | 4 + .../baselines/reference/castingTuple.symbols | 52 +++++---- tests/baselines/reference/castingTuple.types | 10 ++ .../contextualTypeWithTuple.errors.txt | 33 +++--- ...cturingParameterDeclaration1ES5.errors.txt | 16 ++- ...estructuringParameterDeclaration1ES5.types | 8 +- ...arameterDeclaration1ES5iterable.errors.txt | 16 ++- ...ringParameterDeclaration1ES5iterable.types | 8 +- ...cturingParameterDeclaration1ES6.errors.txt | 16 ++- ...estructuringParameterDeclaration1ES6.types | 8 +- ...tructuringParameterDeclaration2.errors.txt | 12 +- ...cturingParameterDeclaration3ES5.errors.txt | 55 +++++++++ ...estructuringParameterDeclaration3ES5.types | 6 +- ...arameterDeclaration3ES5iterable.errors.txt | 55 +++++++++ ...ringParameterDeclaration3ES5iterable.types | 6 +- ...cturingParameterDeclaration3ES6.errors.txt | 55 +++++++++ ...estructuringParameterDeclaration3ES6.types | 6 +- .../genericCallWithTupleType.errors.txt | 12 +- .../reference/keyofAndIndexedAccess.types | 4 +- .../promiseEmptyTupleNoException.errors.txt | 10 +- .../tsconfig.json | 1 - .../tsconfig.json | 1 - .../tsconfig.json | 1 - .../tsconfig.json | 1 - .../tsconfig.json | 1 - .../tsconfig.json | 1 - .../tsconfig.json | 1 - .../tsconfig.json | 1 - .../baselines/reference/tupleTypes.errors.txt | 11 +- tests/baselines/reference/tupleTypes.js | 4 +- tests/baselines/reference/tupleTypes.symbols | 2 +- tests/baselines/reference/tupleTypes.types | 2 +- .../unionTypeFromArrayLiteral.errors.txt | 33 ++++++ .../reference/wideningTuples3.errors.txt | 11 +- .../reference/wideningTuples4.errors.txt | 14 +++ tests/cases/compiler/tupleTypes.ts | 2 +- .../tuple/arityAndOrderCompatibility01.ts | 2 + .../conformance/types/tuple/castingTuple.ts | 2 + .../types/tuple/strictTupleLength.ts | 2 - 48 files changed, 544 insertions(+), 241 deletions(-) create mode 100644 tests/baselines/reference/destructuringParameterDeclaration3ES5.errors.txt create mode 100644 tests/baselines/reference/destructuringParameterDeclaration3ES5iterable.errors.txt create mode 100644 tests/baselines/reference/destructuringParameterDeclaration3ES6.errors.txt create mode 100644 tests/baselines/reference/unionTypeFromArrayLiteral.errors.txt create mode 100644 tests/baselines/reference/wideningTuples4.errors.txt diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index f8593cc76e3..08e7ef8fe50 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2278,7 +2278,6 @@ declare namespace ts { strict?: boolean; strictFunctionTypes?: boolean; strictNullChecks?: boolean; - strictTuples?: boolean; suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; target?: ScriptTarget; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 15269f4d7af..666cc34162b 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2278,7 +2278,6 @@ declare namespace ts { strict?: boolean; strictFunctionTypes?: boolean; strictNullChecks?: boolean; - strictTuples?: boolean; suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; target?: ScriptTarget; diff --git a/tests/baselines/reference/arityAndOrderCompatibility01.errors.txt b/tests/baselines/reference/arityAndOrderCompatibility01.errors.txt index 5a367a4122f..4d6fbd063ae 100644 --- a/tests/baselines/reference/arityAndOrderCompatibility01.errors.txt +++ b/tests/baselines/reference/arityAndOrderCompatibility01.errors.txt @@ -1,52 +1,49 @@ -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(13,12): error TS2493: Tuple type '[string, number]' with length '2' cannot be assigned to tuple with length '3'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(14,12): error TS2460: Type 'StrNum' has no property '2'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(15,5): error TS2461: Type '{ 0: string; 1: number; }' is not an array type. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(15,12): error TS2460: Type '{ 0: string; 1: number; }' has no property '2'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(16,5): error TS2322: Type '[string, number]' is not assignable to type '[number, number, number]'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(15,12): error TS2493: Tuple type '[string, number]' with length '2' cannot be assigned to tuple with length '3'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(16,12): error TS2460: Type 'StrNum' has no property '2'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(17,5): error TS2461: Type '{ 0: string; 1: number; length: 2; }' is not an array type. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(17,12): error TS2460: Type '{ 0: string; 1: number; length: 2; }' has no property '2'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(18,5): error TS2322: Type '[string, number]' is not assignable to type '[number, number, number]'. Property '2' is missing in type '[string, number]'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(17,5): error TS2322: Type 'StrNum' is not assignable to type '[number, number, number]'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(19,5): error TS2322: Type 'StrNum' is not assignable to type '[number, number, number]'. Property '2' is missing in type 'StrNum'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(18,5): error TS2322: Type '{ 0: string; 1: number; }' is not assignable to type '[number, number, number]'. - Property '2' is missing in type '{ 0: string; 1: number; }'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(19,5): error TS2322: Type '[string, number]' is not assignable to type '[string, number, number]'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(20,5): error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[number, number, number]'. + Property '2' is missing in type '{ 0: string; 1: number; length: 2; }'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(21,5): error TS2322: Type '[string, number]' is not assignable to type '[string, number, number]'. Property '2' is missing in type '[string, number]'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(20,5): error TS2322: Type 'StrNum' is not assignable to type '[string, number, number]'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(22,5): error TS2322: Type 'StrNum' is not assignable to type '[string, number, number]'. Property '2' is missing in type 'StrNum'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(21,5): error TS2322: Type '{ 0: string; 1: number; }' is not assignable to type '[string, number, number]'. - Property '2' is missing in type '{ 0: string; 1: number; }'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(22,5): error TS2322: Type '[string, number]' is not assignable to type '[number]'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(23,5): error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[string, number, number]'. + Property '2' is missing in type '{ 0: string; 1: number; length: 2; }'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(24,5): error TS2322: Type '[string, number]' is not assignable to type '[number]'. Types of property '0' are incompatible. Type 'string' is not assignable to type 'number'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(23,5): error TS2322: Type 'StrNum' is not assignable to type '[number]'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(25,5): error TS2322: Type 'StrNum' is not assignable to type '[number]'. Types of property '0' are incompatible. Type 'string' is not assignable to type 'number'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(24,5): error TS2322: Type '{ 0: string; 1: number; }' is not assignable to type '[number]'. - Property 'length' is missing in type '{ 0: string; 1: number; }'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(25,5): error TS2322: Type '[string, number]' is not assignable to type '[string]'. - Types of property 'pop' are incompatible. - Type '() => string | number' is not assignable to type '() => string'. - Type 'string | number' is not assignable to type 'string'. - Type 'number' is not assignable to type 'string'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(26,5): error TS2322: Type 'StrNum' is not assignable to type '[string]'. - Types of property 'pop' are incompatible. - Type '() => string | number' is not assignable to type '() => string'. - Type 'string | number' is not assignable to type 'string'. - Type 'number' is not assignable to type 'string'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(27,5): error TS2322: Type '{ 0: string; 1: number; }' is not assignable to type '[string]'. - Property 'length' is missing in type '{ 0: string; 1: number; }'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(28,5): error TS2322: Type '[string, number]' is not assignable to type '[number, string]'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(26,5): error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[number]'. + Property 'push' is missing in type '{ 0: string; 1: number; length: 2; }'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(27,5): error TS2322: Type '[string, number]' is not assignable to type '[string]'. + Types of property 'length' are incompatible. + Type '2' is not assignable to type '1'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(28,5): error TS2322: Type 'StrNum' is not assignable to type '[string]'. + Types of property 'length' are incompatible. + Type '2' is not assignable to type '1'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(29,5): error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[string]'. + Property 'push' is missing in type '{ 0: string; 1: number; length: 2; }'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(30,5): error TS2322: Type '[string, number]' is not assignable to type '[number, string]'. Type 'string' is not assignable to type 'number'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(29,5): error TS2322: Type 'StrNum' is not assignable to type '[number, string]'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(31,5): error TS2322: Type 'StrNum' is not assignable to type '[number, string]'. Types of property '0' are incompatible. Type 'string' is not assignable to type 'number'. -tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(30,5): error TS2322: Type '{ 0: string; 1: number; }' is not assignable to type '[number, string]'. - Property 'length' is missing in type '{ 0: string; 1: number; }'. +tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(32,5): error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[number, string]'. + Property 'push' is missing in type '{ 0: string; 1: number; length: 2; }'. ==== tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts (19 errors) ==== interface StrNum extends Array { 0: string; 1: number; + length: 2; } var x: [string, number]; @@ -54,6 +51,7 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(30,5): error var z: { 0: string; 1: number; + length: 2; } var [a, b, c] = x; @@ -64,9 +62,9 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(30,5): error !!! error TS2460: Type 'StrNum' has no property '2'. var [g, h, i] = z; ~~~~~~~~~ -!!! error TS2461: Type '{ 0: string; 1: number; }' is not an array type. +!!! error TS2461: Type '{ 0: string; 1: number; length: 2; }' is not an array type. ~ -!!! error TS2460: Type '{ 0: string; 1: number; }' has no property '2'. +!!! error TS2460: Type '{ 0: string; 1: number; length: 2; }' has no property '2'. var j1: [number, number, number] = x; ~~ !!! error TS2322: Type '[string, number]' is not assignable to type '[number, number, number]'. @@ -77,8 +75,8 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(30,5): error !!! error TS2322: Property '2' is missing in type 'StrNum'. var j3: [number, number, number] = z; ~~ -!!! error TS2322: Type '{ 0: string; 1: number; }' is not assignable to type '[number, number, number]'. -!!! error TS2322: Property '2' is missing in type '{ 0: string; 1: number; }'. +!!! error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[number, number, number]'. +!!! error TS2322: Property '2' is missing in type '{ 0: string; 1: number; length: 2; }'. var k1: [string, number, number] = x; ~~ !!! error TS2322: Type '[string, number]' is not assignable to type '[string, number, number]'. @@ -89,8 +87,8 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(30,5): error !!! error TS2322: Property '2' is missing in type 'StrNum'. var k3: [string, number, number] = z; ~~ -!!! error TS2322: Type '{ 0: string; 1: number; }' is not assignable to type '[string, number, number]'. -!!! error TS2322: Property '2' is missing in type '{ 0: string; 1: number; }'. +!!! error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[string, number, number]'. +!!! error TS2322: Property '2' is missing in type '{ 0: string; 1: number; length: 2; }'. var l1: [number] = x; ~~ !!! error TS2322: Type '[string, number]' is not assignable to type '[number]'. @@ -103,26 +101,22 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(30,5): error !!! error TS2322: Type 'string' is not assignable to type 'number'. var l3: [number] = z; ~~ -!!! error TS2322: Type '{ 0: string; 1: number; }' is not assignable to type '[number]'. -!!! error TS2322: Property 'length' is missing in type '{ 0: string; 1: number; }'. +!!! error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[number]'. +!!! error TS2322: Property 'push' is missing in type '{ 0: string; 1: number; length: 2; }'. var m1: [string] = x; ~~ !!! error TS2322: Type '[string, number]' is not assignable to type '[string]'. -!!! error TS2322: Types of property 'pop' are incompatible. -!!! error TS2322: Type '() => string | number' is not assignable to type '() => string'. -!!! error TS2322: Type 'string | number' is not assignable to type 'string'. -!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! error TS2322: Types of property 'length' are incompatible. +!!! error TS2322: Type '2' is not assignable to type '1'. var m2: [string] = y; ~~ !!! error TS2322: Type 'StrNum' is not assignable to type '[string]'. -!!! error TS2322: Types of property 'pop' are incompatible. -!!! error TS2322: Type '() => string | number' is not assignable to type '() => string'. -!!! error TS2322: Type 'string | number' is not assignable to type 'string'. -!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! error TS2322: Types of property 'length' are incompatible. +!!! error TS2322: Type '2' is not assignable to type '1'. var m3: [string] = z; ~~ -!!! error TS2322: Type '{ 0: string; 1: number; }' is not assignable to type '[string]'. -!!! error TS2322: Property 'length' is missing in type '{ 0: string; 1: number; }'. +!!! error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[string]'. +!!! error TS2322: Property 'push' is missing in type '{ 0: string; 1: number; length: 2; }'. var n1: [number, string] = x; ~~ !!! error TS2322: Type '[string, number]' is not assignable to type '[number, string]'. @@ -134,8 +128,8 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(30,5): error !!! error TS2322: Type 'string' is not assignable to type 'number'. var n3: [number, string] = z; ~~ -!!! error TS2322: Type '{ 0: string; 1: number; }' is not assignable to type '[number, string]'. -!!! error TS2322: Property 'length' is missing in type '{ 0: string; 1: number; }'. +!!! error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[number, string]'. +!!! error TS2322: Property 'push' is missing in type '{ 0: string; 1: number; length: 2; }'. var o1: [string, number] = x; var o2: [string, number] = y; var o3: [string, number] = y; diff --git a/tests/baselines/reference/arityAndOrderCompatibility01.js b/tests/baselines/reference/arityAndOrderCompatibility01.js index 2eb1bcf8bd8..bf7736a80c9 100644 --- a/tests/baselines/reference/arityAndOrderCompatibility01.js +++ b/tests/baselines/reference/arityAndOrderCompatibility01.js @@ -2,6 +2,7 @@ interface StrNum extends Array { 0: string; 1: number; + length: 2; } var x: [string, number]; @@ -9,6 +10,7 @@ var y: StrNum var z: { 0: string; 1: number; + length: 2; } var [a, b, c] = x; diff --git a/tests/baselines/reference/arityAndOrderCompatibility01.symbols b/tests/baselines/reference/arityAndOrderCompatibility01.symbols index c6ef08a845b..3a5d55dc1e6 100644 --- a/tests/baselines/reference/arityAndOrderCompatibility01.symbols +++ b/tests/baselines/reference/arityAndOrderCompatibility01.symbols @@ -5,109 +5,113 @@ interface StrNum extends Array { 0: string; 1: number; + length: 2; +>length : Symbol(StrNum.length, Decl(arityAndOrderCompatibility01.ts, 2, 14)) } var x: [string, number]; ->x : Symbol(x, Decl(arityAndOrderCompatibility01.ts, 5, 3)) +>x : Symbol(x, Decl(arityAndOrderCompatibility01.ts, 6, 3)) var y: StrNum ->y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 6, 3)) +>y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 7, 3)) >StrNum : Symbol(StrNum, Decl(arityAndOrderCompatibility01.ts, 0, 0)) var z: { ->z : Symbol(z, Decl(arityAndOrderCompatibility01.ts, 7, 3)) +>z : Symbol(z, Decl(arityAndOrderCompatibility01.ts, 8, 3)) 0: string; 1: number; + length: 2; +>length : Symbol(length, Decl(arityAndOrderCompatibility01.ts, 10, 14)) } var [a, b, c] = x; ->a : Symbol(a, Decl(arityAndOrderCompatibility01.ts, 12, 5)) ->b : Symbol(b, Decl(arityAndOrderCompatibility01.ts, 12, 7)) ->c : Symbol(c, Decl(arityAndOrderCompatibility01.ts, 12, 10)) ->x : Symbol(x, Decl(arityAndOrderCompatibility01.ts, 5, 3)) +>a : Symbol(a, Decl(arityAndOrderCompatibility01.ts, 14, 5)) +>b : Symbol(b, Decl(arityAndOrderCompatibility01.ts, 14, 7)) +>c : Symbol(c, Decl(arityAndOrderCompatibility01.ts, 14, 10)) +>x : Symbol(x, Decl(arityAndOrderCompatibility01.ts, 6, 3)) var [d, e, f] = y; ->d : Symbol(d, Decl(arityAndOrderCompatibility01.ts, 13, 5)) ->e : Symbol(e, Decl(arityAndOrderCompatibility01.ts, 13, 7)) ->f : Symbol(f, Decl(arityAndOrderCompatibility01.ts, 13, 10)) ->y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 6, 3)) +>d : Symbol(d, Decl(arityAndOrderCompatibility01.ts, 15, 5)) +>e : Symbol(e, Decl(arityAndOrderCompatibility01.ts, 15, 7)) +>f : Symbol(f, Decl(arityAndOrderCompatibility01.ts, 15, 10)) +>y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 7, 3)) var [g, h, i] = z; ->g : Symbol(g, Decl(arityAndOrderCompatibility01.ts, 14, 5)) ->h : Symbol(h, Decl(arityAndOrderCompatibility01.ts, 14, 7)) ->i : Symbol(i, Decl(arityAndOrderCompatibility01.ts, 14, 10)) ->z : Symbol(z, Decl(arityAndOrderCompatibility01.ts, 7, 3)) +>g : Symbol(g, Decl(arityAndOrderCompatibility01.ts, 16, 5)) +>h : Symbol(h, Decl(arityAndOrderCompatibility01.ts, 16, 7)) +>i : Symbol(i, Decl(arityAndOrderCompatibility01.ts, 16, 10)) +>z : Symbol(z, Decl(arityAndOrderCompatibility01.ts, 8, 3)) var j1: [number, number, number] = x; ->j1 : Symbol(j1, Decl(arityAndOrderCompatibility01.ts, 15, 3)) ->x : Symbol(x, Decl(arityAndOrderCompatibility01.ts, 5, 3)) +>j1 : Symbol(j1, Decl(arityAndOrderCompatibility01.ts, 17, 3)) +>x : Symbol(x, Decl(arityAndOrderCompatibility01.ts, 6, 3)) var j2: [number, number, number] = y; ->j2 : Symbol(j2, Decl(arityAndOrderCompatibility01.ts, 16, 3)) ->y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 6, 3)) +>j2 : Symbol(j2, Decl(arityAndOrderCompatibility01.ts, 18, 3)) +>y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 7, 3)) var j3: [number, number, number] = z; ->j3 : Symbol(j3, Decl(arityAndOrderCompatibility01.ts, 17, 3)) ->z : Symbol(z, Decl(arityAndOrderCompatibility01.ts, 7, 3)) +>j3 : Symbol(j3, Decl(arityAndOrderCompatibility01.ts, 19, 3)) +>z : Symbol(z, Decl(arityAndOrderCompatibility01.ts, 8, 3)) var k1: [string, number, number] = x; ->k1 : Symbol(k1, Decl(arityAndOrderCompatibility01.ts, 18, 3)) ->x : Symbol(x, Decl(arityAndOrderCompatibility01.ts, 5, 3)) +>k1 : Symbol(k1, Decl(arityAndOrderCompatibility01.ts, 20, 3)) +>x : Symbol(x, Decl(arityAndOrderCompatibility01.ts, 6, 3)) var k2: [string, number, number] = y; ->k2 : Symbol(k2, Decl(arityAndOrderCompatibility01.ts, 19, 3)) ->y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 6, 3)) +>k2 : Symbol(k2, Decl(arityAndOrderCompatibility01.ts, 21, 3)) +>y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 7, 3)) var k3: [string, number, number] = z; ->k3 : Symbol(k3, Decl(arityAndOrderCompatibility01.ts, 20, 3)) ->z : Symbol(z, Decl(arityAndOrderCompatibility01.ts, 7, 3)) +>k3 : Symbol(k3, Decl(arityAndOrderCompatibility01.ts, 22, 3)) +>z : Symbol(z, Decl(arityAndOrderCompatibility01.ts, 8, 3)) var l1: [number] = x; ->l1 : Symbol(l1, Decl(arityAndOrderCompatibility01.ts, 21, 3)) ->x : Symbol(x, Decl(arityAndOrderCompatibility01.ts, 5, 3)) +>l1 : Symbol(l1, Decl(arityAndOrderCompatibility01.ts, 23, 3)) +>x : Symbol(x, Decl(arityAndOrderCompatibility01.ts, 6, 3)) var l2: [number] = y; ->l2 : Symbol(l2, Decl(arityAndOrderCompatibility01.ts, 22, 3)) ->y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 6, 3)) +>l2 : Symbol(l2, Decl(arityAndOrderCompatibility01.ts, 24, 3)) +>y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 7, 3)) var l3: [number] = z; ->l3 : Symbol(l3, Decl(arityAndOrderCompatibility01.ts, 23, 3)) ->z : Symbol(z, Decl(arityAndOrderCompatibility01.ts, 7, 3)) +>l3 : Symbol(l3, Decl(arityAndOrderCompatibility01.ts, 25, 3)) +>z : Symbol(z, Decl(arityAndOrderCompatibility01.ts, 8, 3)) var m1: [string] = x; ->m1 : Symbol(m1, Decl(arityAndOrderCompatibility01.ts, 24, 3)) ->x : Symbol(x, Decl(arityAndOrderCompatibility01.ts, 5, 3)) +>m1 : Symbol(m1, Decl(arityAndOrderCompatibility01.ts, 26, 3)) +>x : Symbol(x, Decl(arityAndOrderCompatibility01.ts, 6, 3)) var m2: [string] = y; ->m2 : Symbol(m2, Decl(arityAndOrderCompatibility01.ts, 25, 3)) ->y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 6, 3)) +>m2 : Symbol(m2, Decl(arityAndOrderCompatibility01.ts, 27, 3)) +>y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 7, 3)) var m3: [string] = z; ->m3 : Symbol(m3, Decl(arityAndOrderCompatibility01.ts, 26, 3)) ->z : Symbol(z, Decl(arityAndOrderCompatibility01.ts, 7, 3)) +>m3 : Symbol(m3, Decl(arityAndOrderCompatibility01.ts, 28, 3)) +>z : Symbol(z, Decl(arityAndOrderCompatibility01.ts, 8, 3)) var n1: [number, string] = x; ->n1 : Symbol(n1, Decl(arityAndOrderCompatibility01.ts, 27, 3)) ->x : Symbol(x, Decl(arityAndOrderCompatibility01.ts, 5, 3)) +>n1 : Symbol(n1, Decl(arityAndOrderCompatibility01.ts, 29, 3)) +>x : Symbol(x, Decl(arityAndOrderCompatibility01.ts, 6, 3)) var n2: [number, string] = y; ->n2 : Symbol(n2, Decl(arityAndOrderCompatibility01.ts, 28, 3)) ->y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 6, 3)) +>n2 : Symbol(n2, Decl(arityAndOrderCompatibility01.ts, 30, 3)) +>y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 7, 3)) var n3: [number, string] = z; ->n3 : Symbol(n3, Decl(arityAndOrderCompatibility01.ts, 29, 3)) ->z : Symbol(z, Decl(arityAndOrderCompatibility01.ts, 7, 3)) +>n3 : Symbol(n3, Decl(arityAndOrderCompatibility01.ts, 31, 3)) +>z : Symbol(z, Decl(arityAndOrderCompatibility01.ts, 8, 3)) var o1: [string, number] = x; ->o1 : Symbol(o1, Decl(arityAndOrderCompatibility01.ts, 30, 3)) ->x : Symbol(x, Decl(arityAndOrderCompatibility01.ts, 5, 3)) +>o1 : Symbol(o1, Decl(arityAndOrderCompatibility01.ts, 32, 3)) +>x : Symbol(x, Decl(arityAndOrderCompatibility01.ts, 6, 3)) var o2: [string, number] = y; ->o2 : Symbol(o2, Decl(arityAndOrderCompatibility01.ts, 31, 3)) ->y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 6, 3)) +>o2 : Symbol(o2, Decl(arityAndOrderCompatibility01.ts, 33, 3)) +>y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 7, 3)) var o3: [string, number] = y; ->o3 : Symbol(o3, Decl(arityAndOrderCompatibility01.ts, 32, 3)) ->y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 6, 3)) +>o3 : Symbol(o3, Decl(arityAndOrderCompatibility01.ts, 34, 3)) +>y : Symbol(y, Decl(arityAndOrderCompatibility01.ts, 7, 3)) diff --git a/tests/baselines/reference/arityAndOrderCompatibility01.types b/tests/baselines/reference/arityAndOrderCompatibility01.types index 934c5c6966d..80e91fbd2e7 100644 --- a/tests/baselines/reference/arityAndOrderCompatibility01.types +++ b/tests/baselines/reference/arityAndOrderCompatibility01.types @@ -5,6 +5,8 @@ interface StrNum extends Array { 0: string; 1: number; + length: 2; +>length : 2 } var x: [string, number]; @@ -15,10 +17,12 @@ var y: StrNum >StrNum : StrNum var z: { ->z : { 0: string; 1: number; } +>z : { 0: string; 1: number; length: 2; } 0: string; 1: number; + length: 2; +>length : 2 } var [a, b, c] = x; @@ -37,7 +41,7 @@ var [g, h, i] = z; >g : string >h : number >i : any ->z : { 0: string; 1: number; } +>z : { 0: string; 1: number; length: 2; } var j1: [number, number, number] = x; >j1 : [number, number, number] @@ -49,7 +53,7 @@ var j2: [number, number, number] = y; var j3: [number, number, number] = z; >j3 : [number, number, number] ->z : { 0: string; 1: number; } +>z : { 0: string; 1: number; length: 2; } var k1: [string, number, number] = x; >k1 : [string, number, number] @@ -61,7 +65,7 @@ var k2: [string, number, number] = y; var k3: [string, number, number] = z; >k3 : [string, number, number] ->z : { 0: string; 1: number; } +>z : { 0: string; 1: number; length: 2; } var l1: [number] = x; >l1 : [number] @@ -73,7 +77,7 @@ var l2: [number] = y; var l3: [number] = z; >l3 : [number] ->z : { 0: string; 1: number; } +>z : { 0: string; 1: number; length: 2; } var m1: [string] = x; >m1 : [string] @@ -85,7 +89,7 @@ var m2: [string] = y; var m3: [string] = z; >m3 : [string] ->z : { 0: string; 1: number; } +>z : { 0: string; 1: number; length: 2; } var n1: [number, string] = x; >n1 : [number, string] @@ -97,7 +101,7 @@ var n2: [number, string] = y; var n3: [number, string] = z; >n3 : [number, string] ->z : { 0: string; 1: number; } +>z : { 0: string; 1: number; length: 2; } var o1: [string, number] = x; >o1 : [string, number] diff --git a/tests/baselines/reference/arrayLiteralExpressionContextualTyping.errors.txt b/tests/baselines/reference/arrayLiteralExpressionContextualTyping.errors.txt index 3e9777aea7c..8cb36b113a7 100644 --- a/tests/baselines/reference/arrayLiteralExpressionContextualTyping.errors.txt +++ b/tests/baselines/reference/arrayLiteralExpressionContextualTyping.errors.txt @@ -1,27 +1,37 @@ +tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionContextualTyping.ts(6,5): error TS2322: Type '[number, number, number, number]' is not assignable to type '[number, number, number]'. + Types of property 'length' are incompatible. + Type '4' is not assignable to type '3'. +tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionContextualTyping.ts(7,5): error TS2322: Type '[number, number, number, string]' is not assignable to type '[string | number, string | number, string | number]'. + Types of property 'length' are incompatible. + Type '4' is not assignable to type '3'. tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionContextualTyping.ts(8,5): error TS2322: Type '[number, number, number, string]' is not assignable to type '[number, number, number]'. - Types of property 'pop' are incompatible. - Type '() => string | number' is not assignable to type '() => number'. - Type 'string | number' is not assignable to type 'number'. - Type 'string' is not assignable to type 'number'. + Types of property 'length' are incompatible. + Type '4' is not assignable to type '3'. tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionContextualTyping.ts(14,5): error TS2322: Type 'number[]' is not assignable to type '[number, number, number]'. Property '0' is missing in type 'number[]'. -==== tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionContextualTyping.ts (2 errors) ==== +==== tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionContextualTyping.ts (4 errors) ==== // In a contextually typed array literal expression containing no spread elements, an element expression at index N is contextually typed by // the type of the property with the numeric name N in the contextual type, if any, or otherwise // the numeric index type of the contextual type, if any. var array = [1, 2, 3]; var array1 = [true, 2, 3]; // Contextual type by the numeric index type of the contextual type var tup: [number, number, number] = [1, 2, 3, 4]; + ~~~ +!!! error TS2322: Type '[number, number, number, number]' is not assignable to type '[number, number, number]'. +!!! error TS2322: Types of property 'length' are incompatible. +!!! error TS2322: Type '4' is not assignable to type '3'. var tup1: [number|string, number|string, number|string] = [1, 2, 3, "string"]; + ~~~~ +!!! error TS2322: Type '[number, number, number, string]' is not assignable to type '[string | number, string | number, string | number]'. +!!! error TS2322: Types of property 'length' are incompatible. +!!! error TS2322: Type '4' is not assignable to type '3'. var tup2: [number, number, number] = [1, 2, 3, "string"]; // Error ~~~~ !!! error TS2322: Type '[number, number, number, string]' is not assignable to type '[number, number, number]'. -!!! error TS2322: Types of property 'pop' are incompatible. -!!! error TS2322: Type '() => string | number' is not assignable to type '() => number'. -!!! error TS2322: Type 'string | number' is not assignable to type 'number'. -!!! error TS2322: Type 'string' is not assignable to type 'number'. +!!! error TS2322: Types of property 'length' are incompatible. +!!! error TS2322: Type '4' is not assignable to type '3'. // In a contextually typed array literal expression containing one or more spread elements, // an element expression at index N is contextually typed by the numeric index type of the contextual type, if any. diff --git a/tests/baselines/reference/arrayLiterals3.errors.txt b/tests/baselines/reference/arrayLiterals3.errors.txt index 3ebf4174f51..8c36d7d59c1 100644 --- a/tests/baselines/reference/arrayLiterals3.errors.txt +++ b/tests/baselines/reference/arrayLiterals3.errors.txt @@ -3,10 +3,8 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(10,5): error tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(11,5): error TS2322: Type '["string", number, boolean]' is not assignable to type '[boolean, string, number]'. Type '"string"' is not assignable to type 'boolean'. tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(17,5): error TS2322: Type '[number, number, string, boolean]' is not assignable to type '[number, number]'. - Types of property 'pop' are incompatible. - Type '() => string | number | boolean' is not assignable to type '() => number'. - Type 'string | number | boolean' is not assignable to type 'number'. - Type 'string' is not assignable to type 'number'. + Types of property 'length' are incompatible. + Type '4' is not assignable to type '2'. tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(32,5): error TS2322: Type '(number[] | string[])[]' is not assignable to type 'tup'. Property '0' is missing in type '(number[] | string[])[]'. tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(33,5): error TS2322: Type 'number[]' is not assignable to type '[number, number, number]'. @@ -46,10 +44,8 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(34,5): error var [b1, b2]: [number, number] = [1, 2, "string", true]; ~~~~~~~~ !!! error TS2322: Type '[number, number, string, boolean]' is not assignable to type '[number, number]'. -!!! error TS2322: Types of property 'pop' are incompatible. -!!! error TS2322: Type '() => string | number | boolean' is not assignable to type '() => number'. -!!! error TS2322: Type 'string | number | boolean' is not assignable to type 'number'. -!!! error TS2322: Type 'string' is not assignable to type 'number'. +!!! error TS2322: Types of property 'length' are incompatible. +!!! error TS2322: Type '4' is not assignable to type '2'. // The resulting type an array literal expression is determined as follows: // - the resulting type is an array type with an element type that is the union of the types of the diff --git a/tests/baselines/reference/castingTuple.errors.txt b/tests/baselines/reference/castingTuple.errors.txt index eb6aac5f463..a17f8c2b082 100644 --- a/tests/baselines/reference/castingTuple.errors.txt +++ b/tests/baselines/reference/castingTuple.errors.txt @@ -1,13 +1,21 @@ -tests/cases/conformance/types/tuple/castingTuple.ts(28,10): error TS2352: Type '[number, string]' cannot be converted to type '[number, number]'. +tests/cases/conformance/types/tuple/castingTuple.ts(13,23): error TS2352: Type '[number, string]' cannot be converted to type '[number, string, boolean]'. + Property '2' is missing in type '[number, string]'. +tests/cases/conformance/types/tuple/castingTuple.ts(14,15): error TS2352: Type '[number, string, boolean]' cannot be converted to type '[number, string]'. + Types of property 'length' are incompatible. + Type '3' is not comparable to type '2'. +tests/cases/conformance/types/tuple/castingTuple.ts(15,14): error TS2352: Type '[number, string]' cannot be converted to type '[number, string, boolean]'. +tests/cases/conformance/types/tuple/castingTuple.ts(18,21): error TS2352: Type '[C, D]' cannot be converted to type '[C, D, A]'. + Property '2' is missing in type '[C, D]'. +tests/cases/conformance/types/tuple/castingTuple.ts(30,10): error TS2352: Type '[number, string]' cannot be converted to type '[number, number]'. Type 'string' is not comparable to type 'number'. -tests/cases/conformance/types/tuple/castingTuple.ts(29,10): error TS2352: Type '[C, D]' cannot be converted to type '[A, I]'. +tests/cases/conformance/types/tuple/castingTuple.ts(31,10): error TS2352: Type '[C, D]' cannot be converted to type '[A, I]'. Type 'C' is not comparable to type 'A'. Property 'a' is missing in type 'C'. -tests/cases/conformance/types/tuple/castingTuple.ts(30,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' has type '{}[]' at tests/cases/conformance/types/tuple/castingTuple.ts 20:4, but here has type 'number[]'. -tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot find name 't4'. +tests/cases/conformance/types/tuple/castingTuple.ts(32,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' has type '{}[]' at tests/cases/conformance/types/tuple/castingTuple.ts 22:4, but here has type 'number[]'. +tests/cases/conformance/types/tuple/castingTuple.ts(33,1): error TS2304: Cannot find name 't4'. -==== tests/cases/conformance/types/tuple/castingTuple.ts (4 errors) ==== +==== tests/cases/conformance/types/tuple/castingTuple.ts (8 errors) ==== interface I { } class A { a = 10; } class C implements I { c }; @@ -21,9 +29,23 @@ tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot var numStrTuple: [number, string] = [5, "foo"]; var emptyObjTuple = <[{}, {}]>numStrTuple; var numStrBoolTuple = <[number, string, boolean]>numStrTuple; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2352: Type '[number, string]' cannot be converted to type '[number, string, boolean]'. +!!! error TS2352: Property '2' is missing in type '[number, string]'. + var shorter = numStrBoolTuple as [number, string] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2352: Type '[number, string, boolean]' cannot be converted to type '[number, string]'. +!!! error TS2352: Types of property 'length' are incompatible. +!!! error TS2352: Type '3' is not comparable to type '2'. + var longer = numStrTuple as [number, string, boolean] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2352: Type '[number, string]' cannot be converted to type '[number, string, boolean]'. var classCDTuple: [C, D] = [new C(), new D()]; var interfaceIITuple = <[I, I]>classCDTuple; var classCDATuple = <[C, D, A]>classCDTuple; + ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2352: Type '[C, D]' cannot be converted to type '[C, D, A]'. +!!! error TS2352: Property '2' is missing in type '[C, D]'. var eleFromCDA1 = classCDATuple[2]; // A var eleFromCDA2 = classCDATuple[5]; // C | D | A var t10: [E1, E2] = [E1.one, E2.one]; @@ -46,7 +68,7 @@ tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot !!! error TS2352: Property 'a' is missing in type 'C'. var array1 = numStrTuple; ~~~~~~ -!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' has type '{}[]' at tests/cases/conformance/types/tuple/castingTuple.ts 20:4, but here has type 'number[]'. +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' has type '{}[]' at tests/cases/conformance/types/tuple/castingTuple.ts 22:4, but here has type 'number[]'. t4[2] = 10; ~~ !!! error TS2304: Cannot find name 't4'. diff --git a/tests/baselines/reference/castingTuple.js b/tests/baselines/reference/castingTuple.js index 3744d40d8a5..a94246a19b8 100644 --- a/tests/baselines/reference/castingTuple.js +++ b/tests/baselines/reference/castingTuple.js @@ -12,6 +12,8 @@ enum E2 { one } var numStrTuple: [number, string] = [5, "foo"]; var emptyObjTuple = <[{}, {}]>numStrTuple; var numStrBoolTuple = <[number, string, boolean]>numStrTuple; +var shorter = numStrBoolTuple as [number, string] +var longer = numStrTuple as [number, string, boolean] var classCDTuple: [C, D] = [new C(), new D()]; var interfaceIITuple = <[I, I]>classCDTuple; var classCDATuple = <[C, D, A]>classCDTuple; @@ -89,6 +91,8 @@ var E2; var numStrTuple = [5, "foo"]; var emptyObjTuple = numStrTuple; var numStrBoolTuple = numStrTuple; +var shorter = numStrBoolTuple; +var longer = numStrTuple; var classCDTuple = [new C(), new D()]; var interfaceIITuple = classCDTuple; var classCDATuple = classCDTuple; diff --git a/tests/baselines/reference/castingTuple.symbols b/tests/baselines/reference/castingTuple.symbols index 61edfb4b376..3cf5face2a6 100644 --- a/tests/baselines/reference/castingTuple.symbols +++ b/tests/baselines/reference/castingTuple.symbols @@ -46,37 +46,45 @@ var numStrBoolTuple = <[number, string, boolean]>numStrTuple; >numStrBoolTuple : Symbol(numStrBoolTuple, Decl(castingTuple.ts, 12, 3)) >numStrTuple : Symbol(numStrTuple, Decl(castingTuple.ts, 10, 3)) +var shorter = numStrBoolTuple as [number, string] +>shorter : Symbol(shorter, Decl(castingTuple.ts, 13, 3)) +>numStrBoolTuple : Symbol(numStrBoolTuple, Decl(castingTuple.ts, 12, 3)) + +var longer = numStrTuple as [number, string, boolean] +>longer : Symbol(longer, Decl(castingTuple.ts, 14, 3)) +>numStrTuple : Symbol(numStrTuple, Decl(castingTuple.ts, 10, 3)) + var classCDTuple: [C, D] = [new C(), new D()]; ->classCDTuple : Symbol(classCDTuple, Decl(castingTuple.ts, 13, 3)) +>classCDTuple : Symbol(classCDTuple, Decl(castingTuple.ts, 15, 3)) >C : Symbol(C, Decl(castingTuple.ts, 1, 19)) >D : Symbol(D, Decl(castingTuple.ts, 2, 27)) >C : Symbol(C, Decl(castingTuple.ts, 1, 19)) >D : Symbol(D, Decl(castingTuple.ts, 2, 27)) var interfaceIITuple = <[I, I]>classCDTuple; ->interfaceIITuple : Symbol(interfaceIITuple, Decl(castingTuple.ts, 14, 3)) +>interfaceIITuple : Symbol(interfaceIITuple, Decl(castingTuple.ts, 16, 3)) >I : Symbol(I, Decl(castingTuple.ts, 0, 0)) >I : Symbol(I, Decl(castingTuple.ts, 0, 0)) ->classCDTuple : Symbol(classCDTuple, Decl(castingTuple.ts, 13, 3)) +>classCDTuple : Symbol(classCDTuple, Decl(castingTuple.ts, 15, 3)) var classCDATuple = <[C, D, A]>classCDTuple; ->classCDATuple : Symbol(classCDATuple, Decl(castingTuple.ts, 15, 3)) +>classCDATuple : Symbol(classCDATuple, Decl(castingTuple.ts, 17, 3)) >C : Symbol(C, Decl(castingTuple.ts, 1, 19)) >D : Symbol(D, Decl(castingTuple.ts, 2, 27)) >A : Symbol(A, Decl(castingTuple.ts, 0, 15)) ->classCDTuple : Symbol(classCDTuple, Decl(castingTuple.ts, 13, 3)) +>classCDTuple : Symbol(classCDTuple, Decl(castingTuple.ts, 15, 3)) var eleFromCDA1 = classCDATuple[2]; // A ->eleFromCDA1 : Symbol(eleFromCDA1, Decl(castingTuple.ts, 16, 3)) ->classCDATuple : Symbol(classCDATuple, Decl(castingTuple.ts, 15, 3)) +>eleFromCDA1 : Symbol(eleFromCDA1, Decl(castingTuple.ts, 18, 3)) +>classCDATuple : Symbol(classCDATuple, Decl(castingTuple.ts, 17, 3)) >2 : Symbol(2) var eleFromCDA2 = classCDATuple[5]; // C | D | A ->eleFromCDA2 : Symbol(eleFromCDA2, Decl(castingTuple.ts, 17, 3)) ->classCDATuple : Symbol(classCDATuple, Decl(castingTuple.ts, 15, 3)) +>eleFromCDA2 : Symbol(eleFromCDA2, Decl(castingTuple.ts, 19, 3)) +>classCDATuple : Symbol(classCDATuple, Decl(castingTuple.ts, 17, 3)) var t10: [E1, E2] = [E1.one, E2.one]; ->t10 : Symbol(t10, Decl(castingTuple.ts, 18, 3)) +>t10 : Symbol(t10, Decl(castingTuple.ts, 20, 3)) >E1 : Symbol(E1, Decl(castingTuple.ts, 5, 24)) >E2 : Symbol(E2, Decl(castingTuple.ts, 6, 15)) >E1.one : Symbol(E1.one, Decl(castingTuple.ts, 6, 9)) @@ -87,45 +95,45 @@ var t10: [E1, E2] = [E1.one, E2.one]; >one : Symbol(E2.one, Decl(castingTuple.ts, 7, 9)) var t11 = <[number, number]>t10; ->t11 : Symbol(t11, Decl(castingTuple.ts, 19, 3)) ->t10 : Symbol(t10, Decl(castingTuple.ts, 18, 3)) +>t11 : Symbol(t11, Decl(castingTuple.ts, 21, 3)) +>t10 : Symbol(t10, Decl(castingTuple.ts, 20, 3)) var array1 = <{}[]>emptyObjTuple; ->array1 : Symbol(array1, Decl(castingTuple.ts, 20, 3), Decl(castingTuple.ts, 29, 3)) +>array1 : Symbol(array1, Decl(castingTuple.ts, 22, 3), Decl(castingTuple.ts, 31, 3)) >emptyObjTuple : Symbol(emptyObjTuple, Decl(castingTuple.ts, 11, 3)) var unionTuple: [C, string | number] = [new C(), "foo"]; ->unionTuple : Symbol(unionTuple, Decl(castingTuple.ts, 21, 3)) +>unionTuple : Symbol(unionTuple, Decl(castingTuple.ts, 23, 3)) >C : Symbol(C, Decl(castingTuple.ts, 1, 19)) >C : Symbol(C, Decl(castingTuple.ts, 1, 19)) var unionTuple2: [C, string | number, D] = [new C(), "foo", new D()]; ->unionTuple2 : Symbol(unionTuple2, Decl(castingTuple.ts, 22, 3)) +>unionTuple2 : Symbol(unionTuple2, Decl(castingTuple.ts, 24, 3)) >C : Symbol(C, Decl(castingTuple.ts, 1, 19)) >D : Symbol(D, Decl(castingTuple.ts, 2, 27)) >C : Symbol(C, Decl(castingTuple.ts, 1, 19)) >D : Symbol(D, Decl(castingTuple.ts, 2, 27)) var unionTuple3: [number, string| number] = [10, "foo"]; ->unionTuple3 : Symbol(unionTuple3, Decl(castingTuple.ts, 23, 3)) +>unionTuple3 : Symbol(unionTuple3, Decl(castingTuple.ts, 25, 3)) var unionTuple4 = <[number, number]>unionTuple3; ->unionTuple4 : Symbol(unionTuple4, Decl(castingTuple.ts, 24, 3)) ->unionTuple3 : Symbol(unionTuple3, Decl(castingTuple.ts, 23, 3)) +>unionTuple4 : Symbol(unionTuple4, Decl(castingTuple.ts, 26, 3)) +>unionTuple3 : Symbol(unionTuple3, Decl(castingTuple.ts, 25, 3)) // error var t3 = <[number, number]>numStrTuple; ->t3 : Symbol(t3, Decl(castingTuple.ts, 27, 3)) +>t3 : Symbol(t3, Decl(castingTuple.ts, 29, 3)) >numStrTuple : Symbol(numStrTuple, Decl(castingTuple.ts, 10, 3)) var t9 = <[A, I]>classCDTuple; ->t9 : Symbol(t9, Decl(castingTuple.ts, 28, 3)) +>t9 : Symbol(t9, Decl(castingTuple.ts, 30, 3)) >A : Symbol(A, Decl(castingTuple.ts, 0, 15)) >I : Symbol(I, Decl(castingTuple.ts, 0, 0)) ->classCDTuple : Symbol(classCDTuple, Decl(castingTuple.ts, 13, 3)) +>classCDTuple : Symbol(classCDTuple, Decl(castingTuple.ts, 15, 3)) var array1 = numStrTuple; ->array1 : Symbol(array1, Decl(castingTuple.ts, 20, 3), Decl(castingTuple.ts, 29, 3)) +>array1 : Symbol(array1, Decl(castingTuple.ts, 22, 3), Decl(castingTuple.ts, 31, 3)) >numStrTuple : Symbol(numStrTuple, Decl(castingTuple.ts, 10, 3)) t4[2] = 10; diff --git a/tests/baselines/reference/castingTuple.types b/tests/baselines/reference/castingTuple.types index 23d2e51a576..0b9aa0a1487 100644 --- a/tests/baselines/reference/castingTuple.types +++ b/tests/baselines/reference/castingTuple.types @@ -52,6 +52,16 @@ var numStrBoolTuple = <[number, string, boolean]>numStrTuple; ><[number, string, boolean]>numStrTuple : [number, string, boolean] >numStrTuple : [number, string] +var shorter = numStrBoolTuple as [number, string] +>shorter : [number, string] +>numStrBoolTuple as [number, string] : [number, string] +>numStrBoolTuple : [number, string, boolean] + +var longer = numStrTuple as [number, string, boolean] +>longer : [number, string, boolean] +>numStrTuple as [number, string, boolean] : [number, string, boolean] +>numStrTuple : [number, string] + var classCDTuple: [C, D] = [new C(), new D()]; >classCDTuple : [C, D] >C : C diff --git a/tests/baselines/reference/contextualTypeWithTuple.errors.txt b/tests/baselines/reference/contextualTypeWithTuple.errors.txt index a488d8c7648..58a90919c5b 100644 --- a/tests/baselines/reference/contextualTypeWithTuple.errors.txt +++ b/tests/baselines/reference/contextualTypeWithTuple.errors.txt @@ -1,8 +1,6 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(3,5): error TS2322: Type '[number, string, boolean]' is not assignable to type '[number, string]'. - Types of property 'pop' are incompatible. - Type '() => string | number | boolean' is not assignable to type '() => string | number'. - Type 'string | number | boolean' is not assignable to type 'string | number'. - Type 'true' is not assignable to type 'string | number'. + Types of property 'length' are incompatible. + Type '3' is not assignable to type '2'. tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(15,1): error TS2322: Type '[number, string, boolean]' is not assignable to type '[number, string]'. tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(18,1): error TS2322: Type '[{}, number]' is not assignable to type '[{ a: string; }, number]'. Type '{}' is not assignable to type '{ a: string; }'. @@ -10,10 +8,11 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(18,1): error TS23 tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(19,1): error TS2322: Type '[number, string]' is not assignable to type '[number, string, boolean]'. Property '2' is missing in type '[number, string]'. tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(20,5): error TS2322: Type '[string, string, number]' is not assignable to type '[string, string]'. - Types of property 'pop' are incompatible. - Type '() => string | number' is not assignable to type '() => string'. - Type 'string | number' is not assignable to type 'string'. - Type 'number' is not assignable to type 'string'. + Types of property 'length' are incompatible. + Type '3' is not assignable to type '2'. +tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(23,1): error TS2322: Type '[C, string | number, D]' is not assignable to type '[C, string | number]'. + Types of property 'length' are incompatible. + Type '3' is not assignable to type '2'. tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(24,1): error TS2322: Type '[C, string | number]' is not assignable to type '[C, string | number, D]'. Property '2' is missing in type '[C, string | number]'. tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(25,1): error TS2322: Type '[number, string | number]' is not assignable to type '[number, string]'. @@ -21,16 +20,14 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(25,1): error TS23 Type 'number' is not assignable to type 'string'. -==== tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts (7 errors) ==== +==== tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts (8 errors) ==== // no error var numStrTuple: [number, string] = [5, "hello"]; var numStrTuple2: [number, string] = [5, "foo", true]; ~~~~~~~~~~~~ !!! error TS2322: Type '[number, string, boolean]' is not assignable to type '[number, string]'. -!!! error TS2322: Types of property 'pop' are incompatible. -!!! error TS2322: Type '() => string | number | boolean' is not assignable to type '() => string | number'. -!!! error TS2322: Type 'string | number | boolean' is not assignable to type 'string | number'. -!!! error TS2322: Type 'true' is not assignable to type 'string | number'. +!!! error TS2322: Types of property 'length' are incompatible. +!!! error TS2322: Type '3' is not assignable to type '2'. var numStrBoolTuple: [number, string, boolean] = [5, "foo", true]; var objNumTuple: [{ a: string }, number] = [{ a: "world" }, 5]; var strTupleTuple: [string, [number, {}]] = ["bar", [5, { x: 1, y: 1 }]]; @@ -59,13 +56,15 @@ tests/cases/conformance/types/tuple/contextualTypeWithTuple.ts(25,1): error TS23 var strStrTuple: [string, string] = ["foo", "bar", 5]; ~~~~~~~~~~~ !!! error TS2322: Type '[string, string, number]' is not assignable to type '[string, string]'. -!!! error TS2322: Types of property 'pop' are incompatible. -!!! error TS2322: Type '() => string | number' is not assignable to type '() => string'. -!!! error TS2322: Type 'string | number' is not assignable to type 'string'. -!!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! error TS2322: Types of property 'length' are incompatible. +!!! error TS2322: Type '3' is not assignable to type '2'. unionTuple = unionTuple1; unionTuple = unionTuple2; + ~~~~~~~~~~ +!!! error TS2322: Type '[C, string | number, D]' is not assignable to type '[C, string | number]'. +!!! error TS2322: Types of property 'length' are incompatible. +!!! error TS2322: Type '3' is not assignable to type '2'. unionTuple2 = unionTuple; ~~~~~~~~~~~ !!! error TS2322: Type '[C, string | number]' is not assignable to type '[C, string | number, D]'. diff --git a/tests/baselines/reference/destructuringParameterDeclaration1ES5.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration1ES5.errors.txt index 8e51c2b6111..fbbfc3b0d21 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration1ES5.errors.txt +++ b/tests/baselines/reference/destructuringParameterDeclaration1ES5.errors.txt @@ -1,8 +1,14 @@ +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5.ts(12,4): error TS2345: Argument of type '[number, number, string[][], number]' is not assignable to parameter of type '[number, number, string[][]]'. + Types of property 'length' are incompatible. + Type '4' is not assignable to type '3'. +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5.ts(57,4): error TS2345: Argument of type '[number, number, [[string]], boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. + Types of property 'length' are incompatible. + Type '5' is not assignable to type '3'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5.ts(62,10): error TS2393: Duplicate function implementation. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5.ts(63,10): error TS2393: Duplicate function implementation. -==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5.ts (2 errors) ==== +==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5.ts (4 errors) ==== // A parameter declaration may specify either an identifier or a binding pattern. // The identifiers specified in parameter declarations and binding patterns // in a parameter list must be unique within that parameter list. @@ -15,6 +21,10 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5. a1([1, 2, [["world"]]]); a1([1, 2, [["world"]], 3]); + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '[number, number, string[][], number]' is not assignable to parameter of type '[number, number, string[][]]'. +!!! error TS2345: Types of property 'length' are incompatible. +!!! error TS2345: Type '4' is not assignable to type '3'. // If the declaration includes an initializer expression (which is permitted only // when the parameter list occurs in conjunction with a function body), @@ -60,6 +70,10 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5. c5([1, 2, [["string"]]]); // Implied type is is [any, any, [[any]]] c5([1, 2, [["string"]], false, true]); // Implied type is is [any, any, [[any]]] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '[number, number, [[string]], boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. +!!! error TS2345: Types of property 'length' are incompatible. +!!! error TS2345: Type '5' is not assignable to type '3'. // A parameter can be marked optional by following its name or binding pattern with a question mark (?) // or by including an initializer. diff --git a/tests/baselines/reference/destructuringParameterDeclaration1ES5.types b/tests/baselines/reference/destructuringParameterDeclaration1ES5.types index a4b7e882298..c7a5c44f1d4 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration1ES5.types +++ b/tests/baselines/reference/destructuringParameterDeclaration1ES5.types @@ -54,7 +54,7 @@ a1([1, 2, [["world"]]]); a1([1, 2, [["world"]], 3]); >a1([1, 2, [["world"]], 3]) : void >a1 : ([a, b, [[c]]]: [number, number, string[][]]) => void ->[1, 2, [["world"]], 3] : [number, number, string[][], number] +>[1, 2, [["world"]], 3] : (number | string[][])[] >1 : 1 >2 : 2 >[["world"]] : string[][] @@ -304,11 +304,11 @@ c5([1, 2, [["string"]]]); // Implied type is is [any, any, [[any]] c5([1, 2, [["string"]], false, true]); // Implied type is is [any, any, [[any]]] >c5([1, 2, [["string"]], false, true]) : void >c5 : ([a, b, [[c]]]: [any, any, [[any]]]) => void ->[1, 2, [["string"]], false, true] : [number, number, [[string]], boolean, boolean] +>[1, 2, [["string"]], false, true] : (number | boolean | string[][])[] >1 : 1 >2 : 2 ->[["string"]] : [[string]] ->["string"] : [string] +>[["string"]] : string[][] +>["string"] : string[] >"string" : "string" >false : false >true : true diff --git a/tests/baselines/reference/destructuringParameterDeclaration1ES5iterable.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration1ES5iterable.errors.txt index 101a37fc84a..1dc3c61bb3a 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration1ES5iterable.errors.txt +++ b/tests/baselines/reference/destructuringParameterDeclaration1ES5iterable.errors.txt @@ -1,8 +1,14 @@ +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5iterable.ts(12,4): error TS2345: Argument of type '[number, number, string[][], number]' is not assignable to parameter of type '[number, number, string[][]]'. + Types of property 'length' are incompatible. + Type '4' is not assignable to type '3'. +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5iterable.ts(57,4): error TS2345: Argument of type '[number, number, [[string]], boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. + Types of property 'length' are incompatible. + Type '5' is not assignable to type '3'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5iterable.ts(62,10): error TS2393: Duplicate function implementation. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5iterable.ts(63,10): error TS2393: Duplicate function implementation. -==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5iterable.ts (2 errors) ==== +==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5iterable.ts (4 errors) ==== // A parameter declaration may specify either an identifier or a binding pattern. // The identifiers specified in parameter declarations and binding patterns // in a parameter list must be unique within that parameter list. @@ -15,6 +21,10 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5i a1([1, 2, [["world"]]]); a1([1, 2, [["world"]], 3]); + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '[number, number, string[][], number]' is not assignable to parameter of type '[number, number, string[][]]'. +!!! error TS2345: Types of property 'length' are incompatible. +!!! error TS2345: Type '4' is not assignable to type '3'. // If the declaration includes an initializer expression (which is permitted only // when the parameter list occurs in conjunction with a function body), @@ -60,6 +70,10 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5i c5([1, 2, [["string"]]]); // Implied type is is [any, any, [[any]]] c5([1, 2, [["string"]], false, true]); // Implied type is is [any, any, [[any]]] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '[number, number, [[string]], boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. +!!! error TS2345: Types of property 'length' are incompatible. +!!! error TS2345: Type '5' is not assignable to type '3'. // A parameter can be marked optional by following its name or binding pattern with a question mark (?) // or by including an initializer. diff --git a/tests/baselines/reference/destructuringParameterDeclaration1ES5iterable.types b/tests/baselines/reference/destructuringParameterDeclaration1ES5iterable.types index 9d72faf55b6..b41a2027586 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration1ES5iterable.types +++ b/tests/baselines/reference/destructuringParameterDeclaration1ES5iterable.types @@ -54,7 +54,7 @@ a1([1, 2, [["world"]]]); a1([1, 2, [["world"]], 3]); >a1([1, 2, [["world"]], 3]) : void >a1 : ([a, b, [[c]]]: [number, number, string[][]]) => void ->[1, 2, [["world"]], 3] : [number, number, string[][], number] +>[1, 2, [["world"]], 3] : (number | string[][])[] >1 : 1 >2 : 2 >[["world"]] : string[][] @@ -304,11 +304,11 @@ c5([1, 2, [["string"]]]); // Implied type is is [any, any, [[any]] c5([1, 2, [["string"]], false, true]); // Implied type is is [any, any, [[any]]] >c5([1, 2, [["string"]], false, true]) : void >c5 : ([a, b, [[c]]]: [any, any, [[any]]]) => void ->[1, 2, [["string"]], false, true] : [number, number, [[string]], boolean, boolean] +>[1, 2, [["string"]], false, true] : (number | boolean | string[][])[] >1 : 1 >2 : 2 ->[["string"]] : [[string]] ->["string"] : [string] +>[["string"]] : string[][] +>["string"] : string[] >"string" : "string" >false : false >true : true diff --git a/tests/baselines/reference/destructuringParameterDeclaration1ES6.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration1ES6.errors.txt index e900b9be393..f6c17a5c0ea 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration1ES6.errors.txt +++ b/tests/baselines/reference/destructuringParameterDeclaration1ES6.errors.txt @@ -1,9 +1,15 @@ +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES6.ts(14,4): error TS2345: Argument of type '[number, number, string[][], number]' is not assignable to parameter of type '[number, number, string[][]]'. + Types of property 'length' are incompatible. + Type '4' is not assignable to type '3'. +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES6.ts(58,4): error TS2345: Argument of type '[number, number, [[string]], boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. + Types of property 'length' are incompatible. + Type '5' is not assignable to type '3'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES6.ts(96,18): error TS2300: Duplicate identifier 'number'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES6.ts(96,26): error TS2300: Duplicate identifier 'number'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES6.ts(96,34): error TS2300: Duplicate identifier 'number'. -==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES6.ts (3 errors) ==== +==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES6.ts (5 errors) ==== // Conformance for emitting ES6 // A parameter declaration may specify either an identifier or a binding pattern. @@ -18,6 +24,10 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES6. a1([1, 2, [["world"]]]); a1([1, 2, [["world"]], 3]); + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '[number, number, string[][], number]' is not assignable to parameter of type '[number, number, string[][]]'. +!!! error TS2345: Types of property 'length' are incompatible. +!!! error TS2345: Type '4' is not assignable to type '3'. // If the declaration includes an initializer expression (which is permitted only @@ -62,6 +72,10 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES6. c5([1, 2, [["string"]]]); // Implied type is is [any, any, [[any]]] c5([1, 2, [["string"]], false, true]); // Implied type is is [any, any, [[any]]] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '[number, number, [[string]], boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. +!!! error TS2345: Types of property 'length' are incompatible. +!!! error TS2345: Type '5' is not assignable to type '3'. // A parameter can be marked optional by following its name or binding pattern with a question mark (?) diff --git a/tests/baselines/reference/destructuringParameterDeclaration1ES6.types b/tests/baselines/reference/destructuringParameterDeclaration1ES6.types index b997dcf6017..9de904efdec 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration1ES6.types +++ b/tests/baselines/reference/destructuringParameterDeclaration1ES6.types @@ -56,7 +56,7 @@ a1([1, 2, [["world"]]]); a1([1, 2, [["world"]], 3]); >a1([1, 2, [["world"]], 3]) : void >a1 : ([a, b, [[c]]]: [number, number, string[][]]) => void ->[1, 2, [["world"]], 3] : [number, number, string[][], number] +>[1, 2, [["world"]], 3] : (number | string[][])[] >1 : 1 >2 : 2 >[["world"]] : string[][] @@ -287,11 +287,11 @@ c5([1, 2, [["string"]]]); // Implied type is is [any, any, [[any]] c5([1, 2, [["string"]], false, true]); // Implied type is is [any, any, [[any]]] >c5([1, 2, [["string"]], false, true]) : void >c5 : ([a, b, [[c]]]: [any, any, [[any]]]) => void ->[1, 2, [["string"]], false, true] : [number, number, [[string]], boolean, boolean] +>[1, 2, [["string"]], false, true] : (number | boolean | string[][])[] >1 : 1 >2 : 2 ->[["string"]] : [[string]] ->["string"] : [string] +>[["string"]] : string[][] +>["string"] : string[] >"string" : "string" >false : false >true : true diff --git a/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt index 81c85f7c42b..96b93423660 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt +++ b/tests/baselines/reference/destructuringParameterDeclaration2.errors.txt @@ -2,10 +2,8 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts( Type 'string' is not assignable to type 'number'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(7,29): error TS1005: ',' expected. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(8,4): error TS2345: Argument of type '[number, number, string[][], string]' is not assignable to parameter of type '[number, number, string[][]]'. - Types of property 'pop' are incompatible. - Type '() => string | number | string[][]' is not assignable to type '() => number | string[][]'. - Type 'string | number | string[][]' is not assignable to type 'number | string[][]'. - Type 'string' is not assignable to type 'number | string[][]'. + Types of property 'length' are incompatible. + Type '4' is not assignable to type '3'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(16,8): error TS2371: A parameter initializer is only allowed in a function or constructor implementation. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(16,16): error TS2371: A parameter initializer is only allowed in a function or constructor implementation. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts(23,14): error TS2345: Argument of type '{ x: string; y: boolean; }' is not assignable to parameter of type '{ x: number; y: any; }'. @@ -64,10 +62,8 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration2.ts( a0([1, 2, [["world"]], "string"]); // Error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2345: Argument of type '[number, number, string[][], string]' is not assignable to parameter of type '[number, number, string[][]]'. -!!! error TS2345: Types of property 'pop' are incompatible. -!!! error TS2345: Type '() => string | number | string[][]' is not assignable to type '() => number | string[][]'. -!!! error TS2345: Type 'string | number | string[][]' is not assignable to type 'number | string[][]'. -!!! error TS2345: Type 'string' is not assignable to type 'number | string[][]'. +!!! error TS2345: Types of property 'length' are incompatible. +!!! error TS2345: Type '4' is not assignable to type '3'. // If the declaration includes an initializer expression (which is permitted only diff --git a/tests/baselines/reference/destructuringParameterDeclaration3ES5.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration3ES5.errors.txt new file mode 100644 index 00000000000..3b16993a047 --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration3ES5.errors.txt @@ -0,0 +1,55 @@ +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration3ES5.ts(26,4): error TS2345: Argument of type '[number, number, [[string]], boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. + Types of property 'length' are incompatible. + Type '5' is not assignable to type '3'. + + +==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration3ES5.ts (1 errors) ==== + // If the parameter is a rest parameter, the parameter type is any[] + // A type annotation for a rest parameter must denote an array type. + + // RestParameter: + // ... Identifier TypeAnnotation(opt) + + type arrayString = Array + type someArray = Array | number[]; + type stringOrNumArray = Array; + + function a1(...x: (number|string)[]) { } + function a2(...a) { } + function a3(...a: Array) { } + function a4(...a: arrayString) { } + function a5(...a: stringOrNumArray) { } + function a9([a, b, [[c]]]) { } + function a10([a, b, [[c]], ...x]) { } + function a11([a, b, c, ...x]: number[]) { } + + + var array = [1, 2, 3]; + var array2 = [true, false, "hello"]; + a2([...array]); + a1(...array); + + a9([1, 2, [["string"]], false, true]); // Parameter type is [any, any, [[any]]] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '[number, number, [[string]], boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. +!!! error TS2345: Types of property 'length' are incompatible. +!!! error TS2345: Type '5' is not assignable to type '3'. + + a10([1, 2, [["string"]], false, true]); // Parameter type is any[] + a10([1, 2, 3, false, true]); // Parameter type is any[] + a10([1, 2]); // Parameter type is any[] + a11([1, 2]); // Parameter type is number[] + + // Rest parameter with generic + function foo(...a: T[]) { } + foo("hello", 1, 2); + foo("hello", "world"); + + enum E { a, b } + const enum E1 { a, b } + function foo1(...a: T[]) { } + foo1(1, 2, 3, E.a); + foo1(1, 2, 3, E1.a, E.b); + + + \ No newline at end of file diff --git a/tests/baselines/reference/destructuringParameterDeclaration3ES5.types b/tests/baselines/reference/destructuringParameterDeclaration3ES5.types index a91d54d5284..33e0d3b6bd8 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration3ES5.types +++ b/tests/baselines/reference/destructuringParameterDeclaration3ES5.types @@ -96,11 +96,11 @@ a1(...array); a9([1, 2, [["string"]], false, true]); // Parameter type is [any, any, [[any]]] >a9([1, 2, [["string"]], false, true]) : void >a9 : ([a, b, [[c]]]: [any, any, [[any]]]) => void ->[1, 2, [["string"]], false, true] : [number, number, [[string]], boolean, boolean] +>[1, 2, [["string"]], false, true] : (number | boolean | string[][])[] >1 : 1 >2 : 2 ->[["string"]] : [[string]] ->["string"] : [string] +>[["string"]] : string[][] +>["string"] : string[] >"string" : "string" >false : false >true : true diff --git a/tests/baselines/reference/destructuringParameterDeclaration3ES5iterable.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration3ES5iterable.errors.txt new file mode 100644 index 00000000000..f0dbf325ed4 --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration3ES5iterable.errors.txt @@ -0,0 +1,55 @@ +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration3ES5iterable.ts(26,4): error TS2345: Argument of type '[number, number, [[string]], boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. + Types of property 'length' are incompatible. + Type '5' is not assignable to type '3'. + + +==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration3ES5iterable.ts (1 errors) ==== + // If the parameter is a rest parameter, the parameter type is any[] + // A type annotation for a rest parameter must denote an array type. + + // RestParameter: + // ... Identifier TypeAnnotation(opt) + + type arrayString = Array + type someArray = Array | number[]; + type stringOrNumArray = Array; + + function a1(...x: (number|string)[]) { } + function a2(...a) { } + function a3(...a: Array) { } + function a4(...a: arrayString) { } + function a5(...a: stringOrNumArray) { } + function a9([a, b, [[c]]]) { } + function a10([a, b, [[c]], ...x]) { } + function a11([a, b, c, ...x]: number[]) { } + + + var array = [1, 2, 3]; + var array2 = [true, false, "hello"]; + a2([...array]); + a1(...array); + + a9([1, 2, [["string"]], false, true]); // Parameter type is [any, any, [[any]]] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '[number, number, [[string]], boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. +!!! error TS2345: Types of property 'length' are incompatible. +!!! error TS2345: Type '5' is not assignable to type '3'. + + a10([1, 2, [["string"]], false, true]); // Parameter type is any[] + a10([1, 2, 3, false, true]); // Parameter type is any[] + a10([1, 2]); // Parameter type is any[] + a11([1, 2]); // Parameter type is number[] + + // Rest parameter with generic + function foo(...a: T[]) { } + foo("hello", 1, 2); + foo("hello", "world"); + + enum E { a, b } + const enum E1 { a, b } + function foo1(...a: T[]) { } + foo1(1, 2, 3, E.a); + foo1(1, 2, 3, E1.a, E.b); + + + \ No newline at end of file diff --git a/tests/baselines/reference/destructuringParameterDeclaration3ES5iterable.types b/tests/baselines/reference/destructuringParameterDeclaration3ES5iterable.types index 5f2963abe87..931e149ffe2 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration3ES5iterable.types +++ b/tests/baselines/reference/destructuringParameterDeclaration3ES5iterable.types @@ -96,11 +96,11 @@ a1(...array); a9([1, 2, [["string"]], false, true]); // Parameter type is [any, any, [[any]]] >a9([1, 2, [["string"]], false, true]) : void >a9 : ([a, b, [[c]]]: [any, any, [[any]]]) => void ->[1, 2, [["string"]], false, true] : [number, number, [[string]], boolean, boolean] +>[1, 2, [["string"]], false, true] : (number | boolean | string[][])[] >1 : 1 >2 : 2 ->[["string"]] : [[string]] ->["string"] : [string] +>[["string"]] : string[][] +>["string"] : string[] >"string" : "string" >false : false >true : true diff --git a/tests/baselines/reference/destructuringParameterDeclaration3ES6.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration3ES6.errors.txt new file mode 100644 index 00000000000..67a5c1bf87f --- /dev/null +++ b/tests/baselines/reference/destructuringParameterDeclaration3ES6.errors.txt @@ -0,0 +1,55 @@ +tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration3ES6.ts(26,4): error TS2345: Argument of type '[number, number, [[string]], boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. + Types of property 'length' are incompatible. + Type '5' is not assignable to type '3'. + + +==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration3ES6.ts (1 errors) ==== + // If the parameter is a rest parameter, the parameter type is any[] + // A type annotation for a rest parameter must denote an array type. + + // RestParameter: + // ... Identifier TypeAnnotation(opt) + + type arrayString = Array + type someArray = Array | number[]; + type stringOrNumArray = Array; + + function a1(...x: (number|string)[]) { } + function a2(...a) { } + function a3(...a: Array) { } + function a4(...a: arrayString) { } + function a5(...a: stringOrNumArray) { } + function a9([a, b, [[c]]]) { } + function a10([a, b, [[c]], ...x]) { } + function a11([a, b, c, ...x]: number[]) { } + + + var array = [1, 2, 3]; + var array2 = [true, false, "hello"]; + a2([...array]); + a1(...array); + + a9([1, 2, [["string"]], false, true]); // Parameter type is [any, any, [[any]]] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '[number, number, [[string]], boolean, boolean]' is not assignable to parameter of type '[any, any, [[any]]]'. +!!! error TS2345: Types of property 'length' are incompatible. +!!! error TS2345: Type '5' is not assignable to type '3'. + + a10([1, 2, [["string"]], false, true]); // Parameter type is any[] + a10([1, 2, 3, false, true]); // Parameter type is any[] + a10([1, 2]); // Parameter type is any[] + a11([1, 2]); // Parameter type is number[] + + // Rest parameter with generic + function foo(...a: T[]) { } + foo("hello", 1, 2); + foo("hello", "world"); + + enum E { a, b } + const enum E1 { a, b } + function foo1(...a: T[]) { } + foo1(1, 2, 3, E.a); + foo1(1, 2, 3, E1.a, E.b); + + + \ No newline at end of file diff --git a/tests/baselines/reference/destructuringParameterDeclaration3ES6.types b/tests/baselines/reference/destructuringParameterDeclaration3ES6.types index 397ec934a2f..dc5e64d2c2c 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration3ES6.types +++ b/tests/baselines/reference/destructuringParameterDeclaration3ES6.types @@ -96,11 +96,11 @@ a1(...array); a9([1, 2, [["string"]], false, true]); // Parameter type is [any, any, [[any]]] >a9([1, 2, [["string"]], false, true]) : void >a9 : ([a, b, [[c]]]: [any, any, [[any]]]) => void ->[1, 2, [["string"]], false, true] : [number, number, [[string]], boolean, boolean] +>[1, 2, [["string"]], false, true] : (number | boolean | string[][])[] >1 : 1 >2 : 2 ->[["string"]] : [[string]] ->["string"] : [string] +>[["string"]] : string[][] +>["string"] : string[] >"string" : "string" >false : false >true : true diff --git a/tests/baselines/reference/genericCallWithTupleType.errors.txt b/tests/baselines/reference/genericCallWithTupleType.errors.txt index 617c4f7159b..65920596c45 100644 --- a/tests/baselines/reference/genericCallWithTupleType.errors.txt +++ b/tests/baselines/reference/genericCallWithTupleType.errors.txt @@ -1,8 +1,6 @@ tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(12,1): error TS2322: Type '[string, number, boolean, boolean]' is not assignable to type '[string, number]'. - Types of property 'pop' are incompatible. - Type '() => string | number | boolean' is not assignable to type '() => string | number'. - Type 'string | number | boolean' is not assignable to type 'string | number'. - Type 'true' is not assignable to type 'string | number'. + Types of property 'length' are incompatible. + Type '4' is not assignable to type '2'. tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(14,1): error TS2322: Type '{ a: string; }' is not assignable to type 'string | number'. Type '{ a: string; }' is not assignable to type 'number'. tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(22,1): error TS2322: Type '[number, string]' is not assignable to type '[string, number]'. @@ -28,10 +26,8 @@ tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTup i1.tuple1 = ["foo", 5, false, true]; ~~~~~~~~~ !!! error TS2322: Type '[string, number, boolean, boolean]' is not assignable to type '[string, number]'. -!!! error TS2322: Types of property 'pop' are incompatible. -!!! error TS2322: Type '() => string | number | boolean' is not assignable to type '() => string | number'. -!!! error TS2322: Type 'string | number | boolean' is not assignable to type 'string | number'. -!!! error TS2322: Type 'true' is not assignable to type 'string | number'. +!!! error TS2322: Types of property 'length' are incompatible. +!!! error TS2322: Type '4' is not assignable to type '2'. var e3 = i1.tuple1[2]; // {} i1.tuple1[3] = { a: "string" }; ~~~~~~~~~~~~ diff --git a/tests/baselines/reference/keyofAndIndexedAccess.types b/tests/baselines/reference/keyofAndIndexedAccess.types index 9ae7b793ce2..302cefabf90 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.types +++ b/tests/baselines/reference/keyofAndIndexedAccess.types @@ -352,8 +352,8 @@ function f12(t: [Shape, boolean]) { >Shape : Shape let len = getProperty(t, "length"); ->len : number ->getProperty(t, "length") : number +>len : 2 +>getProperty(t, "length") : 2 >getProperty : (obj: T, key: K) => T[K] >t : [Shape, boolean] >"length" : "length" diff --git a/tests/baselines/reference/promiseEmptyTupleNoException.errors.txt b/tests/baselines/reference/promiseEmptyTupleNoException.errors.txt index 0237d658da5..73d768ddfeb 100644 --- a/tests/baselines/reference/promiseEmptyTupleNoException.errors.txt +++ b/tests/baselines/reference/promiseEmptyTupleNoException.errors.txt @@ -1,8 +1,7 @@ tests/cases/compiler/promiseEmptyTupleNoException.ts(1,38): error TS1122: A tuple type element list cannot be empty. tests/cases/compiler/promiseEmptyTupleNoException.ts(3,3): error TS2322: Type 'any[]' is not assignable to type '[]'. - Types of property 'pop' are incompatible. - Type '() => any' is not assignable to type '() => never'. - Type 'any' is not assignable to type 'never'. + Types of property 'length' are incompatible. + Type 'number' is not assignable to type '0'. ==== tests/cases/compiler/promiseEmptyTupleNoException.ts (2 errors) ==== @@ -13,8 +12,7 @@ tests/cases/compiler/promiseEmptyTupleNoException.ts(3,3): error TS2322: Type 'a return emails; ~~~~~~~~~~~~~~ !!! error TS2322: Type 'any[]' is not assignable to type '[]'. -!!! error TS2322: Types of property 'pop' are incompatible. -!!! error TS2322: Type '() => any' is not assignable to type '() => never'. -!!! error TS2322: Type 'any' is not assignable to type 'never'. +!!! error TS2322: Types of property 'length' are incompatible. +!!! error TS2322: Type 'number' is not assignable to type '0'. } \ 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 5ddfd890cc5..08887fc6c94 100644 --- a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json @@ -23,7 +23,6 @@ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "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 854d7da20ae..ca2b4aa4087 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 @@ -23,7 +23,6 @@ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "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 386e240f9b4..9437685c295 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 @@ -23,7 +23,6 @@ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "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 235377d03e9..d2e7e85ad55 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 @@ -23,7 +23,6 @@ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "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 e64ea6fc432..3f4100033d0 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 @@ -23,7 +23,6 @@ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "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 5ddfd890cc5..08887fc6c94 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 @@ -23,7 +23,6 @@ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "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 112e47b09d4..22cb0444209 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 @@ -23,7 +23,6 @@ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "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 1e942b5c9b8..fc3321600fe 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 @@ -23,7 +23,6 @@ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "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/tupleTypes.errors.txt b/tests/baselines/reference/tupleTypes.errors.txt index 3b55476e4b1..16a8f66ba79 100644 --- a/tests/baselines/reference/tupleTypes.errors.txt +++ b/tests/baselines/reference/tupleTypes.errors.txt @@ -5,6 +5,9 @@ tests/cases/compiler/tupleTypes.ts(15,1): error TS2322: Type '[number]' is not a Property '1' is missing in type '[number]'. tests/cases/compiler/tupleTypes.ts(17,1): error TS2322: Type '[string, number]' is not assignable to type '[number, string]'. Type 'string' is not assignable to type 'number'. +tests/cases/compiler/tupleTypes.ts(18,1): error TS2322: Type '[number, string, number]' is not assignable to type '[number, string]'. + Types of property 'length' are incompatible. + Type '3' is not assignable to type '2'. tests/cases/compiler/tupleTypes.ts(41,1): error TS2322: Type 'undefined[]' is not assignable to type '[number, string]'. tests/cases/compiler/tupleTypes.ts(47,1): error TS2322: Type '[number, string]' is not assignable to type 'number[]'. Types of property 'pop' are incompatible. @@ -22,7 +25,7 @@ tests/cases/compiler/tupleTypes.ts(51,1): error TS2322: Type '[number, {}]' is n Type '{}' is not assignable to type 'string'. -==== tests/cases/compiler/tupleTypes.ts (9 errors) ==== +==== tests/cases/compiler/tupleTypes.ts (10 errors) ==== var v1: []; // Error ~~ !!! error TS1122: A tuple type element list cannot be empty. @@ -51,7 +54,11 @@ tests/cases/compiler/tupleTypes.ts(51,1): error TS2322: Type '[number, {}]' is n ~ !!! error TS2322: Type '[string, number]' is not assignable to type '[number, string]'. !!! error TS2322: Type 'string' is not assignable to type 'number'. - t = [1, "hello", 2]; // Ok + t = [1, "hello", 2]; // Error + ~ +!!! error TS2322: Type '[number, string, number]' is not assignable to type '[number, string]'. +!!! error TS2322: Types of property 'length' are incompatible. +!!! error TS2322: Type '3' is not assignable to type '2'. var tf: [string, (x: string) => number] = ["hello", x => x.length]; diff --git a/tests/baselines/reference/tupleTypes.js b/tests/baselines/reference/tupleTypes.js index 451aeb5eb09..947b7bba30b 100644 --- a/tests/baselines/reference/tupleTypes.js +++ b/tests/baselines/reference/tupleTypes.js @@ -16,7 +16,7 @@ t = []; // Error t = [1]; // Error t = [1, "hello"]; // Ok t = ["hello", 1]; // Error -t = [1, "hello", 2]; // Ok +t = [1, "hello", 2]; // Error var tf: [string, (x: string) => number] = ["hello", x => x.length]; @@ -70,7 +70,7 @@ t = []; // Error t = [1]; // Error t = [1, "hello"]; // Ok t = ["hello", 1]; // Error -t = [1, "hello", 2]; // Ok +t = [1, "hello", 2]; // Error var tf = ["hello", function (x) { return x.length; }]; var ff1 = ff("hello", ["foo", function (x) { return x.length; }]); var ff1; diff --git a/tests/baselines/reference/tupleTypes.symbols b/tests/baselines/reference/tupleTypes.symbols index 1f14b269ca9..cf60cea8534 100644 --- a/tests/baselines/reference/tupleTypes.symbols +++ b/tests/baselines/reference/tupleTypes.symbols @@ -49,7 +49,7 @@ t = [1, "hello"]; // Ok t = ["hello", 1]; // Error >t : Symbol(t, Decl(tupleTypes.ts, 5, 3)) -t = [1, "hello", 2]; // Ok +t = [1, "hello", 2]; // Error >t : Symbol(t, Decl(tupleTypes.ts, 5, 3)) var tf: [string, (x: string) => number] = ["hello", x => x.length]; diff --git a/tests/baselines/reference/tupleTypes.types b/tests/baselines/reference/tupleTypes.types index 3bbf48bdb29..3f68d4c7e2d 100644 --- a/tests/baselines/reference/tupleTypes.types +++ b/tests/baselines/reference/tupleTypes.types @@ -66,7 +66,7 @@ t = ["hello", 1]; // Error >"hello" : "hello" >1 : 1 -t = [1, "hello", 2]; // Ok +t = [1, "hello", 2]; // Error >t = [1, "hello", 2] : [number, string, number] >t : [number, string] >[1, "hello", 2] : [number, string, number] diff --git a/tests/baselines/reference/unionTypeFromArrayLiteral.errors.txt b/tests/baselines/reference/unionTypeFromArrayLiteral.errors.txt new file mode 100644 index 00000000000..2ecce8a802e --- /dev/null +++ b/tests/baselines/reference/unionTypeFromArrayLiteral.errors.txt @@ -0,0 +1,33 @@ +tests/cases/conformance/types/union/unionTypeFromArrayLiteral.ts(9,5): error TS2322: Type '[number, string, string]' is not assignable to type '[number, string]'. + Types of property 'length' are incompatible. + Type '3' is not assignable to type '2'. + + +==== tests/cases/conformance/types/union/unionTypeFromArrayLiteral.ts (1 errors) ==== + // The resulting type an array literal expression is determined as follows: + // If the array literal is empty, the resulting type is an array type with the element type Undefined. + // Otherwise, if the array literal is contextually typed by a type that has a property with the numeric name ‘0’, the resulting type is a tuple type constructed from the types of the element expressions. + // Otherwise, the resulting type is an array type with an element type that is the union of the types of the element expressions. + + var arr1 = [1, 2]; // number[] + var arr2 = ["hello", true]; // (string | number)[] + var arr3Tuple: [number, string] = [3, "three"]; // [number, string] + var arr4Tuple: [number, string] = [3, "three", "hello"]; // [number, string, string] + ~~~~~~~~~ +!!! error TS2322: Type '[number, string, string]' is not assignable to type '[number, string]'. +!!! error TS2322: Types of property 'length' are incompatible. +!!! error TS2322: Type '3' is not assignable to type '2'. + var arrEmpty = []; + var arr5Tuple: { + 0: string; + 5: number; + } = ["hello", true, false, " hello", true, 10, "any"]; // Tuple + class C { foo() { } } + class D { foo2() { } } + class E extends C { foo3() { } } + class F extends C { foo4() { } } + var c: C, d: D, e: E, f: F; + var arr6 = [c, d]; // (C | D)[] + var arr7 = [c, d, e]; // (C | D)[] + var arr8 = [c, e]; // C[] + var arr9 = [e, f]; // (E|F)[] \ No newline at end of file diff --git a/tests/baselines/reference/wideningTuples3.errors.txt b/tests/baselines/reference/wideningTuples3.errors.txt index 43c7e349a0c..15e02cfb559 100644 --- a/tests/baselines/reference/wideningTuples3.errors.txt +++ b/tests/baselines/reference/wideningTuples3.errors.txt @@ -1,9 +1,16 @@ tests/cases/conformance/types/tuple/wideningTuples3.ts(3,5): error TS7005: Variable 'b' implicitly has an '[any, any]' type. +tests/cases/conformance/types/tuple/wideningTuples3.ts(3,9): error TS2322: Type '[undefined, null]' is not assignable to type '[any]'. + Types of property 'length' are incompatible. + Type '2' is not assignable to type '1'. -==== tests/cases/conformance/types/tuple/wideningTuples3.ts (1 errors) ==== +==== tests/cases/conformance/types/tuple/wideningTuples3.ts (2 errors) ==== var a: [any]; var b = a = [undefined, null]; ~ -!!! error TS7005: Variable 'b' implicitly has an '[any, any]' type. \ No newline at end of file +!!! error TS7005: Variable 'b' implicitly has an '[any, any]' type. + ~ +!!! error TS2322: Type '[undefined, null]' is not assignable to type '[any]'. +!!! error TS2322: Types of property 'length' are incompatible. +!!! error TS2322: Type '2' is not assignable to type '1'. \ No newline at end of file diff --git a/tests/baselines/reference/wideningTuples4.errors.txt b/tests/baselines/reference/wideningTuples4.errors.txt new file mode 100644 index 00000000000..e38035e7041 --- /dev/null +++ b/tests/baselines/reference/wideningTuples4.errors.txt @@ -0,0 +1,14 @@ +tests/cases/conformance/types/tuple/wideningTuples4.ts(3,9): error TS2322: Type '[undefined, null]' is not assignable to type '[any]'. + Types of property 'length' are incompatible. + Type '2' is not assignable to type '1'. + + +==== tests/cases/conformance/types/tuple/wideningTuples4.ts (1 errors) ==== + var a: [any]; + + var b = a = [undefined, null]; + ~ +!!! error TS2322: Type '[undefined, null]' is not assignable to type '[any]'. +!!! error TS2322: Types of property 'length' are incompatible. +!!! error TS2322: Type '2' is not assignable to type '1'. + b = ["", ""]; \ No newline at end of file diff --git a/tests/cases/compiler/tupleTypes.ts b/tests/cases/compiler/tupleTypes.ts index 80181f8b332..53e5b584b7a 100644 --- a/tests/cases/compiler/tupleTypes.ts +++ b/tests/cases/compiler/tupleTypes.ts @@ -15,7 +15,7 @@ t = []; // Error t = [1]; // Error t = [1, "hello"]; // Ok t = ["hello", 1]; // Error -t = [1, "hello", 2]; // Ok +t = [1, "hello", 2]; // Error var tf: [string, (x: string) => number] = ["hello", x => x.length]; diff --git a/tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts b/tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts index 0f486d843ea..85a035d472b 100644 --- a/tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts +++ b/tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts @@ -1,6 +1,7 @@ interface StrNum extends Array { 0: string; 1: number; + length: 2; } var x: [string, number]; @@ -8,6 +9,7 @@ var y: StrNum var z: { 0: string; 1: number; + length: 2; } var [a, b, c] = x; diff --git a/tests/cases/conformance/types/tuple/castingTuple.ts b/tests/cases/conformance/types/tuple/castingTuple.ts index cf5c58af346..2ffc22ff34c 100644 --- a/tests/cases/conformance/types/tuple/castingTuple.ts +++ b/tests/cases/conformance/types/tuple/castingTuple.ts @@ -11,6 +11,8 @@ enum E2 { one } var numStrTuple: [number, string] = [5, "foo"]; var emptyObjTuple = <[{}, {}]>numStrTuple; var numStrBoolTuple = <[number, string, boolean]>numStrTuple; +var shorter = numStrBoolTuple as [number, string] +var longer = numStrTuple as [number, string, boolean] var classCDTuple: [C, D] = [new C(), new D()]; var interfaceIITuple = <[I, I]>classCDTuple; var classCDATuple = <[C, D, A]>classCDTuple; diff --git a/tests/cases/conformance/types/tuple/strictTupleLength.ts b/tests/cases/conformance/types/tuple/strictTupleLength.ts index bfae662cd7c..eaa9111e557 100644 --- a/tests/cases/conformance/types/tuple/strictTupleLength.ts +++ b/tests/cases/conformance/types/tuple/strictTupleLength.ts @@ -1,5 +1,3 @@ -// @strictTuples: true - var t0: []; var t1: [number]; var t2: [number, number]; From 4385444c4488f7d0fe802e58b7de303e088e0a01 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 6 Nov 2017 10:35:53 -0800 Subject: [PATCH 12/73] Add TupleBase with unusable mutating Array methods --- src/compiler/checker.ts | 13 ++++++++----- src/lib/es5.d.ts | 12 ++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8a214e39c19..83ffce7b21f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -327,6 +327,7 @@ namespace ts { let globalFunctionType: ObjectType; let globalArrayType: GenericType; let globalReadonlyArrayType: GenericType; + let globalTupleBaseType: GenericType; let globalStringType: ObjectType; let globalNumberType: ObjectType; let globalBooleanType: ObjectType; @@ -775,7 +776,7 @@ namespace ts { * @param parameterName a name of the parameter to get the symbols for. * @return a tuple of two symbols */ - function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: __String): [Symbol, Symbol] { + function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: __String): Symbol[] { const constructorDeclaration = parameter.parent; const classDeclaration = parameter.parent.parent; @@ -4996,7 +4997,7 @@ namespace ts { function getBaseTypes(type: InterfaceType): BaseType[] { if (!type.resolvedBaseTypes) { if (type.objectFlags & ObjectFlags.Tuple) { - type.resolvedBaseTypes = [createArrayType(getUnionType(type.typeParameters))]; + type.resolvedBaseTypes = [createTypeFromGenericGlobalType(globalTupleBaseType, [getUnionType(type.typeParameters)])]; } else if (type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { if (type.symbol.flags & SymbolFlags.Class) { @@ -9992,7 +9993,7 @@ namespace ts { const typeParameters = type.typeParameters || emptyArray; let variances = type.variances; if (!variances) { - if (type === globalArrayType || type === globalReadonlyArrayType) { + if (type === globalArrayType || type === globalReadonlyArrayType || type === globalTupleBaseType) { // Arrays are known to be covariant, no need to spend time computing this variances = [Variance.Covariant]; } @@ -10321,7 +10322,7 @@ namespace ts { function isArrayLikeType(type: Type): boolean { // A type is array-like if it is a reference to the global Array or global ReadonlyArray type, // or if it is not the undefined or null type and if it is assignable to ReadonlyArray - return getObjectFlags(type) & ObjectFlags.Reference && ((type).target === globalArrayType || (type).target === globalReadonlyArrayType) || + return getObjectFlags(type) & ObjectFlags.Reference && ((type).target === globalArrayType || (type).target === globalReadonlyArrayType || (type as TypeReference).target === globalTupleBaseType) || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType); } @@ -24509,7 +24510,9 @@ namespace ts { anyArrayType = createArrayType(anyType); autoArrayType = createArrayType(autoType); - globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray" as __String, /*arity*/ 1); + // TODO: ReadonlyArray and TupleBase should always be available, but haven't been required previously + globalReadonlyArrayType = getGlobalType("ReadonlyArray" as __String, /*arity*/ 1, /*reportErrors*/ true); + globalTupleBaseType = getGlobalType("TupleBase" as __String, /*arity*/ 1, /*reportErrors*/ true); anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; globalThisType = getGlobalTypeOrUndefined("ThisType" as __String, /*arity*/ 1); } diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index fd2ae5b3fdf..4694fae4868 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1240,6 +1240,18 @@ interface ArrayConstructor { declare const Array: ArrayConstructor; +interface TupleBase extends Array { + // TODO: Add jsdoc here warning not to call this + push(...items: never[]): never; + pop(): never | undefined; + reverse(): never[]; + sort(compareFn?: (a: never, b: never) => number): never; + shift(): never | undefined; + unshift(...items: never[]): never; + splice(start: number, deleteCount?: number): never[]; + splice(start: number, deleteCount: number, ...items: never[]): never[]; +} + interface TypedPropertyDescriptor { enumerable?: boolean; configurable?: boolean; From 2399d58266087aef119250e5e53a5526d245762b Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 6 Nov 2017 10:50:57 -0800 Subject: [PATCH 13/73] Improve TupleBase docs and backward compatibility --- src/compiler/checker.ts | 6 +++--- src/lib/es5.d.ts | 23 ++++++++++++++--------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 83ffce7b21f..5cddb7d411e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4997,7 +4997,7 @@ namespace ts { function getBaseTypes(type: InterfaceType): BaseType[] { if (!type.resolvedBaseTypes) { if (type.objectFlags & ObjectFlags.Tuple) { - type.resolvedBaseTypes = [createTypeFromGenericGlobalType(globalTupleBaseType, [getUnionType(type.typeParameters)])]; + type.resolvedBaseTypes = [createTypeFromGenericGlobalType(globalTupleBaseType || globalArrayType, [getUnionType(type.typeParameters)])]; } else if (type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { if (type.symbol.flags & SymbolFlags.Class) { @@ -24511,8 +24511,8 @@ namespace ts { autoArrayType = createArrayType(autoType); // TODO: ReadonlyArray and TupleBase should always be available, but haven't been required previously - globalReadonlyArrayType = getGlobalType("ReadonlyArray" as __String, /*arity*/ 1, /*reportErrors*/ true); - globalTupleBaseType = getGlobalType("TupleBase" as __String, /*arity*/ 1, /*reportErrors*/ true); + globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray" as __String, /*arity*/ 1); + globalTupleBaseType = getGlobalTypeOrUndefined("TupleBase" as __String, /*arity*/ 1); anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; globalThisType = getGlobalTypeOrUndefined("ThisType" as __String, /*arity*/ 1); } diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 4694fae4868..d3760e3a310 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1241,15 +1241,20 @@ interface ArrayConstructor { declare const Array: ArrayConstructor; interface TupleBase extends Array { - // TODO: Add jsdoc here warning not to call this - push(...items: never[]): never; - pop(): never | undefined; - reverse(): never[]; - sort(compareFn?: (a: never, b: never) => number): never; - shift(): never | undefined; - unshift(...items: never[]): never; - splice(start: number, deleteCount?: number): never[]; - splice(start: number, deleteCount: number, ...items: never[]): never[]; + /** Mutation is not allowed on tuples. Do not use this method. */ + push: never; + /** Mutation is not allowed on tuples. Do not use this method. */ + pop: never; + /** Mutation is not allowed on tuples. Do not use this method. */ + reverse: never; + /** Mutation is not allowed on tuples. Do not use this method. */ + sort: never; + /** Mutation is not allowed on tuples. Do not use this method. */ + shift: never; + /** Mutation is not allowed on tuples. Do not use this method. */ + unshift: never; + /** Mutation is not allowed on tuples. Do not use this method. */ + splice: never; } interface TypedPropertyDescriptor { From e6c38bf67b451794471245b4a9f4909d02f66320 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 6 Nov 2017 15:16:33 -0800 Subject: [PATCH 14/73] Add DefinitelyTyped test runner Assumes that ../DefinitelyTyped holds the DefinitelyTyped repo. --- src/harness/definitelyRunner.ts | 51 +++++++++++++++++++++++++++++++++ src/harness/runner.ts | 6 ++++ src/harness/runnerbase.ts | 2 +- src/harness/tsconfig.json | 1 + src/harness/userRunner.ts | 2 +- 5 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 src/harness/definitelyRunner.ts diff --git a/src/harness/definitelyRunner.ts b/src/harness/definitelyRunner.ts new file mode 100644 index 00000000000..afd39b72424 --- /dev/null +++ b/src/harness/definitelyRunner.ts @@ -0,0 +1,51 @@ +/// +/// +class DefinitelyTypedRunner extends RunnerBase { + private static readonly testDir = "../DefinitelyTyped/types/"; + public enumerateTestFiles() { + return Harness.IO.getDirectories(DefinitelyTypedRunner.testDir).map(dir => DefinitelyTypedRunner.testDir + dir); + } + + public kind(): TestRunnerKind { + return "definitely"; + } + + /** Setup the runner's tests so that they are ready to be executed by the harness + * The first test should be a describe/it block that sets up the harness's compiler instance appropriately + */ + public initializeTests(): void { + // Read in and evaluate the test list + const testList = this.tests && this.tests.length ? this.tests : this.enumerateTestFiles(); + + describe(`${this.kind()} code samples`, () => { + for (const test of testList) { + this.runTest(test); + } + }); + } + + private runTest(directoryName: string) { + describe(directoryName, () => { + const cp = require("child_process"); + const path = require("path"); + + it("should build successfully", () => { + const cwd = path.join(__dirname, "../../", directoryName); + const timeout = 600000; // 600s = 10 minutes + const stdio = isWorker ? "pipe" : "inherit"; + const install = cp.spawnSync(`npm`, ["i"], { cwd, timeout, shell: true, stdio }); + if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed!`); + Harness.Baseline.runBaseline(`${this.kind()}/${directoryName}.log`, () => { + const result = cp.spawnSync(`node`, [path.join(__dirname, "tsc.js"), "--lib dom,es6", "--strict"], { cwd, timeout, shell: true }); + return `Exit Code: ${result.status} +Standard output: +${result.stdout.toString().replace(/\r\n/g, "\n")} + + +Standard error: +${result.stderr.toString().replace(/\r\n/g, "\n")}`; + }); + }); + }); + } +} diff --git a/src/harness/runner.ts b/src/harness/runner.ts index 70954e9e853..fb66e74b958 100644 --- a/src/harness/runner.ts +++ b/src/harness/runner.ts @@ -19,6 +19,7 @@ /// /// /// +/// /// /// @@ -62,6 +63,8 @@ function createRunner(kind: TestRunnerKind): RunnerBase { return new Test262BaselineRunner(); case "user": return new UserCodeRunner(); + case "definitely": + return new DefinitelyTypedRunner(); } ts.Debug.fail(`Unknown runner kind ${kind}`); } @@ -183,6 +186,9 @@ function handleTestConfig() { case "user": runners.push(new UserCodeRunner()); break; + case "definitely": + runners.push(new DefinitelyTypedRunner()); + break; } } } diff --git a/src/harness/runnerbase.ts b/src/harness/runnerbase.ts index 2fef2264b73..42e625a897d 100644 --- a/src/harness/runnerbase.ts +++ b/src/harness/runnerbase.ts @@ -1,7 +1,7 @@ /// -type TestRunnerKind = CompilerTestKind | FourslashTestKind | "project" | "rwc" | "test262" | "user"; +type TestRunnerKind = CompilerTestKind | FourslashTestKind | "project" | "rwc" | "test262" | "user" | "definitely"; type CompilerTestKind = "conformance" | "compiler"; type FourslashTestKind = "fourslash" | "fourslash-shims" | "fourslash-shims-pp" | "fourslash-server"; diff --git a/src/harness/tsconfig.json b/src/harness/tsconfig.json index 6e61b7690bc..96f1999e9e8 100644 --- a/src/harness/tsconfig.json +++ b/src/harness/tsconfig.json @@ -93,6 +93,7 @@ "loggedIO.ts", "rwcRunner.ts", "userRunner.ts", + "definitelyRunner.ts", "test262Runner.ts", "./parallel/shared.ts", "./parallel/host.ts", diff --git a/src/harness/userRunner.ts b/src/harness/userRunner.ts index 9be652aebf8..61a46d7e84f 100644 --- a/src/harness/userRunner.ts +++ b/src/harness/userRunner.ts @@ -36,7 +36,7 @@ class UserCodeRunner extends RunnerBase { const install = cp.spawnSync(`npm`, ["i"], { cwd, timeout, shell: true, stdio }); if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed!`); Harness.Baseline.runBaseline(`${this.kind()}/${directoryName}.log`, () => { - const result = cp.spawnSync(`node`, ["../../../../built/local/tsc.js"], { cwd, timeout, shell: true }); + const result = cp.spawnSync(`node`, [path.join(__dirname, "tsc.js")], { cwd, timeout, shell: true }); return `Exit Code: ${result.status} Standard output: ${result.stdout.toString().replace(/\r\n/g, "\n")} From f2d4b36a49df7e7fb7a828b68d88a86f41f58717 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 6 Nov 2017 15:17:21 -0800 Subject: [PATCH 15/73] Update Jakefile with definitelyRunner.ts --- Jakefile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Jakefile.js b/Jakefile.js index 7f0915ad7e9..40520e79a4a 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -106,6 +106,7 @@ var harnessCoreSources = [ "loggedIO.ts", "rwcRunner.ts", "userRunner.ts", + "definitelyRunner.ts", "test262Runner.ts", "./parallel/shared.ts", "./parallel/host.ts", From ea55de3e988cbc291f88adfd1eae48619a7cfcc6 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 6 Nov 2017 15:44:16 -0800 Subject: [PATCH 16/73] Eagerly fall back to TupleBase --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7aedfa43a5d..264b5dad105 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4993,7 +4993,7 @@ namespace ts { function getBaseTypes(type: InterfaceType): BaseType[] { if (!type.resolvedBaseTypes) { if (type.objectFlags & ObjectFlags.Tuple) { - type.resolvedBaseTypes = [createTypeFromGenericGlobalType(globalTupleBaseType || globalArrayType, [getUnionType(type.typeParameters)])]; + type.resolvedBaseTypes = [createTypeFromGenericGlobalType(globalTupleBaseType, [getUnionType(type.typeParameters)])]; } else if (type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { if (type.symbol.flags & SymbolFlags.Class) { @@ -24526,7 +24526,7 @@ namespace ts { // TODO: ReadonlyArray and TupleBase should always be available, but haven't been required previously globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray" as __String, /*arity*/ 1); - globalTupleBaseType = getGlobalTypeOrUndefined("TupleBase" as __String, /*arity*/ 1); + globalTupleBaseType = getGlobalTypeOrUndefined("TupleBase" as __String, /*arity*/ 1) || globalArrayType; anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; globalThisType = getGlobalTypeOrUndefined("ThisType" as __String, /*arity*/ 1); } From 888da3c3da54042acc96ac270289159730f56396 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 6 Nov 2017 15:55:16 -0800 Subject: [PATCH 17/73] Update baselines --- .../arityAndOrderCompatibility01.errors.txt | 2 +- .../reference/arityAndOrderCompatibility01.js | 2 +- .../arityAndOrderCompatibility01.symbols | 4 +-- .../arityAndOrderCompatibility01.types | 4 +-- ...nmentCompatBetweenTupleAndArray.errors.txt | 18 +++++----- .../baselines/reference/tupleTypes.errors.txt | 36 ++++++++++--------- .../typeInferenceWithTupleType.errors.txt | 31 ++++++++++++++++ .../typeInferenceWithTupleType.symbols | 4 +-- .../typeInferenceWithTupleType.types | 8 ++--- .../tuple/arityAndOrderCompatibility01.ts | 2 +- 10 files changed, 74 insertions(+), 37 deletions(-) create mode 100644 tests/baselines/reference/typeInferenceWithTupleType.errors.txt diff --git a/tests/baselines/reference/arityAndOrderCompatibility01.errors.txt b/tests/baselines/reference/arityAndOrderCompatibility01.errors.txt index 4d6fbd063ae..273d1f3b318 100644 --- a/tests/baselines/reference/arityAndOrderCompatibility01.errors.txt +++ b/tests/baselines/reference/arityAndOrderCompatibility01.errors.txt @@ -40,7 +40,7 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(32,5): error ==== tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts (19 errors) ==== - interface StrNum extends Array { + interface StrNum extends TupleBase { 0: string; 1: number; length: 2; diff --git a/tests/baselines/reference/arityAndOrderCompatibility01.js b/tests/baselines/reference/arityAndOrderCompatibility01.js index bf7736a80c9..e097b72594e 100644 --- a/tests/baselines/reference/arityAndOrderCompatibility01.js +++ b/tests/baselines/reference/arityAndOrderCompatibility01.js @@ -1,5 +1,5 @@ //// [arityAndOrderCompatibility01.ts] -interface StrNum extends Array { +interface StrNum extends TupleBase { 0: string; 1: number; length: 2; diff --git a/tests/baselines/reference/arityAndOrderCompatibility01.symbols b/tests/baselines/reference/arityAndOrderCompatibility01.symbols index 3a5d55dc1e6..8305819f593 100644 --- a/tests/baselines/reference/arityAndOrderCompatibility01.symbols +++ b/tests/baselines/reference/arityAndOrderCompatibility01.symbols @@ -1,7 +1,7 @@ === tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts === -interface StrNum extends Array { +interface StrNum extends TupleBase { >StrNum : Symbol(StrNum, Decl(arityAndOrderCompatibility01.ts, 0, 0)) ->Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>TupleBase : Symbol(TupleBase, Decl(lib.d.ts, --, --)) 0: string; 1: number; diff --git a/tests/baselines/reference/arityAndOrderCompatibility01.types b/tests/baselines/reference/arityAndOrderCompatibility01.types index 80e91fbd2e7..67a02599c40 100644 --- a/tests/baselines/reference/arityAndOrderCompatibility01.types +++ b/tests/baselines/reference/arityAndOrderCompatibility01.types @@ -1,7 +1,7 @@ === tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts === -interface StrNum extends Array { +interface StrNum extends TupleBase { >StrNum : StrNum ->Array : T[] +>TupleBase : TupleBase 0: string; 1: number; diff --git a/tests/baselines/reference/assignmentCompatBetweenTupleAndArray.errors.txt b/tests/baselines/reference/assignmentCompatBetweenTupleAndArray.errors.txt index 03dcee9baf3..53073a5300a 100644 --- a/tests/baselines/reference/assignmentCompatBetweenTupleAndArray.errors.txt +++ b/tests/baselines/reference/assignmentCompatBetweenTupleAndArray.errors.txt @@ -1,8 +1,9 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatBetweenTupleAndArray.ts(17,1): error TS2322: Type '[number, string]' is not assignable to type 'number[]'. - Types of property 'pop' are incompatible. - Type '() => string | number' is not assignable to type '() => number'. - Type 'string | number' is not assignable to type 'number'. - Type 'string' is not assignable to type 'number'. + Types of property 'concat' are incompatible. + Type '{ (...items: ReadonlyArray[]): (string | number)[]; (...items: (string | number | ReadonlyArray)[]): (string | number)[]; }' is not assignable to type '{ (...items: ReadonlyArray[]): number[]; (...items: (number | ReadonlyArray)[]): number[]; }'. + Type '(string | number)[]' is not assignable to type 'number[]'. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatBetweenTupleAndArray.ts(18,1): error TS2322: Type '{}[]' is not assignable to type '[{}]'. Property '0' is missing in type '{}[]'. @@ -27,10 +28,11 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme numArray = numStrTuple; ~~~~~~~~ !!! error TS2322: Type '[number, string]' is not assignable to type 'number[]'. -!!! error TS2322: Types of property 'pop' are incompatible. -!!! error TS2322: Type '() => string | number' is not assignable to type '() => number'. -!!! error TS2322: Type 'string | number' is not assignable to type 'number'. -!!! error TS2322: Type 'string' is not assignable to type 'number'. +!!! error TS2322: Types of property 'concat' are incompatible. +!!! error TS2322: Type '{ (...items: ReadonlyArray[]): (string | number)[]; (...items: (string | number | ReadonlyArray)[]): (string | number)[]; }' is not assignable to type '{ (...items: ReadonlyArray[]): number[]; (...items: (number | ReadonlyArray)[]): number[]; }'. +!!! error TS2322: Type '(string | number)[]' is not assignable to type 'number[]'. +!!! error TS2322: Type 'string | number' is not assignable to type 'number'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. emptyObjTuple = emptyObjArray; ~~~~~~~~~~~~~ !!! error TS2322: Type '{}[]' is not assignable to type '[{}]'. diff --git a/tests/baselines/reference/tupleTypes.errors.txt b/tests/baselines/reference/tupleTypes.errors.txt index 16a8f66ba79..750df3f5092 100644 --- a/tests/baselines/reference/tupleTypes.errors.txt +++ b/tests/baselines/reference/tupleTypes.errors.txt @@ -10,15 +10,17 @@ tests/cases/compiler/tupleTypes.ts(18,1): error TS2322: Type '[number, string, n Type '3' is not assignable to type '2'. tests/cases/compiler/tupleTypes.ts(41,1): error TS2322: Type 'undefined[]' is not assignable to type '[number, string]'. tests/cases/compiler/tupleTypes.ts(47,1): error TS2322: Type '[number, string]' is not assignable to type 'number[]'. - Types of property 'pop' are incompatible. - Type '() => string | number' is not assignable to type '() => number'. - Type 'string | number' is not assignable to type 'number'. - Type 'string' is not assignable to type 'number'. + Types of property 'concat' are incompatible. + Type '{ (...items: ReadonlyArray[]): (string | number)[]; (...items: (string | number | ReadonlyArray)[]): (string | number)[]; }' is not assignable to type '{ (...items: ReadonlyArray[]): number[]; (...items: (number | ReadonlyArray)[]): number[]; }'. + Type '(string | number)[]' is not assignable to type 'number[]'. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. tests/cases/compiler/tupleTypes.ts(49,1): error TS2322: Type '[number, {}]' is not assignable to type 'number[]'. - Types of property 'pop' are incompatible. - Type '() => number | {}' is not assignable to type '() => number'. - Type 'number | {}' is not assignable to type 'number'. - Type '{}' is not assignable to type 'number'. + Types of property 'concat' are incompatible. + Type '{ (...items: ReadonlyArray[]): (number | {})[]; (...items: (number | {} | ReadonlyArray)[]): (number | {})[]; }' is not assignable to type '{ (...items: ReadonlyArray[]): number[]; (...items: (number | ReadonlyArray)[]): number[]; }'. + Type '(number | {})[]' is not assignable to type 'number[]'. + Type 'number | {}' is not assignable to type 'number'. + Type '{}' is not assignable to type 'number'. tests/cases/compiler/tupleTypes.ts(50,1): error TS2322: Type '[number, number]' is not assignable to type '[number, string]'. Type 'number' is not assignable to type 'string'. tests/cases/compiler/tupleTypes.ts(51,1): error TS2322: Type '[number, {}]' is not assignable to type '[number, string]'. @@ -92,18 +94,20 @@ tests/cases/compiler/tupleTypes.ts(51,1): error TS2322: Type '[number, {}]' is n a = a1; // Error ~ !!! error TS2322: Type '[number, string]' is not assignable to type 'number[]'. -!!! error TS2322: Types of property 'pop' are incompatible. -!!! error TS2322: Type '() => string | number' is not assignable to type '() => number'. -!!! error TS2322: Type 'string | number' is not assignable to type 'number'. -!!! error TS2322: Type 'string' is not assignable to type 'number'. +!!! error TS2322: Types of property 'concat' are incompatible. +!!! error TS2322: Type '{ (...items: ReadonlyArray[]): (string | number)[]; (...items: (string | number | ReadonlyArray)[]): (string | number)[]; }' is not assignable to type '{ (...items: ReadonlyArray[]): number[]; (...items: (number | ReadonlyArray)[]): number[]; }'. +!!! error TS2322: Type '(string | number)[]' is not assignable to type 'number[]'. +!!! error TS2322: Type 'string | number' is not assignable to type 'number'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. a = a2; a = a3; // Error ~ !!! error TS2322: Type '[number, {}]' is not assignable to type 'number[]'. -!!! error TS2322: Types of property 'pop' are incompatible. -!!! error TS2322: Type '() => number | {}' is not assignable to type '() => number'. -!!! error TS2322: Type 'number | {}' is not assignable to type 'number'. -!!! error TS2322: Type '{}' is not assignable to type 'number'. +!!! error TS2322: Types of property 'concat' are incompatible. +!!! error TS2322: Type '{ (...items: ReadonlyArray[]): (number | {})[]; (...items: (number | {} | ReadonlyArray)[]): (number | {})[]; }' is not assignable to type '{ (...items: ReadonlyArray[]): number[]; (...items: (number | ReadonlyArray)[]): number[]; }'. +!!! error TS2322: Type '(number | {})[]' is not assignable to type 'number[]'. +!!! error TS2322: Type 'number | {}' is not assignable to type 'number'. +!!! error TS2322: Type '{}' is not assignable to type 'number'. a1 = a2; // Error ~~ !!! error TS2322: Type '[number, number]' is not assignable to type '[number, string]'. diff --git a/tests/baselines/reference/typeInferenceWithTupleType.errors.txt b/tests/baselines/reference/typeInferenceWithTupleType.errors.txt new file mode 100644 index 00000000000..9fba99de278 --- /dev/null +++ b/tests/baselines/reference/typeInferenceWithTupleType.errors.txt @@ -0,0 +1,31 @@ +tests/cases/conformance/types/tuple/typeInferenceWithTupleType.ts(16,9): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'never' has no compatible call signatures. + + +==== tests/cases/conformance/types/tuple/typeInferenceWithTupleType.ts (1 errors) ==== + function combine(x: T, y: U): [T, U] { + return [x, y]; + } + + var combineResult = combine("string", 10); + var combineEle1 = combineResult[0]; // string + var combineEle2 = combineResult[1]; // number + + function zip(array1: T[], array2: U[]): [[T, U]] { + if (array1.length != array2.length) { + return [[undefined, undefined]]; + } + var length = array1.length; + var zipResult: [[T, U]]; + for (var i = 0; i < length; ++i) { + zipResult.push([array1[i], array2[i]]); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'never' has no compatible call signatures. + } + return zipResult; + } + + var zipResult = zip(["foo", "bar"], [5, 6]); + var zipResultEle = zipResult[0]; // [string, number] + var zipResultEleEle = zipResult[0][0]; // string + + \ No newline at end of file diff --git a/tests/baselines/reference/typeInferenceWithTupleType.symbols b/tests/baselines/reference/typeInferenceWithTupleType.symbols index 6f3279db8c2..e28ea2571dd 100644 --- a/tests/baselines/reference/typeInferenceWithTupleType.symbols +++ b/tests/baselines/reference/typeInferenceWithTupleType.symbols @@ -70,9 +70,9 @@ function zip(array1: T[], array2: U[]): [[T, U]] { >i : Symbol(i, Decl(typeInferenceWithTupleType.ts, 14, 12)) zipResult.push([array1[i], array2[i]]); ->zipResult.push : Symbol(Array.push, Decl(lib.d.ts, --, --)) +>zipResult.push : Symbol(TupleBase.push, Decl(lib.d.ts, --, --)) >zipResult : Symbol(zipResult, Decl(typeInferenceWithTupleType.ts, 13, 7)) ->push : Symbol(Array.push, Decl(lib.d.ts, --, --)) +>push : Symbol(TupleBase.push, Decl(lib.d.ts, --, --)) >array1 : Symbol(array1, Decl(typeInferenceWithTupleType.ts, 8, 19)) >i : Symbol(i, Decl(typeInferenceWithTupleType.ts, 14, 12)) >array2 : Symbol(array2, Decl(typeInferenceWithTupleType.ts, 8, 31)) diff --git a/tests/baselines/reference/typeInferenceWithTupleType.types b/tests/baselines/reference/typeInferenceWithTupleType.types index a7f8bff6798..e546a127758 100644 --- a/tests/baselines/reference/typeInferenceWithTupleType.types +++ b/tests/baselines/reference/typeInferenceWithTupleType.types @@ -82,11 +82,11 @@ function zip(array1: T[], array2: U[]): [[T, U]] { >i : number zipResult.push([array1[i], array2[i]]); ->zipResult.push([array1[i], array2[i]]) : number ->zipResult.push : (...items: [T, U][]) => number +>zipResult.push([array1[i], array2[i]]) : any +>zipResult.push : never >zipResult : [[T, U]] ->push : (...items: [T, U][]) => number ->[array1[i], array2[i]] : [T, U] +>push : never +>[array1[i], array2[i]] : (T | U)[] >array1[i] : T >array1 : T[] >i : number diff --git a/tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts b/tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts index 85a035d472b..ebd7738125e 100644 --- a/tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts +++ b/tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts @@ -1,4 +1,4 @@ -interface StrNum extends Array { +interface StrNum extends TupleBase { 0: string; 1: number; length: 2; From 2a4519eb0f276763b3c01d78c09fc69da609f4ff Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 6 Nov 2017 16:22:30 -0800 Subject: [PATCH 18/73] Remove last bits of strictTuples flag --- src/harness/unittests/configurationExtension.ts | 6 ------ src/harness/unittests/transpile.ts | 4 ---- src/server/protocol.ts | 1 - tests/baselines/reference/api/tsserverlibrary.d.ts | 1 - 4 files changed, 12 deletions(-) diff --git a/src/harness/unittests/configurationExtension.ts b/src/harness/unittests/configurationExtension.ts index b5a9d105cc3..0032505aba1 100644 --- a/src/harness/unittests/configurationExtension.ts +++ b/src/harness/unittests/configurationExtension.ts @@ -16,12 +16,6 @@ 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 dbad72a71a0..16bef6500f2 100644 --- a/src/harness/unittests/transpile.ts +++ b/src/harness/unittests/transpile.ts @@ -410,10 +410,6 @@ 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 a55aea9eaa7..93d5c69d361 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -2542,7 +2542,6 @@ 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/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index eb25861eb68..95800d82c2e 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -6850,7 +6850,6 @@ declare namespace ts.server.protocol { sourceRoot?: string; strict?: boolean; strictNullChecks?: boolean; - strictTuples?: boolean; suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; target?: ScriptTarget | ts.ScriptTarget; From 9a415a2b23fa26e1f997580718ea41948b51f7ce Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 7 Nov 2017 09:50:17 -0800 Subject: [PATCH 19/73] DefinitelyRunner cleanup and speedup 1. Only `npm install` packages with a package.json 2. Add `workingDirectory` to runnerBase to differentiate input directory from output directory (which should be different for definitelyRunner). 3. Don't output anything on success. --- src/harness/definitelyRunner.ts | 20 +++++++++++++------- src/harness/parallel/host.ts | 8 ++++---- src/harness/runnerbase.ts | 3 +++ 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/harness/definitelyRunner.ts b/src/harness/definitelyRunner.ts index afd39b72424..c2f7a04d3e7 100644 --- a/src/harness/definitelyRunner.ts +++ b/src/harness/definitelyRunner.ts @@ -2,8 +2,11 @@ /// class DefinitelyTypedRunner extends RunnerBase { private static readonly testDir = "../DefinitelyTyped/types/"; + + public workingDirectory = DefinitelyTypedRunner.testDir; + public enumerateTestFiles() { - return Harness.IO.getDirectories(DefinitelyTypedRunner.testDir).map(dir => DefinitelyTypedRunner.testDir + dir); + return Harness.IO.getDirectories(DefinitelyTypedRunner.testDir); } public kind(): TestRunnerKind { @@ -28,16 +31,19 @@ class DefinitelyTypedRunner extends RunnerBase { describe(directoryName, () => { const cp = require("child_process"); const path = require("path"); + const fs = require("fs"); it("should build successfully", () => { - const cwd = path.join(__dirname, "../../", directoryName); + const cwd = path.join(__dirname, "../../", DefinitelyTypedRunner.testDir, directoryName); const timeout = 600000; // 600s = 10 minutes - const stdio = isWorker ? "pipe" : "inherit"; - const install = cp.spawnSync(`npm`, ["i"], { cwd, timeout, shell: true, stdio }); - if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed!`); + if (fs.existsSync(path.join(cwd, 'package.json'))) { + const stdio = isWorker ? "pipe" : "inherit"; + const install = cp.spawnSync(`npm`, ["i"], { cwd, timeout, shell: true, stdio }); + if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed!`); + } Harness.Baseline.runBaseline(`${this.kind()}/${directoryName}.log`, () => { - const result = cp.spawnSync(`node`, [path.join(__dirname, "tsc.js"), "--lib dom,es6", "--strict"], { cwd, timeout, shell: true }); - return `Exit Code: ${result.status} + const result = cp.spawnSync(`node`, [path.join(__dirname, "tsc.js")], { cwd, timeout, shell: true }); + return result.status === 0 ? null : `Exit Code: ${result.status} Standard output: ${result.stdout.toString().replace(/\r\n/g, "\n")} diff --git a/src/harness/parallel/host.ts b/src/harness/parallel/host.ts index f37a3b1099e..e278d267e1f 100644 --- a/src/harness/parallel/host.ts +++ b/src/harness/parallel/host.ts @@ -77,18 +77,18 @@ namespace Harness.Parallel.Host { console.log("Discovering runner-based tests..."); const discoverStart = +(new Date()); const { statSync }: { statSync(path: string): { size: number }; } = require("fs"); + const path: { join: (...args: string[]) => string } = require("path"); for (const runner of runners) { - const files = runner.enumerateTestFiles(); - for (const file of files) { + for (const file of runner.enumerateTestFiles()) { let size: number; if (!perfData) { try { - size = statSync(file).size; + size = statSync(path.join(runner.workingDirectory, file)).size; } catch { // May be a directory try { - size = Harness.IO.listFiles(file, /.*/g, { recursive: true }).reduce((acc, elem) => acc + statSync(elem).size, 0); + size = Harness.IO.listFiles(path.join(runner.workingDirectory, file), /.*/g, { recursive: true }).reduce((acc, elem) => acc + statSync(elem).size, 0); } catch { // Unknown test kind, just return 0 and let the historical analysis take over after one run diff --git a/src/harness/runnerbase.ts b/src/harness/runnerbase.ts index 42e625a897d..1f5b31db2d6 100644 --- a/src/harness/runnerbase.ts +++ b/src/harness/runnerbase.ts @@ -24,6 +24,9 @@ abstract class RunnerBase { abstract enumerateTestFiles(): string[]; + /** The working directory where tests are found. Needed for batch testing where the input path will differ from the output path inside baselines */ + public workingDirectory = ""; + /** Setup the runner's tests so that they are ready to be executed by the harness * The first test should be a describe/it block that sets up the harness's compiler instance appropriately */ From 2378ff32b1164388ec8c7d74872f3f8dee8d764a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 7 Nov 2017 10:45:42 -0800 Subject: [PATCH 20/73] Fix lint and allow null keyword --- src/harness/definitelyRunner.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/harness/definitelyRunner.ts b/src/harness/definitelyRunner.ts index c2f7a04d3e7..ca9f9137ca4 100644 --- a/src/harness/definitelyRunner.ts +++ b/src/harness/definitelyRunner.ts @@ -36,13 +36,14 @@ class DefinitelyTypedRunner extends RunnerBase { it("should build successfully", () => { const cwd = path.join(__dirname, "../../", DefinitelyTypedRunner.testDir, directoryName); const timeout = 600000; // 600s = 10 minutes - if (fs.existsSync(path.join(cwd, 'package.json'))) { + if (fs.existsSync(path.join(cwd, "package.json"))) { const stdio = isWorker ? "pipe" : "inherit"; const install = cp.spawnSync(`npm`, ["i"], { cwd, timeout, shell: true, stdio }); if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed!`); } Harness.Baseline.runBaseline(`${this.kind()}/${directoryName}.log`, () => { const result = cp.spawnSync(`node`, [path.join(__dirname, "tsc.js")], { cwd, timeout, shell: true }); + // tslint:disable:no-null-keyword return result.status === 0 ? null : `Exit Code: ${result.status} Standard output: ${result.stdout.toString().replace(/\r\n/g, "\n")} @@ -50,6 +51,7 @@ ${result.stdout.toString().replace(/\r\n/g, "\n")} Standard error: ${result.stderr.toString().replace(/\r\n/g, "\n")}`; + // tslint:enable:no-null-keyword }); }); }); From 88a31d60967d86fd8107f630e4575b5d75048661 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 7 Nov 2017 10:57:54 -0800 Subject: [PATCH 21/73] Change runner name from 'definitely' to 'dt' --- Jakefile.js | 2 +- src/harness/{definitelyRunner.ts => dtRunner.ts} | 2 +- src/harness/runner.ts | 6 +++--- src/harness/runnerbase.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) rename src/harness/{definitelyRunner.ts => dtRunner.ts} (96%) diff --git a/Jakefile.js b/Jakefile.js index 40520e79a4a..a133d0dba32 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -106,7 +106,7 @@ var harnessCoreSources = [ "loggedIO.ts", "rwcRunner.ts", "userRunner.ts", - "definitelyRunner.ts", + "dtRunner.ts", "test262Runner.ts", "./parallel/shared.ts", "./parallel/host.ts", diff --git a/src/harness/definitelyRunner.ts b/src/harness/dtRunner.ts similarity index 96% rename from src/harness/definitelyRunner.ts rename to src/harness/dtRunner.ts index ca9f9137ca4..1da07b92d86 100644 --- a/src/harness/definitelyRunner.ts +++ b/src/harness/dtRunner.ts @@ -10,7 +10,7 @@ class DefinitelyTypedRunner extends RunnerBase { } public kind(): TestRunnerKind { - return "definitely"; + return "dt"; } /** Setup the runner's tests so that they are ready to be executed by the harness diff --git a/src/harness/runner.ts b/src/harness/runner.ts index fb66e74b958..0a9a7d3428d 100644 --- a/src/harness/runner.ts +++ b/src/harness/runner.ts @@ -19,7 +19,7 @@ /// /// /// -/// +/// /// /// @@ -63,7 +63,7 @@ function createRunner(kind: TestRunnerKind): RunnerBase { return new Test262BaselineRunner(); case "user": return new UserCodeRunner(); - case "definitely": + case "dt": return new DefinitelyTypedRunner(); } ts.Debug.fail(`Unknown runner kind ${kind}`); @@ -186,7 +186,7 @@ function handleTestConfig() { case "user": runners.push(new UserCodeRunner()); break; - case "definitely": + case "dt": runners.push(new DefinitelyTypedRunner()); break; } diff --git a/src/harness/runnerbase.ts b/src/harness/runnerbase.ts index 1f5b31db2d6..2858738f4b5 100644 --- a/src/harness/runnerbase.ts +++ b/src/harness/runnerbase.ts @@ -1,7 +1,7 @@ /// -type TestRunnerKind = CompilerTestKind | FourslashTestKind | "project" | "rwc" | "test262" | "user" | "definitely"; +type TestRunnerKind = CompilerTestKind | FourslashTestKind | "project" | "rwc" | "test262" | "user" | "dt"; type CompilerTestKind = "conformance" | "compiler"; type FourslashTestKind = "fourslash" | "fourslash-shims" | "fourslash-shims-pp" | "fourslash-server"; From 5e5b5652ed8437eac908f40a1ac91e2f55a04761 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 7 Nov 2017 11:10:24 -0800 Subject: [PATCH 22/73] Remove package-lock.json before `npm install` --- src/harness/dtRunner.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/harness/dtRunner.ts b/src/harness/dtRunner.ts index 1da07b92d86..3b739b28f1c 100644 --- a/src/harness/dtRunner.ts +++ b/src/harness/dtRunner.ts @@ -37,6 +37,9 @@ class DefinitelyTypedRunner extends RunnerBase { const cwd = path.join(__dirname, "../../", DefinitelyTypedRunner.testDir, directoryName); const timeout = 600000; // 600s = 10 minutes if (fs.existsSync(path.join(cwd, "package.json"))) { + if (fs.existsSync(path.join(cwd, "package-lock.json"))) { + fs.unlinkSync(path.join(cwd, "package-lock.json")); + } const stdio = isWorker ? "pipe" : "inherit"; const install = cp.spawnSync(`npm`, ["i"], { cwd, timeout, shell: true, stdio }); if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed!`); From ad18bde92bbe4307f0a2b245cc0ecd0f89fcf671 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 7 Nov 2017 15:43:55 -0800 Subject: [PATCH 23/73] RWC:Handle lib entries in tsconfig --- src/harness/harness.ts | 4 ++-- src/harness/rwcRunner.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/harness/harness.ts b/src/harness/harness.ts index abec41ea4a4..338ca6bb087 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -2146,8 +2146,8 @@ namespace Harness { return filePath.indexOf(Harness.libFolder) === 0; } - export function getDefaultLibraryFile(io: Harness.Io): Harness.Compiler.TestFile { - const libFile = Harness.userSpecifiedRoot + Harness.libFolder + Harness.Compiler.defaultLibFileName; + export function getDefaultLibraryFile(libPath: string, io: Harness.Io): Harness.Compiler.TestFile { + const libFile = Harness.userSpecifiedRoot + Harness.libFolder + libPath.slice(io.directoryName(libPath).length + 1); return { unitName: libFile, content: io.readFile(libFile) }; } diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index af6e8c95c5c..5613848b8e0 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -131,7 +131,7 @@ namespace RWC { } else { // set the flag to put default library to the beginning of the list - inputFiles.unshift(Harness.getDefaultLibraryFile(oldIO)); + inputFiles.unshift(Harness.getDefaultLibraryFile(fileRead.path, oldIO)); } } } From 4e4f7507d09699f26b3884254e208d1e7966442f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 7 Nov 2017 16:08:57 -0800 Subject: [PATCH 24/73] Fix getDefaultLibraryFile + turn off lib 1. getDefaultLibraryFile should use ts to normalise the file and find the filename. 2. lib should be turned off at the same time that noLib is turned on to avoid a pointless error. --- src/harness/harness.ts | 4 ++-- src/harness/rwcRunner.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 338ca6bb087..8a3202b88be 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -2146,8 +2146,8 @@ namespace Harness { return filePath.indexOf(Harness.libFolder) === 0; } - export function getDefaultLibraryFile(libPath: string, io: Harness.Io): Harness.Compiler.TestFile { - const libFile = Harness.userSpecifiedRoot + Harness.libFolder + libPath.slice(io.directoryName(libPath).length + 1); + export function getDefaultLibraryFile(filePath: string, io: Harness.Io): Harness.Compiler.TestFile { + const libFile = Harness.userSpecifiedRoot + Harness.libFolder + ts.getBaseFileName(ts.normalizeSlashes(filePath)); return { unitName: libFile, content: io.readFile(libFile) }; } diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index 5613848b8e0..ef7a371b0c4 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -138,6 +138,7 @@ namespace RWC { } // do not use lib since we already read it in above + opts.options.lib = undefined; opts.options.noLib = true; // Emit the results From ef6f9351b5ec2fb5c2a2664e60ba35903b51bd43 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 8 Nov 2017 09:40:53 -0800 Subject: [PATCH 25/73] Fix undefined error for diagnostic for instantiating an abstract class (#19809) * Fix undefined error for diagnostic for instantiating an abstract class * Only use the name-less diagnostic --- src/compiler/checker.ts | 2 +- src/compiler/diagnosticMessages.json | 2 +- ...ractClassInLocalScopeIsAbstract.errors.txt | 4 +-- ...bstractConstructorAssignability.errors.txt | 4 +-- .../classAbstractFactoryFunction.errors.txt | 4 +-- ...lassAbstractImportInstantiation.errors.txt | 8 ++--- .../classAbstractInAModule.errors.txt | 4 +-- .../classAbstractInstantiations1.errors.txt | 12 +++---- .../classAbstractInstantiations2.errors.txt | 12 +++---- .../classAbstractMergedDeclaration.errors.txt | 32 +++++++++---------- .../classAbstractSingleLineDecl.errors.txt | 4 +-- ...assAbstractUsingAbstractMethod1.errors.txt | 4 +-- .../reference/newAbstractInstance2.errors.txt | 12 +++++++ .../reference/newAbstractInstance2.js | 24 ++++++++++++++ .../reference/newAbstractInstance2.symbols | 10 ++++++ .../reference/newAbstractInstance2.types | 11 +++++++ tests/cases/compiler/newAbstractInstance2.ts | 6 ++++ 17 files changed, 109 insertions(+), 46 deletions(-) create mode 100644 tests/baselines/reference/newAbstractInstance2.errors.txt create mode 100644 tests/baselines/reference/newAbstractInstance2.js create mode 100644 tests/baselines/reference/newAbstractInstance2.symbols create mode 100644 tests/baselines/reference/newAbstractInstance2.types create mode 100644 tests/cases/compiler/newAbstractInstance2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8fa4429f7fd..21ae2369a41 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16726,7 +16726,7 @@ namespace ts { // only the class declaration node will have the Abstract flag set. const valueDecl = expressionType.symbol && getClassLikeDeclarationOfSymbol(expressionType.symbol); if (valueDecl && hasModifier(valueDecl, ModifierFlags.Abstract)) { - error(node, Diagnostics.Cannot_create_an_instance_of_the_abstract_class_0, declarationNameToString(getNameOfDeclaration(valueDecl))); + error(node, Diagnostics.Cannot_create_an_instance_of_an_abstract_class); return resolveErrorCall(node); } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 60e3d6c4c4f..0eb3959fd3c 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1716,7 +1716,7 @@ "category": "Error", "code": 2510 }, - "Cannot create an instance of the abstract class '{0}'.": { + "Cannot create an instance of an abstract class.": { "category": "Error", "code": 2511 }, diff --git a/tests/baselines/reference/abstractClassInLocalScopeIsAbstract.errors.txt b/tests/baselines/reference/abstractClassInLocalScopeIsAbstract.errors.txt index f5c5b417ea3..fa02cb21d34 100644 --- a/tests/baselines/reference/abstractClassInLocalScopeIsAbstract.errors.txt +++ b/tests/baselines/reference/abstractClassInLocalScopeIsAbstract.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/abstractClassInLocalScopeIsAbstract.ts(4,5): error TS2511: Cannot create an instance of the abstract class 'A'. +tests/cases/compiler/abstractClassInLocalScopeIsAbstract.ts(4,5): error TS2511: Cannot create an instance of an abstract class. ==== tests/cases/compiler/abstractClassInLocalScopeIsAbstract.ts (1 errors) ==== @@ -7,7 +7,7 @@ tests/cases/compiler/abstractClassInLocalScopeIsAbstract.ts(4,5): error TS2511: class B extends A {} new A(); ~~~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'A'. +!!! error TS2511: Cannot create an instance of an abstract class. new B(); })() \ No newline at end of file diff --git a/tests/baselines/reference/classAbstractConstructorAssignability.errors.txt b/tests/baselines/reference/classAbstractConstructorAssignability.errors.txt index 0f834665346..3ad45cc2b04 100644 --- a/tests/baselines/reference/classAbstractConstructorAssignability.errors.txt +++ b/tests/baselines/reference/classAbstractConstructorAssignability.errors.txt @@ -2,7 +2,7 @@ tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbst Cannot assign an abstract constructor type to a non-abstract constructor type. tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractConstructorAssignability.ts(9,5): error TS2322: Type 'typeof B' is not assignable to type 'typeof C'. Cannot assign an abstract constructor type to a non-abstract constructor type. -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractConstructorAssignability.ts(12,1): error TS2511: Cannot create an instance of the abstract class 'B'. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractConstructorAssignability.ts(12,1): error TS2511: Cannot create an instance of an abstract class. ==== tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractConstructorAssignability.ts (3 errors) ==== @@ -25,5 +25,5 @@ tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbst new AA; new BB; ~~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'B'. +!!! error TS2511: Cannot create an instance of an abstract class. new CC; \ No newline at end of file diff --git a/tests/baselines/reference/classAbstractFactoryFunction.errors.txt b/tests/baselines/reference/classAbstractFactoryFunction.errors.txt index 1b281f35260..2e7b3ad8f46 100644 --- a/tests/baselines/reference/classAbstractFactoryFunction.errors.txt +++ b/tests/baselines/reference/classAbstractFactoryFunction.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractFactoryFunction.ts(9,12): error TS2511: Cannot create an instance of the abstract class 'B'. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractFactoryFunction.ts(9,12): error TS2511: Cannot create an instance of an abstract class. tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractFactoryFunction.ts(13,6): error TS2345: Argument of type 'typeof B' is not assignable to parameter of type 'typeof A'. Cannot assign an abstract constructor type to a non-abstract constructor type. @@ -14,7 +14,7 @@ tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbst function NewB(Factory: typeof B) { return new B; ~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'B'. +!!! error TS2511: Cannot create an instance of an abstract class. } NewA(A); diff --git a/tests/baselines/reference/classAbstractImportInstantiation.errors.txt b/tests/baselines/reference/classAbstractImportInstantiation.errors.txt index 76110afa4ff..a01c75b6dae 100644 --- a/tests/baselines/reference/classAbstractImportInstantiation.errors.txt +++ b/tests/baselines/reference/classAbstractImportInstantiation.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractImportInstantiation.ts(4,5): error TS2511: Cannot create an instance of the abstract class 'A'. -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractImportInstantiation.ts(9,1): error TS2511: Cannot create an instance of the abstract class 'A'. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractImportInstantiation.ts(4,5): error TS2511: Cannot create an instance of an abstract class. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractImportInstantiation.ts(9,1): error TS2511: Cannot create an instance of an abstract class. ==== tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractImportInstantiation.ts (2 errors) ==== @@ -8,12 +8,12 @@ tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbst new A; ~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'A'. +!!! error TS2511: Cannot create an instance of an abstract class. } import myA = M.A; new myA; ~~~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'A'. +!!! error TS2511: Cannot create an instance of an abstract class. \ No newline at end of file diff --git a/tests/baselines/reference/classAbstractInAModule.errors.txt b/tests/baselines/reference/classAbstractInAModule.errors.txt index 426da866087..18bb6d4391e 100644 --- a/tests/baselines/reference/classAbstractInAModule.errors.txt +++ b/tests/baselines/reference/classAbstractInAModule.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInAModule.ts(6,1): error TS2511: Cannot create an instance of the abstract class 'A'. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInAModule.ts(6,1): error TS2511: Cannot create an instance of an abstract class. ==== tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInAModule.ts (1 errors) ==== @@ -9,5 +9,5 @@ tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbst new M.A; ~~~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'A'. +!!! error TS2511: Cannot create an instance of an abstract class. new M.B; \ No newline at end of file diff --git a/tests/baselines/reference/classAbstractInstantiations1.errors.txt b/tests/baselines/reference/classAbstractInstantiations1.errors.txt index d1c159858a4..bc696ce19db 100644 --- a/tests/baselines/reference/classAbstractInstantiations1.errors.txt +++ b/tests/baselines/reference/classAbstractInstantiations1.errors.txt @@ -1,6 +1,6 @@ -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations1.ts(11,1): error TS2511: Cannot create an instance of the abstract class 'A'. -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations1.ts(12,1): error TS2511: Cannot create an instance of the abstract class 'A'. -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations1.ts(14,1): error TS2511: Cannot create an instance of the abstract class 'C'. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations1.ts(11,1): error TS2511: Cannot create an instance of an abstract class. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations1.ts(12,1): error TS2511: Cannot create an instance of an abstract class. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations1.ts(14,1): error TS2511: Cannot create an instance of an abstract class. ==== tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations1.ts (3 errors) ==== @@ -16,14 +16,14 @@ tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbst new A; ~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'A'. +!!! error TS2511: Cannot create an instance of an abstract class. new A(1); // should report 1 error ~~~~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'A'. +!!! error TS2511: Cannot create an instance of an abstract class. new B; new C; ~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'C'. +!!! error TS2511: Cannot create an instance of an abstract class. var a : A; var b : B; diff --git a/tests/baselines/reference/classAbstractInstantiations2.errors.txt b/tests/baselines/reference/classAbstractInstantiations2.errors.txt index 15b63a6d3e8..d05e05517b2 100644 --- a/tests/baselines/reference/classAbstractInstantiations2.errors.txt +++ b/tests/baselines/reference/classAbstractInstantiations2.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations2.ts(10,1): error TS2511: Cannot create an instance of the abstract class 'B'. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations2.ts(10,1): error TS2511: Cannot create an instance of an abstract class. tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations2.ts(13,5): error TS2322: Type 'typeof B' is not assignable to type 'typeof A'. Cannot assign an abstract constructor type to a non-abstract constructor type. -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations2.ts(17,5): error TS2511: Cannot create an instance of the abstract class 'B'. -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations2.ts(21,1): error TS2511: Cannot create an instance of the abstract class 'B'. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations2.ts(17,5): error TS2511: Cannot create an instance of an abstract class. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations2.ts(21,1): error TS2511: Cannot create an instance of an abstract class. tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations2.ts(23,15): error TS2449: Class 'C' used before its declaration. tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations2.ts(26,7): error TS2515: Non-abstract class 'C' does not implement inherited abstract member 'bar' from class 'B'. tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations2.ts(46,5): error TS2391: Function implementation is missing or not immediately following the declaration. @@ -22,7 +22,7 @@ tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbst new B; // error ~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'B'. +!!! error TS2511: Cannot create an instance of an abstract class. var BB: typeof B = B; var AA: typeof A = BB; // error, AA is not of abstract type. @@ -34,13 +34,13 @@ tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbst function constructB(Factory : typeof B) { new Factory; // error -- Factory is of type typeof B. ~~~~~~~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'B'. +!!! error TS2511: Cannot create an instance of an abstract class. } var BB = B; new BB; // error -- BB is of type typeof B. ~~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'B'. +!!! error TS2511: Cannot create an instance of an abstract class. var x : any = C; ~ diff --git a/tests/baselines/reference/classAbstractMergedDeclaration.errors.txt b/tests/baselines/reference/classAbstractMergedDeclaration.errors.txt index 3e18d8796fb..fc15ca410e8 100644 --- a/tests/baselines/reference/classAbstractMergedDeclaration.errors.txt +++ b/tests/baselines/reference/classAbstractMergedDeclaration.errors.txt @@ -6,14 +6,14 @@ tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbst tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(26,15): error TS2300: Duplicate identifier 'DCC1'. tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(28,15): error TS2300: Duplicate identifier 'DCC2'. tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(29,24): error TS2300: Duplicate identifier 'DCC2'. -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(31,1): error TS2511: Cannot create an instance of the abstract class 'CM'. -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(32,1): error TS2511: Cannot create an instance of the abstract class 'MC'. -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(33,1): error TS2511: Cannot create an instance of the abstract class 'CI'. -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(34,1): error TS2511: Cannot create an instance of the abstract class 'IC'. -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(35,1): error TS2511: Cannot create an instance of the abstract class 'CC1'. -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(37,1): error TS2511: Cannot create an instance of the abstract class 'DCI'. -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(38,1): error TS2511: Cannot create an instance of the abstract class 'DIC'. -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(39,1): error TS2511: Cannot create an instance of the abstract class 'DCC1'. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(31,1): error TS2511: Cannot create an instance of an abstract class. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(32,1): error TS2511: Cannot create an instance of an abstract class. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(33,1): error TS2511: Cannot create an instance of an abstract class. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(34,1): error TS2511: Cannot create an instance of an abstract class. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(35,1): error TS2511: Cannot create an instance of an abstract class. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(37,1): error TS2511: Cannot create an instance of an abstract class. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(38,1): error TS2511: Cannot create an instance of an abstract class. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts(39,1): error TS2511: Cannot create an instance of an abstract class. ==== tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMergedDeclaration.ts (16 errors) ==== @@ -65,27 +65,27 @@ tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbst new CM; ~~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'CM'. +!!! error TS2511: Cannot create an instance of an abstract class. new MC; ~~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'MC'. +!!! error TS2511: Cannot create an instance of an abstract class. new CI; ~~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'CI'. +!!! error TS2511: Cannot create an instance of an abstract class. new IC; ~~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'IC'. +!!! error TS2511: Cannot create an instance of an abstract class. new CC1; ~~~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'CC1'. +!!! error TS2511: Cannot create an instance of an abstract class. new CC2; new DCI; ~~~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'DCI'. +!!! error TS2511: Cannot create an instance of an abstract class. new DIC; ~~~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'DIC'. +!!! error TS2511: Cannot create an instance of an abstract class. new DCC1; ~~~~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'DCC1'. +!!! error TS2511: Cannot create an instance of an abstract class. new DCC2; \ No newline at end of file diff --git a/tests/baselines/reference/classAbstractSingleLineDecl.errors.txt b/tests/baselines/reference/classAbstractSingleLineDecl.errors.txt index 0670ea108ea..1bdabfefe6d 100644 --- a/tests/baselines/reference/classAbstractSingleLineDecl.errors.txt +++ b/tests/baselines/reference/classAbstractSingleLineDecl.errors.txt @@ -1,6 +1,6 @@ tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractSingleLineDecl.ts(3,1): error TS2304: Cannot find name 'abstract'. tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractSingleLineDecl.ts(6,1): error TS2304: Cannot find name 'abstract'. -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractSingleLineDecl.ts(10,1): error TS2511: Cannot create an instance of the abstract class 'A'. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractSingleLineDecl.ts(10,1): error TS2511: Cannot create an instance of an abstract class. ==== tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractSingleLineDecl.ts (3 errors) ==== @@ -19,6 +19,6 @@ tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbst new A; ~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'A'. +!!! error TS2511: Cannot create an instance of an abstract class. new B; new C; \ No newline at end of file diff --git a/tests/baselines/reference/classAbstractUsingAbstractMethod1.errors.txt b/tests/baselines/reference/classAbstractUsingAbstractMethod1.errors.txt index df3682a36af..282fa3a53aa 100644 --- a/tests/baselines/reference/classAbstractUsingAbstractMethod1.errors.txt +++ b/tests/baselines/reference/classAbstractUsingAbstractMethod1.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractUsingAbstractMethod1.ts(16,5): error TS2511: Cannot create an instance of the abstract class 'C'. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractUsingAbstractMethod1.ts(16,5): error TS2511: Cannot create an instance of an abstract class. ==== tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractUsingAbstractMethod1.ts (1 errors) ==== @@ -19,5 +19,5 @@ tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbst a = new C; // error, cannot instantiate abstract class. ~~~~~ -!!! error TS2511: Cannot create an instance of the abstract class 'C'. +!!! error TS2511: Cannot create an instance of an abstract class. a.foo(); \ No newline at end of file diff --git a/tests/baselines/reference/newAbstractInstance2.errors.txt b/tests/baselines/reference/newAbstractInstance2.errors.txt new file mode 100644 index 00000000000..2b2559cc932 --- /dev/null +++ b/tests/baselines/reference/newAbstractInstance2.errors.txt @@ -0,0 +1,12 @@ +/b.ts(2,1): error TS2511: Cannot create an instance of an abstract class. + + +==== /a.ts (0 errors) ==== + export default abstract class {} + +==== /b.ts (1 errors) ==== + import A from "./a"; + new A(); + ~~~~~~~ +!!! error TS2511: Cannot create an instance of an abstract class. + \ No newline at end of file diff --git a/tests/baselines/reference/newAbstractInstance2.js b/tests/baselines/reference/newAbstractInstance2.js new file mode 100644 index 00000000000..2be1012fcd5 --- /dev/null +++ b/tests/baselines/reference/newAbstractInstance2.js @@ -0,0 +1,24 @@ +//// [tests/cases/compiler/newAbstractInstance2.ts] //// + +//// [a.ts] +export default abstract class {} + +//// [b.ts] +import A from "./a"; +new A(); + + +//// [a.js] +"use strict"; +exports.__esModule = true; +var default_1 = /** @class */ (function () { + function default_1() { + } + return default_1; +}()); +exports["default"] = default_1; +//// [b.js] +"use strict"; +exports.__esModule = true; +var a_1 = require("./a"); +new a_1["default"](); diff --git a/tests/baselines/reference/newAbstractInstance2.symbols b/tests/baselines/reference/newAbstractInstance2.symbols new file mode 100644 index 00000000000..2ce91130095 --- /dev/null +++ b/tests/baselines/reference/newAbstractInstance2.symbols @@ -0,0 +1,10 @@ +=== /a.ts === +export default abstract class {} +No type information for this code. +No type information for this code.=== /b.ts === +import A from "./a"; +>A : Symbol(A, Decl(b.ts, 0, 6)) + +new A(); +>A : Symbol(A, Decl(b.ts, 0, 6)) + diff --git a/tests/baselines/reference/newAbstractInstance2.types b/tests/baselines/reference/newAbstractInstance2.types new file mode 100644 index 00000000000..8e980d90300 --- /dev/null +++ b/tests/baselines/reference/newAbstractInstance2.types @@ -0,0 +1,11 @@ +=== /a.ts === +export default abstract class {} +No type information for this code. +No type information for this code.=== /b.ts === +import A from "./a"; +>A : typeof A + +new A(); +>new A() : any +>A : typeof A + diff --git a/tests/cases/compiler/newAbstractInstance2.ts b/tests/cases/compiler/newAbstractInstance2.ts new file mode 100644 index 00000000000..a035ccabdcf --- /dev/null +++ b/tests/cases/compiler/newAbstractInstance2.ts @@ -0,0 +1,6 @@ +// @Filename: /a.ts +export default abstract class {} + +// @Filename: /b.ts +import A from "./a"; +new A(); From d73fb3acdd33712b7d6267e8fc11173596c3e07a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 8 Nov 2017 09:48:36 -0800 Subject: [PATCH 26/73] Narrow property access from string index signatures Previously these accesses did not use control flow to narrow property accesses of undefined properties that are resolved from a string index signature. Now the use control flow to narrow these just like normal properties. --- src/compiler/checker.ts | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7bce66892de..e2a419900c7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15221,7 +15221,7 @@ namespace ts { if (indexInfo.isReadonly && (isAssignmentTarget(node) || isDeleteTarget(node))) { error(node, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(apparentType)); } - return indexInfo.type; + return getFlowTypeOfPropertyAccess(node, /*prop*/ undefined, indexInfo.type, getAssignmentTargetKind(node)); } if (right.escapedText && !checkAndReportErrorForExtendingInterface(node)) { reportNonexistentProperty(right, type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType ? apparentType : type); @@ -15246,16 +15246,21 @@ namespace ts { return unknownType; } } + return getFlowTypeOfPropertyAccess(node, prop, propType, assignmentKind); + } - // Only compute control flow type if this is a property access expression that isn't an - // assignment target, and the referenced property was declared as a variable, property, - // accessor, or optional method. - if (node.kind !== SyntaxKind.PropertyAccessExpression || assignmentKind === AssignmentKind.Definite || - !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) && - !(prop.flags & SymbolFlags.Method && propType.flags & TypeFlags.Union)) { - return propType; + /** + * Only compute control flow type if this is a property access expression that isn't an + * assignment target, and the referenced property was declared as a variable, property, + * accessor, or optional method. + */ + function getFlowTypeOfPropertyAccess(node: PropertyAccessExpression | QualifiedName, prop: Symbol | undefined, type: Type, assignmentKind: AssignmentKind) { + if (node.kind !== SyntaxKind.PropertyAccessExpression || + assignmentKind === AssignmentKind.Definite || + prop && !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) && !(prop.flags & SymbolFlags.Method && type.flags & TypeFlags.Union)) { + return type; } - const flowType = getFlowTypeOfReference(node, propType); + const flowType = getFlowTypeOfReference(node, type); return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType; } From 6c74b81d7eeb67abf3f17cdcc9f1c858916bdd1f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 8 Nov 2017 09:50:39 -0800 Subject: [PATCH 27/73] Test:narrow properties from string index signatures --- .../reference/controlFlowStringIndex.js | 13 ++++++++++ .../reference/controlFlowStringIndex.symbols | 18 +++++++++++++ .../reference/controlFlowStringIndex.types | 26 +++++++++++++++++++ .../controlFlow/controlFlowStringIndex.ts | 6 +++++ 4 files changed, 63 insertions(+) create mode 100644 tests/baselines/reference/controlFlowStringIndex.js create mode 100644 tests/baselines/reference/controlFlowStringIndex.symbols create mode 100644 tests/baselines/reference/controlFlowStringIndex.types create mode 100644 tests/cases/conformance/controlFlow/controlFlowStringIndex.ts diff --git a/tests/baselines/reference/controlFlowStringIndex.js b/tests/baselines/reference/controlFlowStringIndex.js new file mode 100644 index 00000000000..456ae6afcd4 --- /dev/null +++ b/tests/baselines/reference/controlFlowStringIndex.js @@ -0,0 +1,13 @@ +//// [controlFlowStringIndex.ts] +type A = { [index: string]: number | null }; +declare const value: A; +if (value.foo !== null) { + value.foo.toExponential() +} + + +//// [controlFlowStringIndex.js] +"use strict"; +if (value.foo !== null) { + value.foo.toExponential(); +} diff --git a/tests/baselines/reference/controlFlowStringIndex.symbols b/tests/baselines/reference/controlFlowStringIndex.symbols new file mode 100644 index 00000000000..aad08e48a9b --- /dev/null +++ b/tests/baselines/reference/controlFlowStringIndex.symbols @@ -0,0 +1,18 @@ +=== tests/cases/conformance/controlFlow/controlFlowStringIndex.ts === +type A = { [index: string]: number | null }; +>A : Symbol(A, Decl(controlFlowStringIndex.ts, 0, 0)) +>index : Symbol(index, Decl(controlFlowStringIndex.ts, 0, 12)) + +declare const value: A; +>value : Symbol(value, Decl(controlFlowStringIndex.ts, 1, 13)) +>A : Symbol(A, Decl(controlFlowStringIndex.ts, 0, 0)) + +if (value.foo !== null) { +>value : Symbol(value, Decl(controlFlowStringIndex.ts, 1, 13)) + + value.foo.toExponential() +>value.foo.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>value : Symbol(value, Decl(controlFlowStringIndex.ts, 1, 13)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +} + diff --git a/tests/baselines/reference/controlFlowStringIndex.types b/tests/baselines/reference/controlFlowStringIndex.types new file mode 100644 index 00000000000..d1722dd6925 --- /dev/null +++ b/tests/baselines/reference/controlFlowStringIndex.types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/controlFlow/controlFlowStringIndex.ts === +type A = { [index: string]: number | null }; +>A : A +>index : string +>null : null + +declare const value: A; +>value : A +>A : A + +if (value.foo !== null) { +>value.foo !== null : boolean +>value.foo : number | null +>value : A +>foo : number | null +>null : null + + value.foo.toExponential() +>value.foo.toExponential() : string +>value.foo.toExponential : (fractionDigits?: number | undefined) => string +>value.foo : number +>value : A +>foo : number +>toExponential : (fractionDigits?: number | undefined) => string +} + diff --git a/tests/cases/conformance/controlFlow/controlFlowStringIndex.ts b/tests/cases/conformance/controlFlow/controlFlowStringIndex.ts new file mode 100644 index 00000000000..78acf6d654e --- /dev/null +++ b/tests/cases/conformance/controlFlow/controlFlowStringIndex.ts @@ -0,0 +1,6 @@ +// @strict: true +type A = { [index: string]: number | null }; +declare const value: A; +if (value.foo !== null) { + value.foo.toExponential() +} From 1a0ec81488b4fb4236f9bbfa25448eaf4e26d8db Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 8 Nov 2017 09:56:50 -0800 Subject: [PATCH 28/73] quickInfo: Display info for signature on a separate line from variable info (#18698) --- src/services/symbolDisplay.ts | 7 ++-- ...kInfoDisplayPartsInterfaceMembers.baseline | 16 ++++++-- ...playPartsTypeParameterInInterface.baseline | 32 +++++++++++---- tests/cases/fourslash/commentsInterface.ts | 4 +- tests/cases/fourslash/commentsOverloads.ts | 40 +++++++++---------- .../externalModuleWithExportAssignment.ts | 8 ++-- 6 files changed, 66 insertions(+), 41 deletions(-) diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index ad9ac88bdfc..fe04342b8f7 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -191,13 +191,14 @@ namespace ts.SymbolDisplay { // If it is call or construct signature of lambda's write type name displayParts.push(punctuationPart(SyntaxKind.ColonToken)); displayParts.push(spacePart()); + if (!(type.flags & TypeFlags.Object && (type).objectFlags & ObjectFlags.Anonymous) && type.symbol) { + addRange(displayParts, symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments)); + displayParts.push(lineBreakPart()); + } if (useConstructSignatures) { displayParts.push(keywordPart(SyntaxKind.NewKeyword)); displayParts.push(spacePart()); } - if (!(type.flags & TypeFlags.Object && (type).objectFlags & ObjectFlags.Anonymous) && type.symbol) { - addRange(displayParts, symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments)); - } addSignatureDisplayParts(signature, allSignatures, TypeFormatFlags.WriteArrowStyleSignature); break; diff --git a/tests/baselines/reference/quickInfoDisplayPartsInterfaceMembers.baseline b/tests/baselines/reference/quickInfoDisplayPartsInterfaceMembers.baseline index 732582d9190..fa1e5977dd5 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsInterfaceMembers.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsInterfaceMembers.baseline @@ -368,6 +368,10 @@ "text": "I", "kind": "interfaceName" }, + { + "text": "\n", + "kind": "lineBreak" + }, { "text": "(", "kind": "punctuation" @@ -472,6 +476,14 @@ "text": " ", "kind": "space" }, + { + "text": "I", + "kind": "interfaceName" + }, + { + "text": "\n", + "kind": "lineBreak" + }, { "text": "new", "kind": "keyword" @@ -480,10 +492,6 @@ "text": " ", "kind": "space" }, - { - "text": "I", - "kind": "interfaceName" - }, { "text": "(", "kind": "punctuation" diff --git a/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInInterface.baseline b/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInInterface.baseline index d48bb70f8ff..80da1f19ef9 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInInterface.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInInterface.baseline @@ -2058,6 +2058,14 @@ "text": " ", "kind": "space" }, + { + "text": "I", + "kind": "interfaceName" + }, + { + "text": "\n", + "kind": "lineBreak" + }, { "text": "new", "kind": "keyword" @@ -2066,10 +2074,6 @@ "text": " ", "kind": "space" }, - { - "text": "I", - "kind": "interfaceName" - }, { "text": "<", "kind": "punctuation" @@ -2188,6 +2192,10 @@ "text": "I", "kind": "interfaceName" }, + { + "text": "\n", + "kind": "lineBreak" + }, { "text": "<", "kind": "punctuation" @@ -5462,6 +5470,14 @@ "text": " ", "kind": "space" }, + { + "text": "I1", + "kind": "interfaceName" + }, + { + "text": "\n", + "kind": "lineBreak" + }, { "text": "new", "kind": "keyword" @@ -5470,10 +5486,6 @@ "text": " ", "kind": "space" }, - { - "text": "I1", - "kind": "interfaceName" - }, { "text": "<", "kind": "punctuation" @@ -5748,6 +5760,10 @@ "text": "I1", "kind": "interfaceName" }, + { + "text": "\n", + "kind": "lineBreak" + }, { "text": "<", "kind": "punctuation" diff --git a/tests/cases/fourslash/commentsInterface.ts b/tests/cases/fourslash/commentsInterface.ts index 7a09329a0fd..e2223326274 100644 --- a/tests/cases/fourslash/commentsInterface.ts +++ b/tests/cases/fourslash/commentsInterface.ts @@ -113,7 +113,7 @@ goTo.marker('16'); verify.currentSignatureHelpDocCommentIs("new method"); verify.currentParameterHelpArgumentDocCommentIs("param"); verify.quickInfos({ - "16q": ["var i2_i: new i2(i: i1) => any", "new method"], + "16q": ["var i2_i: i2\nnew (i: i1) => any", "new method"], 17: "var i2_i_nc_x: number", 18: "(property) i2.nc_x: number", @@ -133,7 +133,7 @@ verify.quickInfos({ goTo.marker('24'); verify.currentSignatureHelpDocCommentIs("this is call signature"); verify.currentParameterHelpArgumentDocCommentIs("paramhelp a"); -verify.quickInfoAt("24q", "var i2_i: i2(a: number, b: number) => number", "this is call signature"); +verify.quickInfoAt("24q", "var i2_i: i2\n(a: number, b: number) => number", "this is call signature"); goTo.marker('25'); verify.currentSignatureHelpDocCommentIs("this is call signature"); diff --git a/tests/cases/fourslash/commentsOverloads.ts b/tests/cases/fourslash/commentsOverloads.ts index 6add2609897..1068e1e6fe1 100644 --- a/tests/cases/fourslash/commentsOverloads.ts +++ b/tests/cases/fourslash/commentsOverloads.ts @@ -296,34 +296,34 @@ verify.completionListContains('f4', 'function f4(a: number): number (+1 overload goTo.marker('18'); verify.not.completionListContains('i1', 'interface i1', ''); -verify.completionListContains('i1_i', 'var i1_i: new i1(b: number) => any (+1 overload)', ''); +verify.completionListContains('i1_i', 'var i1_i: i1\nnew (b: number) => any (+1 overload)', ''); verify.not.completionListContains('i2', 'interface i2', ''); -verify.completionListContains('i2_i', 'var i2_i: new i2(a: string) => any (+1 overload)', ''); +verify.completionListContains('i2_i', 'var i2_i: i2\nnew (a: string) => any (+1 overload)', ''); verify.not.completionListContains('i3', 'interface i3', ''); -verify.completionListContains('i3_i', 'var i3_i: new i3(a: string) => any (+1 overload)', 'new 1'); +verify.completionListContains('i3_i', 'var i3_i: i3\nnew (a: string) => any (+1 overload)', 'new 1'); verify.not.completionListContains('i4', 'interface i4', ''); -verify.completionListContains('i4_i', 'var i4_i: new i4(a: string) => any (+1 overload)', ''); +verify.completionListContains('i4_i', 'var i4_i: i4\nnew (a: string) => any (+1 overload)', ''); goTo.marker('19'); verify.currentSignatureHelpDocCommentIs(""); verify.currentParameterHelpArgumentDocCommentIs(""); -verify.quickInfoAt("19q", "var i1_i: new i1(b: number) => any (+1 overload)"); +verify.quickInfoAt("19q", "var i1_i: i1\nnew (b: number) => any (+1 overload)"); goTo.marker('20'); verify.currentSignatureHelpDocCommentIs("new 1"); verify.currentParameterHelpArgumentDocCommentIs(""); -verify.quickInfoAt("20q", "var i1_i: new i1(a: string) => any (+1 overload)", "new 1"); +verify.quickInfoAt("20q", "var i1_i: i1\nnew (a: string) => any (+1 overload)", "new 1"); goTo.marker('21'); verify.currentSignatureHelpDocCommentIs("this signature 1"); verify.currentParameterHelpArgumentDocCommentIs("param a"); -verify.quickInfoAt("21q", "var i1_i: i1(a: number) => number (+1 overload)", "this signature 1"); +verify.quickInfoAt("21q", "var i1_i: i1\n(a: number) => number (+1 overload)", "this signature 1"); goTo.marker('22'); verify.currentSignatureHelpDocCommentIs("this is signature 2"); verify.currentParameterHelpArgumentDocCommentIs(""); goTo.marker('22q'); -verify.quickInfoAt("22q", "var i1_i: i1(b: string) => number (+1 overload)", "this is signature 2"); +verify.quickInfoAt("22q", "var i1_i: i1\n(b: string) => number (+1 overload)", "this is signature 2"); goTo.marker('23'); verify.completionListContains('foo', '(method) i1.foo(a: number): number (+1 overload)', 'foo 1'); @@ -374,62 +374,62 @@ verify.quickInfoAt("31q", "(method) i1.foo4(b: string): number (+1 overload)"); goTo.marker('32'); verify.currentSignatureHelpDocCommentIs("new 2"); verify.currentParameterHelpArgumentDocCommentIs(""); -verify.quickInfoAt("32q", "var i2_i: new i2(b: number) => any (+1 overload)", "new 2"); +verify.quickInfoAt("32q", "var i2_i: i2\nnew (b: number) => any (+1 overload)", "new 2"); goTo.marker('33'); verify.currentSignatureHelpDocCommentIs(""); verify.currentParameterHelpArgumentDocCommentIs(""); -verify.quickInfoAt("33q", "var i2_i: new i2(a: string) => any (+1 overload)"); +verify.quickInfoAt("33q", "var i2_i: i2\nnew (a: string) => any (+1 overload)"); goTo.marker('34'); verify.currentSignatureHelpDocCommentIs(""); verify.currentParameterHelpArgumentDocCommentIs(""); -verify.quickInfoAt("34q", "var i2_i: i2(a: number) => number (+1 overload)"); +verify.quickInfoAt("34q", "var i2_i: i2\n(a: number) => number (+1 overload)"); goTo.marker('35'); verify.currentSignatureHelpDocCommentIs("this is signature 2"); verify.currentParameterHelpArgumentDocCommentIs(""); -verify.quickInfoAt("35q", "var i2_i: i2(b: string) => number (+1 overload)", "this is signature 2"); +verify.quickInfoAt("35q", "var i2_i: i2\n(b: string) => number (+1 overload)", "this is signature 2"); goTo.marker('36'); verify.currentSignatureHelpDocCommentIs("new 2"); verify.currentParameterHelpArgumentDocCommentIs(""); -verify.quickInfoAt("36q", "var i3_i: new i3(b: number) => any (+1 overload)", "new 2"); +verify.quickInfoAt("36q", "var i3_i: i3\nnew (b: number) => any (+1 overload)", "new 2"); goTo.marker('37'); verify.currentSignatureHelpDocCommentIs("new 1"); verify.currentParameterHelpArgumentDocCommentIs(""); -verify.quickInfoAt("37q", "var i3_i: new i3(a: string) => any (+1 overload)", "new 1"); +verify.quickInfoAt("37q", "var i3_i: i3\nnew (a: string) => any (+1 overload)", "new 1"); goTo.marker('38'); verify.currentSignatureHelpDocCommentIs("this is signature 1"); verify.currentParameterHelpArgumentDocCommentIs(""); -verify.quickInfoAt("38q", "var i3_i: i3(a: number) => number (+1 overload)", "this is signature 1"); +verify.quickInfoAt("38q", "var i3_i: i3\n(a: number) => number (+1 overload)", "this is signature 1"); goTo.marker('39'); verify.currentSignatureHelpDocCommentIs(""); verify.currentParameterHelpArgumentDocCommentIs(""); -verify.quickInfoAt("39q", "var i3_i: i3(b: string) => number (+1 overload)"); +verify.quickInfoAt("39q", "var i3_i: i3\n(b: string) => number (+1 overload)"); goTo.marker('40'); verify.currentSignatureHelpDocCommentIs(""); verify.currentParameterHelpArgumentDocCommentIs(""); -verify.quickInfoAt("40q", "var i4_i: new i4(b: number) => any (+1 overload)"); +verify.quickInfoAt("40q", "var i4_i: i4\nnew (b: number) => any (+1 overload)"); goTo.marker('41'); verify.currentSignatureHelpDocCommentIs(""); verify.currentParameterHelpArgumentDocCommentIs(""); -verify.quickInfoAt("41q", "var i4_i: new i4(a: string) => any (+1 overload)"); +verify.quickInfoAt("41q", "var i4_i: i4\nnew (a: string) => any (+1 overload)"); goTo.marker('42'); verify.currentSignatureHelpDocCommentIs(""); verify.currentParameterHelpArgumentDocCommentIs(""); -verify.quickInfoAt("42q", "var i4_i: i4(a: number) => number (+1 overload)"); +verify.quickInfoAt("42q", "var i4_i: i4\n(a: number) => number (+1 overload)"); goTo.marker('43'); verify.currentSignatureHelpDocCommentIs(""); verify.currentParameterHelpArgumentDocCommentIs(""); -verify.quickInfoAt("43q", "var i4_i: i4(b: string) => number (+1 overload)"); +verify.quickInfoAt("43q", "var i4_i: i4\n(b: string) => number (+1 overload)"); goTo.marker('44'); verify.completionListContains('prop1', '(method) c.prop1(a: number): number (+1 overload)', ''); diff --git a/tests/cases/fourslash/externalModuleWithExportAssignment.ts b/tests/cases/fourslash/externalModuleWithExportAssignment.ts index 90009fe9d46..5b392623690 100644 --- a/tests/cases/fourslash/externalModuleWithExportAssignment.ts +++ b/tests/cases/fourslash/externalModuleWithExportAssignment.ts @@ -33,8 +33,8 @@ verify.quickInfoAt("1", 'import a1 = require("./externalModuleWithExportAssignme verify.quickInfoAt("2", "var a: {\n (): a1.connectExport;\n test1: a1.connectModule;\n test2(): a1.connectModule;\n}", undefined); goTo.marker('3'); -verify.quickInfoIs("(property) test1: a1.connectModule(res: any, req: any, next: any) => void", undefined); -verify.completionListContains("test1", "(property) test1: a1.connectModule(res: any, req: any, next: any) => void", undefined); +verify.quickInfoIs("(property) test1: a1.connectModule\n(res: any, req: any, next: any) => void", undefined); +verify.completionListContains("test1", "(property) test1: a1.connectModule\n(res: any, req: any, next: any) => void", undefined); verify.completionListContains("test2", "(method) test2(): a1.connectModule", undefined); verify.not.completionListContains("connectModule"); verify.not.completionListContains("connectExport"); @@ -53,8 +53,8 @@ verify.currentSignatureHelpIs("a(): a1.connectExport"); verify.quickInfoAt("8", "var r2: a1.connectExport", undefined); goTo.marker('9'); -verify.quickInfoIs("(property) test1: a1.connectModule(res: any, req: any, next: any) => void", undefined); -verify.completionListContains("test1", "(property) test1: a1.connectModule(res: any, req: any, next: any) => void", undefined); +verify.quickInfoIs("(property) test1: a1.connectModule\n(res: any, req: any, next: any) => void", undefined); +verify.completionListContains("test1", "(property) test1: a1.connectModule\n(res: any, req: any, next: any) => void", undefined); verify.completionListContains("test2", "(method) test2(): a1.connectModule", undefined); verify.not.completionListContains("connectModule"); verify.not.completionListContains("connectExport"); From a1da5bd5af7ab16c6a1910f2f20b9f3f72a2d888 Mon Sep 17 00:00:00 2001 From: Adrian Leonhard Date: Wed, 8 Nov 2017 19:02:39 +0100 Subject: [PATCH 29/73] Changed error for setter when emitting declaration with private param type (#18593) so that error message refers to prop name instead of param name. Changed getter errors for similar case so they also refer to prop name. Fixed bug where static getters wouldn't output their specific error. Fixes #1976 --- src/compiler/declarationEmitter.ts | 41 +++-- src/compiler/diagnosticMessages.json | 20 +-- ...otationVisibilityErrorAccessors.errors.txt | 44 +++--- ...eTypeAnnotationVisibilityErrorAccessors.js | 4 +- .../privacyAccessorDeclFile.errors.txt | 144 +++++++++--------- ...ivacyCannotNameAccessorDeclFile.errors.txt | 32 ++-- .../symbolDeclarationEmit12.errors.txt | 4 +- ...eTypeAnnotationVisibilityErrorAccessors.ts | 4 +- 8 files changed, 144 insertions(+), 149 deletions(-) diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 48b97b048e9..3276e68b2ac 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -1429,45 +1429,40 @@ namespace ts { function getAccessorDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { let diagnosticMessage: DiagnosticMessage; if (accessorWithTypeAnnotation.kind === SyntaxKind.SetAccessor) { - // Setters have to have type named and cannot infer it so, the type should always be named - if (hasModifier(accessorWithTypeAnnotation.parent, ModifierFlags.Static)) { + // Getters can infer the return type from the returned expression, but setters cannot, so the + // "_from_external_module_1_but_cannot_be_named" case cannot occur. + if (hasModifier(accessorWithTypeAnnotation, ModifierFlags.Static)) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1; + Diagnostics.Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_private_name_1; } else { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - Diagnostics.Parameter_0_of_public_property_setter_from_exported_class_has_or_is_using_private_name_1; + Diagnostics.Parameter_type_of_public_setter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Parameter_type_of_public_setter_0_from_exported_class_has_or_is_using_private_name_1; } - return { - diagnosticMessage, - errorNode: accessorWithTypeAnnotation.parameters[0], - // TODO(jfreeman): Investigate why we are passing node.name instead of node.parameters[0].name - typeName: accessorWithTypeAnnotation.name - }; } else { if (hasModifier(accessorWithTypeAnnotation, ModifierFlags.Static)) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 : - Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_private_name_0; + Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_private_name_1; } else { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? - Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_name_0_from_private_module_1 : - Diagnostics.Return_type_of_public_property_getter_from_exported_class_has_or_is_using_private_name_0; + Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_private_name_1; } - return { - diagnosticMessage, - errorNode: accessorWithTypeAnnotation.name, - typeName: undefined - }; } + return { + diagnosticMessage, + errorNode: accessorWithTypeAnnotation.name, + typeName: accessorWithTypeAnnotation.name + }; } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 0eb3959fd3c..964264ff6e8 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2321,43 +2321,43 @@ "category": "Error", "code": 4033 }, - "Parameter '{0}' of public static property setter from exported class has or is using name '{1}' from private module '{2}'.": { + "Parameter type of public static setter '{0}' from exported class has or is using name '{1}' from private module '{2}'.": { "category": "Error", "code": 4034 }, - "Parameter '{0}' of public static property setter from exported class has or is using private name '{1}'.": { + "Parameter type of public static setter '{0}' from exported class has or is using private name '{1}'.": { "category": "Error", "code": 4035 }, - "Parameter '{0}' of public property setter from exported class has or is using name '{1}' from private module '{2}'.": { + "Parameter type of public setter '{0}' from exported class has or is using name '{1}' from private module '{2}'.": { "category": "Error", "code": 4036 }, - "Parameter '{0}' of public property setter from exported class has or is using private name '{1}'.": { + "Parameter type of public setter '{0}' from exported class has or is using private name '{1}'.": { "category": "Error", "code": 4037 }, - "Return type of public static property getter from exported class has or is using name '{0}' from external module {1} but cannot be named.": { + "Return type of public static getter '{0}' from exported class has or is using name '{1}' from external module {2} but cannot be named.": { "category": "Error", "code": 4038 }, - "Return type of public static property getter from exported class has or is using name '{0}' from private module '{1}'.": { + "Return type of public static getter '{0}' from exported class has or is using name '{1}' from private module '{2}'.": { "category": "Error", "code": 4039 }, - "Return type of public static property getter from exported class has or is using private name '{0}'.": { + "Return type of public static getter '{0}' from exported class has or is using private name '{1}'.": { "category": "Error", "code": 4040 }, - "Return type of public property getter from exported class has or is using name '{0}' from external module {1} but cannot be named.": { + "Return type of public getter '{0}' from exported class has or is using name '{1}' from external module {2} but cannot be named.": { "category": "Error", "code": 4041 }, - "Return type of public property getter from exported class has or is using name '{0}' from private module '{1}'.": { + "Return type of public getter '{0}' from exported class has or is using name '{1}' from private module '{2}'.": { "category": "Error", "code": 4042 }, - "Return type of public property getter from exported class has or is using private name '{0}'.": { + "Return type of public getter '{0}' from exported class has or is using private name '{1}'.": { "category": "Error", "code": 4043 }, diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.errors.txt b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.errors.txt index 771960ba788..4ea18c15901 100644 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.errors.txt +++ b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.errors.txt @@ -1,13 +1,13 @@ -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(15,21): error TS4043: Return type of public property getter from exported class has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(20,13): error TS4043: Return type of public property getter from exported class has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(25,25): error TS4037: Parameter 'foo3' of public property setter from exported class has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(32,25): error TS4037: Parameter 'foo4' of public property setter from exported class has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(36,21): error TS4043: Return type of public property getter from exported class has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(71,23): error TS4043: Return type of public property getter from exported class has or is using private name 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(76,13): error TS4042: Return type of public property getter from exported class has or is using name 'm2.public2' from private module 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(81,27): error TS4037: Parameter 'foo113' of public property setter from exported class has or is using private name 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(88,27): error TS4037: Parameter 'foo114' of public property setter from exported class has or is using private name 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(92,23): error TS4043: Return type of public property getter from exported class has or is using private name 'm2'. +tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(15,21): error TS4043: Return type of public getter 'foo1' from exported class has or is using private name 'private1'. +tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(20,13): error TS4043: Return type of public getter 'foo2' from exported class has or is using private name 'private1'. +tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(25,25): error TS4037: Parameter type of public setter 'foo3' from exported class has or is using private name 'private1'. +tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(32,25): error TS4037: Parameter type of public setter 'foo4' from exported class has or is using private name 'private1'. +tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(36,21): error TS4043: Return type of public getter 'foo5' from exported class has or is using private name 'private1'. +tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(71,23): error TS4043: Return type of public getter 'foo111' from exported class has or is using private name 'm2'. +tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(76,13): error TS4042: Return type of public getter 'foo112' from exported class has or is using name 'm2.public2' from private module 'm2'. +tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(81,27): error TS4037: Parameter type of public setter 'foo113' from exported class has or is using private name 'm2'. +tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(88,27): error TS4037: Parameter type of public setter 'foo114' from exported class has or is using private name 'm2'. +tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(92,23): error TS4043: Return type of public getter 'foo115' from exported class has or is using private name 'm2'. ==== tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts (10 errors) ==== @@ -22,26 +22,26 @@ tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(92,23): e export class public2 { } } - + export class c { // getter with annotation get foo1(): private1 { ~~~~~~~~ -!!! error TS4043: Return type of public property getter from exported class has or is using private name 'private1'. +!!! error TS4043: Return type of public getter 'foo1' from exported class has or is using private name 'private1'. return; } // getter without annotation get foo2() { ~~~~ -!!! error TS4043: Return type of public property getter from exported class has or is using private name 'private1'. +!!! error TS4043: Return type of public getter 'foo2' from exported class has or is using private name 'private1'. return new private1(); } // setter with annotation set foo3(param: private1) { ~~~~~~~~ -!!! error TS4037: Parameter 'foo3' of public property setter from exported class has or is using private name 'private1'. +!!! error TS4037: Parameter type of public setter 'foo3' from exported class has or is using private name 'private1'. } // Both - getter without annotation, setter with annotation @@ -50,18 +50,18 @@ tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(92,23): e } set foo4(param: private1) { ~~~~~~~~ -!!! error TS4037: Parameter 'foo4' of public property setter from exported class has or is using private name 'private1'. +!!! error TS4037: Parameter type of public setter 'foo4' from exported class has or is using private name 'private1'. } // Both - with annotation get foo5(): private1 { ~~~~~~~~ -!!! error TS4043: Return type of public property getter from exported class has or is using private name 'private1'. +!!! error TS4043: Return type of public getter 'foo5' from exported class has or is using private name 'private1'. return; } set foo5(param: private1) { } - + // getter with annotation get foo11(): public1 { return; @@ -93,21 +93,21 @@ tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(92,23): e // getter with annotation get foo111(): m2.public2 { ~~ -!!! error TS4043: Return type of public property getter from exported class has or is using private name 'm2'. +!!! error TS4043: Return type of public getter 'foo111' from exported class has or is using private name 'm2'. return; } // getter without annotation get foo112() { ~~~~~~ -!!! error TS4042: Return type of public property getter from exported class has or is using name 'm2.public2' from private module 'm2'. +!!! error TS4042: Return type of public getter 'foo112' from exported class has or is using name 'm2.public2' from private module 'm2'. return new m2.public2(); } // setter with annotation set foo113(param: m2.public2) { ~~ -!!! error TS4037: Parameter 'foo113' of public property setter from exported class has or is using private name 'm2'. +!!! error TS4037: Parameter type of public setter 'foo113' from exported class has or is using private name 'm2'. } // Both - getter without annotation, setter with annotation @@ -116,13 +116,13 @@ tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(92,23): e } set foo114(param: m2.public2) { ~~ -!!! error TS4037: Parameter 'foo114' of public property setter from exported class has or is using private name 'm2'. +!!! error TS4037: Parameter type of public setter 'foo114' from exported class has or is using private name 'm2'. } // Both - with annotation get foo115(): m2.public2 { ~~ -!!! error TS4043: Return type of public property getter from exported class has or is using private name 'm2'. +!!! error TS4043: Return type of public getter 'foo115' from exported class has or is using private name 'm2'. return; } set foo115(param: m2.public2) { diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.js b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.js index 2d4d948668a..c02807207ca 100644 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.js +++ b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.js @@ -10,7 +10,7 @@ module m { export class public2 { } } - + export class c { // getter with annotation get foo1(): private1 { @@ -39,7 +39,7 @@ module m { } set foo5(param: private1) { } - + // getter with annotation get foo11(): public1 { return; diff --git a/tests/baselines/reference/privacyAccessorDeclFile.errors.txt b/tests/baselines/reference/privacyAccessorDeclFile.errors.txt index 67a62a2269c..92ce3d5c535 100644 --- a/tests/baselines/reference/privacyAccessorDeclFile.errors.txt +++ b/tests/baselines/reference/privacyAccessorDeclFile.errors.txt @@ -1,39 +1,39 @@ -tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(253,44): error TS4040: Return type of public static property getter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(259,31): error TS4043: Return type of public property getter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(265,20): error TS4040: Return type of public static property getter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(271,13): error TS4043: Return type of public property getter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(361,48): error TS4037: Parameter 'myPublicStaticMethod' of public property setter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(365,35): error TS4037: Parameter 'myPublicMethod' of public property setter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(405,44): error TS4040: Return type of public static property getter from exported class has or is using private name 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(408,31): error TS4043: Return type of public property getter from exported class has or is using private name 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(411,20): error TS4039: Return type of public static property getter from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(414,13): error TS4042: Return type of public property getter from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(420,48): error TS4037: Parameter 'myPublicStaticMethod' of public property setter from exported class has or is using private name 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(422,35): error TS4037: Parameter 'myPublicMethod' of public property setter from exported class has or is using private name 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(8,40): error TS4040: Return type of public static property getter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(14,27): error TS4043: Return type of public property getter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(20,16): error TS4040: Return type of public static property getter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(26,9): error TS4043: Return type of public property getter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(116,44): error TS4037: Parameter 'myPublicStaticMethod' of public property setter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(120,31): error TS4037: Parameter 'myPublicMethod' of public property setter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(160,40): error TS4040: Return type of public static property getter from exported class has or is using private name 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(163,27): error TS4043: Return type of public property getter from exported class has or is using private name 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(166,16): error TS4039: Return type of public static property getter from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(169,9): error TS4042: Return type of public property getter from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(175,44): error TS4037: Parameter 'myPublicStaticMethod' of public property setter from exported class has or is using private name 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(177,31): error TS4037: Parameter 'myPublicMethod' of public property setter from exported class has or is using private name 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(210,44): error TS4040: Return type of public static property getter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(216,31): error TS4043: Return type of public property getter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(222,20): error TS4040: Return type of public static property getter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(228,13): error TS4043: Return type of public property getter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(318,48): error TS4037: Parameter 'myPublicStaticMethod' of public property setter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(322,35): error TS4037: Parameter 'myPublicMethod' of public property setter from exported class has or is using private name 'privateClass'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(362,44): error TS4040: Return type of public static property getter from exported class has or is using private name 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(365,31): error TS4043: Return type of public property getter from exported class has or is using private name 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(368,20): error TS4039: Return type of public static property getter from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(371,13): error TS4042: Return type of public property getter from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(377,48): error TS4037: Parameter 'myPublicStaticMethod' of public property setter from exported class has or is using private name 'privateModule'. -tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS4037: Parameter 'myPublicMethod' of public property setter from exported class has or is using private name 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(253,44): error TS4040: Return type of public static getter 'myPublicStaticMethod' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(259,31): error TS4043: Return type of public getter 'myPublicMethod' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(265,20): error TS4040: Return type of public static getter 'myPublicStaticMethod1' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(271,13): error TS4043: Return type of public getter 'myPublicMethod1' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(361,48): error TS4035: Parameter type of public static setter 'myPublicStaticMethod' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(365,35): error TS4037: Parameter type of public setter 'myPublicMethod' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(405,44): error TS4040: Return type of public static getter 'myPublicStaticMethod' from exported class has or is using private name 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(408,31): error TS4043: Return type of public getter 'myPublicMethod' from exported class has or is using private name 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(411,20): error TS4039: Return type of public static getter 'myPublicStaticMethod1' from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(414,13): error TS4042: Return type of public getter 'myPublicMethod1' from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(420,48): error TS4035: Parameter type of public static setter 'myPublicStaticMethod' from exported class has or is using private name 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_GlobalFile.ts(422,35): error TS4037: Parameter type of public setter 'myPublicMethod' from exported class has or is using private name 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(8,40): error TS4040: Return type of public static getter 'myPublicStaticMethod' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(14,27): error TS4043: Return type of public getter 'myPublicMethod' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(20,16): error TS4040: Return type of public static getter 'myPublicStaticMethod1' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(26,9): error TS4043: Return type of public getter 'myPublicMethod1' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(116,44): error TS4035: Parameter type of public static setter 'myPublicStaticMethod' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(120,31): error TS4037: Parameter type of public setter 'myPublicMethod' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(160,40): error TS4040: Return type of public static getter 'myPublicStaticMethod' from exported class has or is using private name 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(163,27): error TS4043: Return type of public getter 'myPublicMethod' from exported class has or is using private name 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(166,16): error TS4039: Return type of public static getter 'myPublicStaticMethod1' from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(169,9): error TS4042: Return type of public getter 'myPublicMethod1' from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(175,44): error TS4035: Parameter type of public static setter 'myPublicStaticMethod' from exported class has or is using private name 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(177,31): error TS4037: Parameter type of public setter 'myPublicMethod' from exported class has or is using private name 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(210,44): error TS4040: Return type of public static getter 'myPublicStaticMethod' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(216,31): error TS4043: Return type of public getter 'myPublicMethod' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(222,20): error TS4040: Return type of public static getter 'myPublicStaticMethod1' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(228,13): error TS4043: Return type of public getter 'myPublicMethod1' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(318,48): error TS4035: Parameter type of public static setter 'myPublicStaticMethod' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(322,35): error TS4037: Parameter type of public setter 'myPublicMethod' from exported class has or is using private name 'privateClass'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(362,44): error TS4040: Return type of public static getter 'myPublicStaticMethod' from exported class has or is using private name 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(365,31): error TS4043: Return type of public getter 'myPublicMethod' from exported class has or is using private name 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(368,20): error TS4039: Return type of public static getter 'myPublicStaticMethod1' from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(371,13): error TS4042: Return type of public getter 'myPublicMethod1' from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(377,48): error TS4035: Parameter type of public static setter 'myPublicStaticMethod' from exported class has or is using private name 'privateModule'. +tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS4037: Parameter type of public setter 'myPublicMethod' from exported class has or is using private name 'privateModule'. ==== tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts (24 errors) ==== @@ -46,7 +46,7 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS export class publicClassWithWithPrivateGetAccessorTypes { static get myPublicStaticMethod(): privateClass { // Error ~~~~~~~~~~~~ -!!! error TS4040: Return type of public static property getter from exported class has or is using private name 'privateClass'. +!!! error TS4040: Return type of public static getter 'myPublicStaticMethod' from exported class has or is using private name 'privateClass'. return null; } private static get myPrivateStaticMethod(): privateClass { @@ -54,7 +54,7 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS } get myPublicMethod(): privateClass { // Error ~~~~~~~~~~~~ -!!! error TS4043: Return type of public property getter from exported class has or is using private name 'privateClass'. +!!! error TS4043: Return type of public getter 'myPublicMethod' from exported class has or is using private name 'privateClass'. return null; } private get myPrivateMethod(): privateClass { @@ -62,7 +62,7 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS } static get myPublicStaticMethod1() { // Error ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS4040: Return type of public static property getter from exported class has or is using private name 'privateClass'. +!!! error TS4040: Return type of public static getter 'myPublicStaticMethod1' from exported class has or is using private name 'privateClass'. return new privateClass(); } private static get myPrivateStaticMethod1() { @@ -70,7 +70,7 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS } get myPublicMethod1() { // Error ~~~~~~~~~~~~~~~ -!!! error TS4043: Return type of public property getter from exported class has or is using private name 'privateClass'. +!!! error TS4043: Return type of public getter 'myPublicMethod1' from exported class has or is using private name 'privateClass'. return new privateClass(); } private get myPrivateMethod1() { @@ -162,13 +162,13 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS export class publicClassWithWithPrivateSetAccessorTypes { static set myPublicStaticMethod(param: privateClass) { // Error ~~~~~~~~~~~~ -!!! error TS4037: Parameter 'myPublicStaticMethod' of public property setter from exported class has or is using private name 'privateClass'. +!!! error TS4035: Parameter type of public static setter 'myPublicStaticMethod' from exported class has or is using private name 'privateClass'. } private static set myPrivateStaticMethod(param: privateClass) { } set myPublicMethod(param: privateClass) { // Error ~~~~~~~~~~~~ -!!! error TS4037: Parameter 'myPublicMethod' of public property setter from exported class has or is using private name 'privateClass'. +!!! error TS4037: Parameter type of public setter 'myPublicMethod' from exported class has or is using private name 'privateClass'. } private set myPrivateMethod(param: privateClass) { } @@ -210,22 +210,22 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS export class publicClassWithPrivateModuleGetAccessorTypes { static get myPublicStaticMethod(): privateModule.publicClass { // Error ~~~~~~~~~~~~~ -!!! error TS4040: Return type of public static property getter from exported class has or is using private name 'privateModule'. +!!! error TS4040: Return type of public static getter 'myPublicStaticMethod' from exported class has or is using private name 'privateModule'. return null; } get myPublicMethod(): privateModule.publicClass { // Error ~~~~~~~~~~~~~ -!!! error TS4043: Return type of public property getter from exported class has or is using private name 'privateModule'. +!!! error TS4043: Return type of public getter 'myPublicMethod' from exported class has or is using private name 'privateModule'. return null; } static get myPublicStaticMethod1() { // Error ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS4039: Return type of public static property getter from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. +!!! error TS4039: Return type of public static getter 'myPublicStaticMethod1' from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. return new privateModule.publicClass(); } get myPublicMethod1() { // Error ~~~~~~~~~~~~~~~ -!!! error TS4042: Return type of public property getter from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. +!!! error TS4042: Return type of public getter 'myPublicMethod1' from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. return new privateModule.publicClass(); } } @@ -233,11 +233,11 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS export class publicClassWithPrivateModuleSetAccessorTypes { static set myPublicStaticMethod(param: privateModule.publicClass) { // Error ~~~~~~~~~~~~~ -!!! error TS4037: Parameter 'myPublicStaticMethod' of public property setter from exported class has or is using private name 'privateModule'. +!!! error TS4035: Parameter type of public static setter 'myPublicStaticMethod' from exported class has or is using private name 'privateModule'. } set myPublicMethod(param: privateModule.publicClass) { // Error ~~~~~~~~~~~~~ -!!! error TS4037: Parameter 'myPublicMethod' of public property setter from exported class has or is using private name 'privateModule'. +!!! error TS4037: Parameter type of public setter 'myPublicMethod' from exported class has or is using private name 'privateModule'. } } @@ -272,7 +272,7 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS export class publicClassWithWithPrivateGetAccessorTypes { static get myPublicStaticMethod(): privateClass { // Error ~~~~~~~~~~~~ -!!! error TS4040: Return type of public static property getter from exported class has or is using private name 'privateClass'. +!!! error TS4040: Return type of public static getter 'myPublicStaticMethod' from exported class has or is using private name 'privateClass'. return null; } private static get myPrivateStaticMethod(): privateClass { @@ -280,7 +280,7 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS } get myPublicMethod(): privateClass { // Error ~~~~~~~~~~~~ -!!! error TS4043: Return type of public property getter from exported class has or is using private name 'privateClass'. +!!! error TS4043: Return type of public getter 'myPublicMethod' from exported class has or is using private name 'privateClass'. return null; } private get myPrivateMethod(): privateClass { @@ -288,7 +288,7 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS } static get myPublicStaticMethod1() { // Error ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS4040: Return type of public static property getter from exported class has or is using private name 'privateClass'. +!!! error TS4040: Return type of public static getter 'myPublicStaticMethod1' from exported class has or is using private name 'privateClass'. return new privateClass(); } private static get myPrivateStaticMethod1() { @@ -296,7 +296,7 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS } get myPublicMethod1() { // Error ~~~~~~~~~~~~~~~ -!!! error TS4043: Return type of public property getter from exported class has or is using private name 'privateClass'. +!!! error TS4043: Return type of public getter 'myPublicMethod1' from exported class has or is using private name 'privateClass'. return new privateClass(); } private get myPrivateMethod1() { @@ -388,13 +388,13 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS export class publicClassWithWithPrivateSetAccessorTypes { static set myPublicStaticMethod(param: privateClass) { // Error ~~~~~~~~~~~~ -!!! error TS4037: Parameter 'myPublicStaticMethod' of public property setter from exported class has or is using private name 'privateClass'. +!!! error TS4035: Parameter type of public static setter 'myPublicStaticMethod' from exported class has or is using private name 'privateClass'. } private static set myPrivateStaticMethod(param: privateClass) { } set myPublicMethod(param: privateClass) { // Error ~~~~~~~~~~~~ -!!! error TS4037: Parameter 'myPublicMethod' of public property setter from exported class has or is using private name 'privateClass'. +!!! error TS4037: Parameter type of public setter 'myPublicMethod' from exported class has or is using private name 'privateClass'. } private set myPrivateMethod(param: privateClass) { } @@ -436,22 +436,22 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS export class publicClassWithPrivateModuleGetAccessorTypes { static get myPublicStaticMethod(): privateModule.publicClass { // Error ~~~~~~~~~~~~~ -!!! error TS4040: Return type of public static property getter from exported class has or is using private name 'privateModule'. +!!! error TS4040: Return type of public static getter 'myPublicStaticMethod' from exported class has or is using private name 'privateModule'. return null; } get myPublicMethod(): privateModule.publicClass { // Error ~~~~~~~~~~~~~ -!!! error TS4043: Return type of public property getter from exported class has or is using private name 'privateModule'. +!!! error TS4043: Return type of public getter 'myPublicMethod' from exported class has or is using private name 'privateModule'. return null; } static get myPublicStaticMethod1() { // Error ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS4039: Return type of public static property getter from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. +!!! error TS4039: Return type of public static getter 'myPublicStaticMethod1' from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. return new privateModule.publicClass(); } get myPublicMethod1() { // Error ~~~~~~~~~~~~~~~ -!!! error TS4042: Return type of public property getter from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. +!!! error TS4042: Return type of public getter 'myPublicMethod1' from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. return new privateModule.publicClass(); } } @@ -459,11 +459,11 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS export class publicClassWithPrivateModuleSetAccessorTypes { static set myPublicStaticMethod(param: privateModule.publicClass) { // Error ~~~~~~~~~~~~~ -!!! error TS4037: Parameter 'myPublicStaticMethod' of public property setter from exported class has or is using private name 'privateModule'. +!!! error TS4035: Parameter type of public static setter 'myPublicStaticMethod' from exported class has or is using private name 'privateModule'. } set myPublicMethod(param: privateModule.publicClass) { // Error ~~~~~~~~~~~~~ -!!! error TS4037: Parameter 'myPublicMethod' of public property setter from exported class has or is using private name 'privateModule'. +!!! error TS4037: Parameter type of public setter 'myPublicMethod' from exported class has or is using private name 'privateModule'. } } @@ -948,7 +948,7 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS export class publicClassWithWithPrivateGetAccessorTypes { static get myPublicStaticMethod(): privateClass { // Error ~~~~~~~~~~~~ -!!! error TS4040: Return type of public static property getter from exported class has or is using private name 'privateClass'. +!!! error TS4040: Return type of public static getter 'myPublicStaticMethod' from exported class has or is using private name 'privateClass'. return null; } private static get myPrivateStaticMethod(): privateClass { @@ -956,7 +956,7 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS } get myPublicMethod(): privateClass { // Error ~~~~~~~~~~~~ -!!! error TS4043: Return type of public property getter from exported class has or is using private name 'privateClass'. +!!! error TS4043: Return type of public getter 'myPublicMethod' from exported class has or is using private name 'privateClass'. return null; } private get myPrivateMethod(): privateClass { @@ -964,7 +964,7 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS } static get myPublicStaticMethod1() { // Error ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS4040: Return type of public static property getter from exported class has or is using private name 'privateClass'. +!!! error TS4040: Return type of public static getter 'myPublicStaticMethod1' from exported class has or is using private name 'privateClass'. return new privateClass(); } private static get myPrivateStaticMethod1() { @@ -972,7 +972,7 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS } get myPublicMethod1() { // Error ~~~~~~~~~~~~~~~ -!!! error TS4043: Return type of public property getter from exported class has or is using private name 'privateClass'. +!!! error TS4043: Return type of public getter 'myPublicMethod1' from exported class has or is using private name 'privateClass'. return new privateClass(); } private get myPrivateMethod1() { @@ -1064,13 +1064,13 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS export class publicClassWithWithPrivateSetAccessorTypes { static set myPublicStaticMethod(param: privateClass) { // Error ~~~~~~~~~~~~ -!!! error TS4037: Parameter 'myPublicStaticMethod' of public property setter from exported class has or is using private name 'privateClass'. +!!! error TS4035: Parameter type of public static setter 'myPublicStaticMethod' from exported class has or is using private name 'privateClass'. } private static set myPrivateStaticMethod(param: privateClass) { } set myPublicMethod(param: privateClass) { // Error ~~~~~~~~~~~~ -!!! error TS4037: Parameter 'myPublicMethod' of public property setter from exported class has or is using private name 'privateClass'. +!!! error TS4037: Parameter type of public setter 'myPublicMethod' from exported class has or is using private name 'privateClass'. } private set myPrivateMethod(param: privateClass) { } @@ -1112,22 +1112,22 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS export class publicClassWithPrivateModuleGetAccessorTypes { static get myPublicStaticMethod(): privateModule.publicClass { // Error ~~~~~~~~~~~~~ -!!! error TS4040: Return type of public static property getter from exported class has or is using private name 'privateModule'. +!!! error TS4040: Return type of public static getter 'myPublicStaticMethod' from exported class has or is using private name 'privateModule'. return null; } get myPublicMethod(): privateModule.publicClass { // Error ~~~~~~~~~~~~~ -!!! error TS4043: Return type of public property getter from exported class has or is using private name 'privateModule'. +!!! error TS4043: Return type of public getter 'myPublicMethod' from exported class has or is using private name 'privateModule'. return null; } static get myPublicStaticMethod1() { // Error ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS4039: Return type of public static property getter from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. +!!! error TS4039: Return type of public static getter 'myPublicStaticMethod1' from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. return new privateModule.publicClass(); } get myPublicMethod1() { // Error ~~~~~~~~~~~~~~~ -!!! error TS4042: Return type of public property getter from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. +!!! error TS4042: Return type of public getter 'myPublicMethod1' from exported class has or is using name 'privateModule.publicClass' from private module 'privateModule'. return new privateModule.publicClass(); } } @@ -1135,11 +1135,11 @@ tests/cases/compiler/privacyAccessorDeclFile_externalModule.ts(379,35): error TS export class publicClassWithPrivateModuleSetAccessorTypes { static set myPublicStaticMethod(param: privateModule.publicClass) { // Error ~~~~~~~~~~~~~ -!!! error TS4037: Parameter 'myPublicStaticMethod' of public property setter from exported class has or is using private name 'privateModule'. +!!! error TS4035: Parameter type of public static setter 'myPublicStaticMethod' from exported class has or is using private name 'privateModule'. } set myPublicMethod(param: privateModule.publicClass) { // Error ~~~~~~~~~~~~~ -!!! error TS4037: Parameter 'myPublicMethod' of public property setter from exported class has or is using private name 'privateModule'. +!!! error TS4037: Parameter type of public setter 'myPublicMethod' from exported class has or is using private name 'privateModule'. } } diff --git a/tests/baselines/reference/privacyCannotNameAccessorDeclFile.errors.txt b/tests/baselines/reference/privacyCannotNameAccessorDeclFile.errors.txt index 6c1763f293e..f2419b360d6 100644 --- a/tests/baselines/reference/privacyCannotNameAccessorDeclFile.errors.txt +++ b/tests/baselines/reference/privacyCannotNameAccessorDeclFile.errors.txt @@ -1,11 +1,11 @@ -tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(3,16): error TS4038: Return type of public static property getter from exported class has or is using name 'Widget1' from external module "tests/cases/compiler/privacyCannotNameAccessorDeclFile_Widgets" but cannot be named. -tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(9,9): error TS4041: Return type of public property getter from exported class has or is using name 'Widget1' from external module "tests/cases/compiler/privacyCannotNameAccessorDeclFile_Widgets" but cannot be named. -tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(15,16): error TS4038: Return type of public static property getter from exported class has or is using name 'Widget3' from external module "GlobalWidgets" but cannot be named. -tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(21,9): error TS4041: Return type of public property getter from exported class has or is using name 'Widget3' from external module "GlobalWidgets" but cannot be named. -tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(57,16): error TS4038: Return type of public static property getter from exported class has or is using name 'SpecializedWidget.Widget2' from external module "tests/cases/compiler/privacyCannotNameAccessorDeclFile_Widgets" but cannot be named. -tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(60,9): error TS4041: Return type of public property getter from exported class has or is using name 'SpecializedWidget.Widget2' from external module "tests/cases/compiler/privacyCannotNameAccessorDeclFile_Widgets" but cannot be named. -tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(63,16): error TS4038: Return type of public static property getter from exported class has or is using name 'SpecializedGlobalWidget.Widget4' from external module "GlobalWidgets" but cannot be named. -tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(66,9): error TS4041: Return type of public property getter from exported class has or is using name 'SpecializedGlobalWidget.Widget4' from external module "GlobalWidgets" but cannot be named. +tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(3,16): error TS4038: Return type of public static getter 'myPublicStaticMethod' from exported class has or is using name 'Widget1' from external module "tests/cases/compiler/privacyCannotNameAccessorDeclFile_Widgets" but cannot be named. +tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(9,9): error TS4041: Return type of public getter 'myPublicMethod' from exported class has or is using name 'Widget1' from external module "tests/cases/compiler/privacyCannotNameAccessorDeclFile_Widgets" but cannot be named. +tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(15,16): error TS4038: Return type of public static getter 'myPublicStaticMethod1' from exported class has or is using name 'Widget3' from external module "GlobalWidgets" but cannot be named. +tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(21,9): error TS4041: Return type of public getter 'myPublicMethod1' from exported class has or is using name 'Widget3' from external module "GlobalWidgets" but cannot be named. +tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(57,16): error TS4038: Return type of public static getter 'myPublicStaticMethod' from exported class has or is using name 'SpecializedWidget.Widget2' from external module "tests/cases/compiler/privacyCannotNameAccessorDeclFile_Widgets" but cannot be named. +tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(60,9): error TS4041: Return type of public getter 'myPublicMethod' from exported class has or is using name 'SpecializedWidget.Widget2' from external module "tests/cases/compiler/privacyCannotNameAccessorDeclFile_Widgets" but cannot be named. +tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(63,16): error TS4038: Return type of public static getter 'myPublicStaticMethod1' from exported class has or is using name 'SpecializedGlobalWidget.Widget4' from external module "GlobalWidgets" but cannot be named. +tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(66,9): error TS4041: Return type of public getter 'myPublicMethod1' from exported class has or is using name 'SpecializedGlobalWidget.Widget4' from external module "GlobalWidgets" but cannot be named. ==== tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts (8 errors) ==== @@ -13,7 +13,7 @@ tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(66,9): error export class publicClassWithWithPrivateGetAccessorTypes { static get myPublicStaticMethod() { // Error ~~~~~~~~~~~~~~~~~~~~ -!!! error TS4038: Return type of public static property getter from exported class has or is using name 'Widget1' from external module "tests/cases/compiler/privacyCannotNameAccessorDeclFile_Widgets" but cannot be named. +!!! error TS4038: Return type of public static getter 'myPublicStaticMethod' from exported class has or is using name 'Widget1' from external module "tests/cases/compiler/privacyCannotNameAccessorDeclFile_Widgets" but cannot be named. return exporter.createExportedWidget1(); } private static get myPrivateStaticMethod() { @@ -21,7 +21,7 @@ tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(66,9): error } get myPublicMethod() { // Error ~~~~~~~~~~~~~~ -!!! error TS4041: Return type of public property getter from exported class has or is using name 'Widget1' from external module "tests/cases/compiler/privacyCannotNameAccessorDeclFile_Widgets" but cannot be named. +!!! error TS4041: Return type of public getter 'myPublicMethod' from exported class has or is using name 'Widget1' from external module "tests/cases/compiler/privacyCannotNameAccessorDeclFile_Widgets" but cannot be named. return exporter.createExportedWidget1(); } private get myPrivateMethod() { @@ -29,7 +29,7 @@ tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(66,9): error } static get myPublicStaticMethod1() { // Error ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS4038: Return type of public static property getter from exported class has or is using name 'Widget3' from external module "GlobalWidgets" but cannot be named. +!!! error TS4038: Return type of public static getter 'myPublicStaticMethod1' from exported class has or is using name 'Widget3' from external module "GlobalWidgets" but cannot be named. return exporter.createExportedWidget3(); } private static get myPrivateStaticMethod1() { @@ -37,7 +37,7 @@ tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(66,9): error } get myPublicMethod1() { // Error ~~~~~~~~~~~~~~~ -!!! error TS4041: Return type of public property getter from exported class has or is using name 'Widget3' from external module "GlobalWidgets" but cannot be named. +!!! error TS4041: Return type of public getter 'myPublicMethod1' from exported class has or is using name 'Widget3' from external module "GlobalWidgets" but cannot be named. return exporter.createExportedWidget3(); } private get myPrivateMethod1() { @@ -75,22 +75,22 @@ tests/cases/compiler/privacyCannotNameAccessorDeclFile_consumer.ts(66,9): error export class publicClassWithPrivateModuleGetAccessorTypes { static get myPublicStaticMethod() { // Error ~~~~~~~~~~~~~~~~~~~~ -!!! error TS4038: Return type of public static property getter from exported class has or is using name 'SpecializedWidget.Widget2' from external module "tests/cases/compiler/privacyCannotNameAccessorDeclFile_Widgets" but cannot be named. +!!! error TS4038: Return type of public static getter 'myPublicStaticMethod' from exported class has or is using name 'SpecializedWidget.Widget2' from external module "tests/cases/compiler/privacyCannotNameAccessorDeclFile_Widgets" but cannot be named. return exporter.createExportedWidget2(); } get myPublicMethod() { // Error ~~~~~~~~~~~~~~ -!!! error TS4041: Return type of public property getter from exported class has or is using name 'SpecializedWidget.Widget2' from external module "tests/cases/compiler/privacyCannotNameAccessorDeclFile_Widgets" but cannot be named. +!!! error TS4041: Return type of public getter 'myPublicMethod' from exported class has or is using name 'SpecializedWidget.Widget2' from external module "tests/cases/compiler/privacyCannotNameAccessorDeclFile_Widgets" but cannot be named. return exporter.createExportedWidget2(); } static get myPublicStaticMethod1() { // Error ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS4038: Return type of public static property getter from exported class has or is using name 'SpecializedGlobalWidget.Widget4' from external module "GlobalWidgets" but cannot be named. +!!! error TS4038: Return type of public static getter 'myPublicStaticMethod1' from exported class has or is using name 'SpecializedGlobalWidget.Widget4' from external module "GlobalWidgets" but cannot be named. return exporter.createExportedWidget4(); } get myPublicMethod1() { // Error ~~~~~~~~~~~~~~~ -!!! error TS4041: Return type of public property getter from exported class has or is using name 'SpecializedGlobalWidget.Widget4' from external module "GlobalWidgets" but cannot be named. +!!! error TS4041: Return type of public getter 'myPublicMethod1' from exported class has or is using name 'SpecializedGlobalWidget.Widget4' from external module "GlobalWidgets" but cannot be named. return exporter.createExportedWidget4(); } } diff --git a/tests/baselines/reference/symbolDeclarationEmit12.errors.txt b/tests/baselines/reference/symbolDeclarationEmit12.errors.txt index cdc712f698d..3052065ebe6 100644 --- a/tests/baselines/reference/symbolDeclarationEmit12.errors.txt +++ b/tests/baselines/reference/symbolDeclarationEmit12.errors.txt @@ -4,7 +4,7 @@ tests/cases/conformance/es6/Symbols/symbolDeclarationEmit12.ts(5,33): error TS40 tests/cases/conformance/es6/Symbols/symbolDeclarationEmit12.ts(6,40): error TS4055: Return type of public method from exported class has or is using private name 'I'. tests/cases/conformance/es6/Symbols/symbolDeclarationEmit12.ts(9,13): error TS2300: Duplicate identifier '[Symbol.toPrimitive]'. tests/cases/conformance/es6/Symbols/symbolDeclarationEmit12.ts(10,13): error TS2300: Duplicate identifier '[Symbol.toPrimitive]'. -tests/cases/conformance/es6/Symbols/symbolDeclarationEmit12.ts(10,37): error TS4037: Parameter '[Symbol.toPrimitive]' of public property setter from exported class has or is using private name 'I'. +tests/cases/conformance/es6/Symbols/symbolDeclarationEmit12.ts(10,37): error TS4037: Parameter type of public setter '[Symbol.toPrimitive]' from exported class has or is using private name 'I'. ==== tests/cases/conformance/es6/Symbols/symbolDeclarationEmit12.ts (7 errors) ==== @@ -31,6 +31,6 @@ tests/cases/conformance/es6/Symbols/symbolDeclarationEmit12.ts(10,37): error TS4 ~~~~~~~~~~~~~~~~~~~~ !!! error TS2300: Duplicate identifier '[Symbol.toPrimitive]'. ~ -!!! error TS4037: Parameter '[Symbol.toPrimitive]' of public property setter from exported class has or is using private name 'I'. +!!! error TS4037: Parameter type of public setter '[Symbol.toPrimitive]' from exported class has or is using private name 'I'. } } \ No newline at end of file diff --git a/tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts b/tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts index 8dced33083b..6625973717f 100644 --- a/tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts +++ b/tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts @@ -13,7 +13,7 @@ module m { export class public2 { } } - + export class c { // getter with annotation get foo1(): private1 { @@ -42,7 +42,7 @@ module m { } set foo5(param: private1) { } - + // getter with annotation get foo11(): public1 { return; From ca181a7952a5f51d6f1fff2b4ffe5e236bf81cec Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 8 Nov 2017 10:47:34 -0800 Subject: [PATCH 30/73] Accept baselines --- .../declFileTypeAnnotationVisibilityErrorAccessors.symbols | 4 ++-- .../declFileTypeAnnotationVisibilityErrorAccessors.types | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.symbols b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.symbols index 503fa75ff97..25b8adca4ac 100644 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.symbols +++ b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.symbols @@ -17,7 +17,7 @@ module m { >public2 : Symbol(public2, Decl(declFileTypeAnnotationVisibilityErrorAccessors.ts, 7, 15)) } } - + export class c { >c : Symbol(c, Decl(declFileTypeAnnotationVisibilityErrorAccessors.ts, 10, 5)) @@ -69,7 +69,7 @@ module m { >param : Symbol(param, Decl(declFileTypeAnnotationVisibilityErrorAccessors.ts, 38, 17)) >private1 : Symbol(private1, Decl(declFileTypeAnnotationVisibilityErrorAccessors.ts, 0, 10)) } - + // getter with annotation get foo11(): public1 { >foo11 : Symbol(c.foo11, Decl(declFileTypeAnnotationVisibilityErrorAccessors.ts, 39, 9)) diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.types b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.types index c82794f2764..a05a00908d2 100644 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.types +++ b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.types @@ -17,7 +17,7 @@ module m { >public2 : public2 } } - + export class c { >c : c @@ -71,7 +71,7 @@ module m { >param : private1 >private1 : private1 } - + // getter with annotation get foo11(): public1 { >foo11 : public1 From 2548aced3f0482c579ef8e00f25d8f370974fb3c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 8 Nov 2017 10:56:30 -0800 Subject: [PATCH 31/73] Add a couple of test cases --- .../reference/controlFlowStringIndex.js | 9 ++++++- .../reference/controlFlowStringIndex.symbols | 24 +++++++++++++++---- .../reference/controlFlowStringIndex.types | 19 ++++++++++++++- .../controlFlow/controlFlowStringIndex.ts | 7 +++++- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/tests/baselines/reference/controlFlowStringIndex.js b/tests/baselines/reference/controlFlowStringIndex.js index 456ae6afcd4..db4d4a30ab9 100644 --- a/tests/baselines/reference/controlFlowStringIndex.js +++ b/tests/baselines/reference/controlFlowStringIndex.js @@ -1,8 +1,13 @@ //// [controlFlowStringIndex.ts] -type A = { [index: string]: number | null }; +type A = { + other: number | null; + [index: string]: number | null +}; declare const value: A; if (value.foo !== null) { value.foo.toExponential() + value.other // should still be number | null + value.bar // should still be number | null } @@ -10,4 +15,6 @@ if (value.foo !== null) { "use strict"; if (value.foo !== null) { value.foo.toExponential(); + value.other; // should still be number | null + value.bar; // should still be number | null } diff --git a/tests/baselines/reference/controlFlowStringIndex.symbols b/tests/baselines/reference/controlFlowStringIndex.symbols index aad08e48a9b..5c7d626d4a7 100644 --- a/tests/baselines/reference/controlFlowStringIndex.symbols +++ b/tests/baselines/reference/controlFlowStringIndex.symbols @@ -1,18 +1,32 @@ === tests/cases/conformance/controlFlow/controlFlowStringIndex.ts === -type A = { [index: string]: number | null }; +type A = { >A : Symbol(A, Decl(controlFlowStringIndex.ts, 0, 0)) ->index : Symbol(index, Decl(controlFlowStringIndex.ts, 0, 12)) + other: number | null; +>other : Symbol(other, Decl(controlFlowStringIndex.ts, 0, 10)) + + [index: string]: number | null +>index : Symbol(index, Decl(controlFlowStringIndex.ts, 2, 5)) + +}; declare const value: A; ->value : Symbol(value, Decl(controlFlowStringIndex.ts, 1, 13)) +>value : Symbol(value, Decl(controlFlowStringIndex.ts, 4, 13)) >A : Symbol(A, Decl(controlFlowStringIndex.ts, 0, 0)) if (value.foo !== null) { ->value : Symbol(value, Decl(controlFlowStringIndex.ts, 1, 13)) +>value : Symbol(value, Decl(controlFlowStringIndex.ts, 4, 13)) value.foo.toExponential() >value.foo.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) ->value : Symbol(value, Decl(controlFlowStringIndex.ts, 1, 13)) +>value : Symbol(value, Decl(controlFlowStringIndex.ts, 4, 13)) >toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + + value.other // should still be number | null +>value.other : Symbol(other, Decl(controlFlowStringIndex.ts, 0, 10)) +>value : Symbol(value, Decl(controlFlowStringIndex.ts, 4, 13)) +>other : Symbol(other, Decl(controlFlowStringIndex.ts, 0, 10)) + + value.bar // should still be number | null +>value : Symbol(value, Decl(controlFlowStringIndex.ts, 4, 13)) } diff --git a/tests/baselines/reference/controlFlowStringIndex.types b/tests/baselines/reference/controlFlowStringIndex.types index d1722dd6925..8c5f82cbf80 100644 --- a/tests/baselines/reference/controlFlowStringIndex.types +++ b/tests/baselines/reference/controlFlowStringIndex.types @@ -1,9 +1,16 @@ === tests/cases/conformance/controlFlow/controlFlowStringIndex.ts === -type A = { [index: string]: number | null }; +type A = { >A : A + + other: number | null; +>other : number | null +>null : null + + [index: string]: number | null >index : string >null : null +}; declare const value: A; >value : A >A : A @@ -22,5 +29,15 @@ if (value.foo !== null) { >value : A >foo : number >toExponential : (fractionDigits?: number | undefined) => string + + value.other // should still be number | null +>value.other : number | null +>value : A +>other : number | null + + value.bar // should still be number | null +>value.bar : number | null +>value : A +>bar : number | null } diff --git a/tests/cases/conformance/controlFlow/controlFlowStringIndex.ts b/tests/cases/conformance/controlFlow/controlFlowStringIndex.ts index 78acf6d654e..28b75eaba70 100644 --- a/tests/cases/conformance/controlFlow/controlFlowStringIndex.ts +++ b/tests/cases/conformance/controlFlow/controlFlowStringIndex.ts @@ -1,6 +1,11 @@ // @strict: true -type A = { [index: string]: number | null }; +type A = { + other: number | null; + [index: string]: number | null +}; declare const value: A; if (value.foo !== null) { value.foo.toExponential() + value.other // should still be number | null + value.bar // should still be number | null } From 80d1aa0b4f4d19a3d799afb877260902c13ad24e Mon Sep 17 00:00:00 2001 From: Adrian Leonhard Date: Wed, 8 Nov 2017 21:56:39 +0100 Subject: [PATCH 32/73] processDiagnosticMessages.ts: linted, removed unused code (#18697) Added following line to generated output: "// generated from 'src/diagnosticMessages.json' by 'scripts/processDiagnosticMessages.ts'\r\n" + Fixes https://github.com/Microsoft/TypeScript/issues/3591 --- scripts/processDiagnosticMessages.ts | 67 ++++++++++++++-------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/scripts/processDiagnosticMessages.ts b/scripts/processDiagnosticMessages.ts index 20085022c04..dd66564b134 100644 --- a/scripts/processDiagnosticMessages.ts +++ b/scripts/processDiagnosticMessages.ts @@ -1,4 +1,5 @@ /// +/// interface DiagnosticDetails { category: string; @@ -9,57 +10,55 @@ interface DiagnosticDetails { type InputDiagnosticMessageTable = ts.Map; function main(): void { - var sys = ts.sys; + const sys = ts.sys; if (sys.args.length < 1) { - sys.write("Usage:" + sys.newLine) + sys.write("Usage:" + sys.newLine); sys.write("\tnode processDiagnosticMessages.js " + sys.newLine); return; } function writeFile(fileName: string, contents: string) { - // TODO: Fix path joining - var inputDirectory = inputFilePath.substr(0,inputFilePath.lastIndexOf("/")); - var fileOutputPath = inputDirectory + "/" + fileName; + const inputDirectory = ts.getDirectoryPath(inputFilePath); + const fileOutputPath = ts.combinePaths(inputDirectory, fileName); sys.writeFile(fileOutputPath, contents); } - var inputFilePath = sys.args[0].replace(/\\/g, "/"); - var inputStr = sys.readFile(inputFilePath); + const inputFilePath = sys.args[0].replace(/\\/g, "/"); + const inputStr = sys.readFile(inputFilePath); - var diagnosticMessagesJson: { [key: string]: DiagnosticDetails } = JSON.parse(inputStr); - // Check that there are no duplicates. - const seenNames = ts.createMap(); - for (const name of Object.keys(diagnosticMessagesJson)) { - if (seenNames.has(name)) - throw new Error(`Name ${name} appears twice`); - seenNames.set(name, true); - } + const diagnosticMessagesJson: { [key: string]: DiagnosticDetails } = JSON.parse(inputStr); const diagnosticMessages: InputDiagnosticMessageTable = ts.createMapFromTemplate(diagnosticMessagesJson); - var infoFileOutput = buildInfoFileOutput(diagnosticMessages); + const outputFilesDir = ts.getDirectoryPath(inputFilePath); + const thisFilePathRel = ts.getRelativePathToDirectoryOrUrl(outputFilesDir, sys.getExecutingFilePath(), + sys.getCurrentDirectory(), ts.createGetCanonicalFileName(sys.useCaseSensitiveFileNames), /* isAbsolutePathAnUrl */ false); + + const infoFileOutput = buildInfoFileOutput(diagnosticMessages, "./diagnosticInformationMap.generated.ts", thisFilePathRel); checkForUniqueCodes(diagnosticMessages); writeFile("diagnosticInformationMap.generated.ts", infoFileOutput); - var messageOutput = buildDiagnosticMessageOutput(diagnosticMessages); + const messageOutput = buildDiagnosticMessageOutput(diagnosticMessages); writeFile("diagnosticMessages.generated.json", messageOutput); } function checkForUniqueCodes(diagnosticTable: InputDiagnosticMessageTable) { const allCodes: { [key: number]: true | undefined } = []; diagnosticTable.forEach(({ code }) => { - if (allCodes[code]) + if (allCodes[code]) { throw new Error(`Diagnostic code ${code} appears more than once.`); + } allCodes[code] = true; }); } -function buildInfoFileOutput(messageTable: InputDiagnosticMessageTable): string { - var result = - '// \r\n' + - '/// \r\n' + - '/* @internal */\r\n' + - 'namespace ts {\r\n' + +function buildInfoFileOutput(messageTable: InputDiagnosticMessageTable, inputFilePathRel: string, thisFilePathRel: string): string { + let result = + "// \r\n" + + "// generated from '" + inputFilePathRel + "' by '" + thisFilePathRel + "'\r\n" + + "/// \r\n" + + "/* @internal */\r\n" + + "namespace ts {\r\n" + " function diag(code: number, category: DiagnosticCategory, key: string, message: string): DiagnosticMessage {\r\n" + " return { code, category, key, message };\r\n" + " }\r\n" + @@ -70,20 +69,20 @@ function buildInfoFileOutput(messageTable: InputDiagnosticMessageTable): string result += ` ${propName}: diag(${code}, DiagnosticCategory.${category}, "${createKey(propName, code)}", ${JSON.stringify(name)}),\r\n`; }); - result += ' };\r\n}'; + result += " };\r\n}"; return result; } function buildDiagnosticMessageOutput(messageTable: InputDiagnosticMessageTable): string { - let result = '{'; + let result = "{"; messageTable.forEach(({ code }, name) => { const propName = convertPropertyName(name); result += `\r\n "${createKey(propName, code)}" : "${name.replace(/[\"]/g, '\\"')}",`; }); // Shave trailing comma, then add newline and ending brace - result = result.slice(0, result.length - 1) + '\r\n}'; + result = result.slice(0, result.length - 1) + "\r\n}"; // Assert that we generated valid JSON JSON.parse(result); @@ -91,15 +90,15 @@ function buildDiagnosticMessageOutput(messageTable: InputDiagnosticMessageTable) return result; } -function createKey(name: string, code: number) : string { - return name.slice(0, 100) + '_' + code; +function createKey(name: string, code: number): string { + return name.slice(0, 100) + "_" + code; } function convertPropertyName(origName: string): string { - var result = origName.split("").map(char => { - if (char === '*') { return "_Asterisk"; } - if (char === '/') { return "_Slash"; } - if (char === ':') { return "_Colon"; } + let result = origName.split("").map(char => { + if (char === "*") { return "_Asterisk"; } + if (char === "/") { return "_Slash"; } + if (char === ":") { return "_Colon"; } return /\w/.test(char) ? char : "_"; }).join(""); @@ -107,7 +106,7 @@ function convertPropertyName(origName: string): string { result = result.replace(/_+/g, "_"); // remove any leading underscore, unless it is followed by a number. - result = result.replace(/^_([^\d])/, "$1") + result = result.replace(/^_([^\d])/, "$1"); // get rid of all trailing underscores. result = result.replace(/_$/, ""); From 20e36dba53262e8efee437f52c7af673bc0a4e93 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 8 Nov 2017 13:18:23 -0800 Subject: [PATCH 33/73] Remove trailing whitespace from unit tests (#19836) --- src/harness/unittests/textChanges.ts | 8 ++++---- .../baselines/reference/textChanges/extractMethodLike.js | 8 ++++---- .../reference/textChanges/insertNodeInListAfter6.js | 6 +++--- .../reference/textChanges/insertNodeInListAfter7.js | 4 ++-- .../reference/textChanges/insertNodeInListAfter8.js | 6 +++--- .../reference/textChanges/insertNodeInListAfter9.js | 4 ++-- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/harness/unittests/textChanges.ts b/src/harness/unittests/textChanges.ts index c37e50a2565..aa0bbb253fa 100644 --- a/src/harness/unittests/textChanges.ts +++ b/src/harness/unittests/textChanges.ts @@ -122,9 +122,9 @@ namespace ts { { const text = ` -namespace M +namespace M { - namespace M2 + namespace M2 { function foo() { // comment 1 @@ -572,7 +572,7 @@ const x = 1;`; } { const text = ` -const x = 1, +const x = 1, y = 2;`; runSingleFileTest("insertNodeInListAfter6", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1))); @@ -583,7 +583,7 @@ const x = 1, } { const text = ` -const /*x*/ x = 1, +const /*x*/ x = 1, /*y*/ y = 2;`; runSingleFileTest("insertNodeInListAfter8", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), createVariableDeclaration("z", /*type*/ undefined, createLiteral(1))); diff --git a/tests/baselines/reference/textChanges/extractMethodLike.js b/tests/baselines/reference/textChanges/extractMethodLike.js index fa1d625dc4d..a566f76b8ed 100644 --- a/tests/baselines/reference/textChanges/extractMethodLike.js +++ b/tests/baselines/reference/textChanges/extractMethodLike.js @@ -1,8 +1,8 @@ ===ORIGINAL=== -namespace M +namespace M { - namespace M2 + namespace M2 { function foo() { // comment 1 @@ -22,7 +22,7 @@ namespace M } ===MODIFIED=== -namespace M +namespace M { function bar(): any { @@ -37,7 +37,7 @@ namespace M const y = 2; // comment 3 return 1; } - namespace M2 + namespace M2 { function foo() { // comment 1 diff --git a/tests/baselines/reference/textChanges/insertNodeInListAfter6.js b/tests/baselines/reference/textChanges/insertNodeInListAfter6.js index 06eae7372a9..4cffc3f1244 100644 --- a/tests/baselines/reference/textChanges/insertNodeInListAfter6.js +++ b/tests/baselines/reference/textChanges/insertNodeInListAfter6.js @@ -1,9 +1,9 @@ ===ORIGINAL=== -const x = 1, +const x = 1, y = 2; ===MODIFIED=== -const x = 1, - z = 1, +const x = 1, + z = 1, y = 2; \ No newline at end of file diff --git a/tests/baselines/reference/textChanges/insertNodeInListAfter7.js b/tests/baselines/reference/textChanges/insertNodeInListAfter7.js index bef01503683..afc1d97e155 100644 --- a/tests/baselines/reference/textChanges/insertNodeInListAfter7.js +++ b/tests/baselines/reference/textChanges/insertNodeInListAfter7.js @@ -1,9 +1,9 @@ ===ORIGINAL=== -const x = 1, +const x = 1, y = 2; ===MODIFIED=== -const x = 1, +const x = 1, y = 2, z = 1; \ No newline at end of file diff --git a/tests/baselines/reference/textChanges/insertNodeInListAfter8.js b/tests/baselines/reference/textChanges/insertNodeInListAfter8.js index e3c44b14274..fd325a4469a 100644 --- a/tests/baselines/reference/textChanges/insertNodeInListAfter8.js +++ b/tests/baselines/reference/textChanges/insertNodeInListAfter8.js @@ -1,9 +1,9 @@ ===ORIGINAL=== -const /*x*/ x = 1, +const /*x*/ x = 1, /*y*/ y = 2; ===MODIFIED=== -const /*x*/ x = 1, - z = 1, +const /*x*/ x = 1, + z = 1, /*y*/ y = 2; \ No newline at end of file diff --git a/tests/baselines/reference/textChanges/insertNodeInListAfter9.js b/tests/baselines/reference/textChanges/insertNodeInListAfter9.js index 510984b7574..951fcea64bf 100644 --- a/tests/baselines/reference/textChanges/insertNodeInListAfter9.js +++ b/tests/baselines/reference/textChanges/insertNodeInListAfter9.js @@ -1,9 +1,9 @@ ===ORIGINAL=== -const /*x*/ x = 1, +const /*x*/ x = 1, /*y*/ y = 2; ===MODIFIED=== -const /*x*/ x = 1, +const /*x*/ x = 1, /*y*/ y = 2, z = 1; \ No newline at end of file From d64a8f62f28e0f77fb8b5b681494e76cb35b3373 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 8 Nov 2017 13:28:35 -0800 Subject: [PATCH 34/73] Refactor user+dt runners into externalCompilerRunner --- Jakefile.js | 3 +- .../{dtRunner.ts => externalCompileRunner.ts} | 129 +++++++++--------- src/harness/runner.ts | 3 +- src/harness/tsconfig.json | 3 +- src/harness/userRunner.ts | 51 ------- 5 files changed, 70 insertions(+), 119 deletions(-) rename src/harness/{dtRunner.ts => externalCompileRunner.ts} (76%) delete mode 100644 src/harness/userRunner.ts diff --git a/Jakefile.js b/Jakefile.js index a133d0dba32..147270e0a59 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -105,8 +105,7 @@ var harnessCoreSources = [ "projectsRunner.ts", "loggedIO.ts", "rwcRunner.ts", - "userRunner.ts", - "dtRunner.ts", + "externalCompileRunner.ts", "test262Runner.ts", "./parallel/shared.ts", "./parallel/host.ts", diff --git a/src/harness/dtRunner.ts b/src/harness/externalCompileRunner.ts similarity index 76% rename from src/harness/dtRunner.ts rename to src/harness/externalCompileRunner.ts index 3b739b28f1c..8ca0be807bf 100644 --- a/src/harness/dtRunner.ts +++ b/src/harness/externalCompileRunner.ts @@ -1,62 +1,67 @@ -/// -/// -class DefinitelyTypedRunner extends RunnerBase { - private static readonly testDir = "../DefinitelyTyped/types/"; - - public workingDirectory = DefinitelyTypedRunner.testDir; - - public enumerateTestFiles() { - return Harness.IO.getDirectories(DefinitelyTypedRunner.testDir); - } - - public kind(): TestRunnerKind { - return "dt"; - } - - /** Setup the runner's tests so that they are ready to be executed by the harness - * The first test should be a describe/it block that sets up the harness's compiler instance appropriately - */ - public initializeTests(): void { - // Read in and evaluate the test list - const testList = this.tests && this.tests.length ? this.tests : this.enumerateTestFiles(); - - describe(`${this.kind()} code samples`, () => { - for (const test of testList) { - this.runTest(test); - } - }); - } - - private runTest(directoryName: string) { - describe(directoryName, () => { - const cp = require("child_process"); - const path = require("path"); - const fs = require("fs"); - - it("should build successfully", () => { - const cwd = path.join(__dirname, "../../", DefinitelyTypedRunner.testDir, directoryName); - const timeout = 600000; // 600s = 10 minutes - if (fs.existsSync(path.join(cwd, "package.json"))) { - if (fs.existsSync(path.join(cwd, "package-lock.json"))) { - fs.unlinkSync(path.join(cwd, "package-lock.json")); - } - const stdio = isWorker ? "pipe" : "inherit"; - const install = cp.spawnSync(`npm`, ["i"], { cwd, timeout, shell: true, stdio }); - if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed!`); - } - Harness.Baseline.runBaseline(`${this.kind()}/${directoryName}.log`, () => { - const result = cp.spawnSync(`node`, [path.join(__dirname, "tsc.js")], { cwd, timeout, shell: true }); - // tslint:disable:no-null-keyword - return result.status === 0 ? null : `Exit Code: ${result.status} -Standard output: -${result.stdout.toString().replace(/\r\n/g, "\n")} - - -Standard error: -${result.stderr.toString().replace(/\r\n/g, "\n")}`; - // tslint:enable:no-null-keyword - }); - }); - }); - } -} +/// +/// +abstract class ExternalCompileRunnerBase extends RunnerBase { + abstract testDir: string; + public enumerateTestFiles() { + return Harness.IO.getDirectories(this.testDir); + } + /** Setup the runner's tests so that they are ready to be executed by the harness + * The first test should be a describe/it block that sets up the harness's compiler instance appropriately + */ + public initializeTests(): void { + // Read in and evaluate the test list + const testList = this.tests && this.tests.length ? this.tests : this.enumerateTestFiles(); + + describe(`${this.kind()} code samples`, () => { + for (const test of testList) { + this.runTest(test); + } + }); + } + private runTest(directoryName: string) { + describe(directoryName, () => { + const cp = require("child_process"); + const path = require("path"); + const fs = require("fs"); + + it("should build successfully", () => { + const cwd = path.join(__dirname, "../../", this.testDir, directoryName); + const timeout = 600000; // 600s = 10 minutes + if (fs.existsSync(path.join(cwd, "package.json"))) { + if (fs.existsSync(path.join(cwd, "package-lock.json"))) { + fs.unlinkSync(path.join(cwd, "package-lock.json")); + } + const stdio = isWorker ? "pipe" : "inherit"; + const install = cp.spawnSync(`npm`, ["i"], { cwd, timeout, shell: true, stdio }); + if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed!`); + } + Harness.Baseline.runBaseline(`${this.kind()}/${directoryName}.log`, () => { + const result = cp.spawnSync(`node`, [path.join(__dirname, "tsc.js")], { cwd, timeout, shell: true }); + // tslint:disable-next-line:no-null-keyword + return result.status === 0 ? null : `Exit Code: ${result.status} +Standard output: +${result.stdout.toString().replace(/\r\n/g, "\n")} + + +Standard error: +${result.stderr.toString().replace(/\r\n/g, "\n")}`; + }); + }); + }); + } +} + +class UserCodeRunner extends ExternalCompileRunnerBase { + public readonly testDir = "tests/cases/user/"; + public kind(): TestRunnerKind { + return "user"; + } +} + +class DefinitelyTypedRunner extends ExternalCompileRunnerBase { + public readonly testDir = "../DefinitelyTyped/types/"; + public workingDirectory = this.testDir; + public kind(): TestRunnerKind { + return "dt"; + } +} diff --git a/src/harness/runner.ts b/src/harness/runner.ts index 0a9a7d3428d..a1210591090 100644 --- a/src/harness/runner.ts +++ b/src/harness/runner.ts @@ -18,8 +18,7 @@ /// /// /// -/// -/// +/// /// /// diff --git a/src/harness/tsconfig.json b/src/harness/tsconfig.json index 96f1999e9e8..1ab2cb955c8 100644 --- a/src/harness/tsconfig.json +++ b/src/harness/tsconfig.json @@ -92,8 +92,7 @@ "projectsRunner.ts", "loggedIO.ts", "rwcRunner.ts", - "userRunner.ts", - "definitelyRunner.ts", + "externalCompileRunner.ts", "test262Runner.ts", "./parallel/shared.ts", "./parallel/host.ts", diff --git a/src/harness/userRunner.ts b/src/harness/userRunner.ts deleted file mode 100644 index 61a46d7e84f..00000000000 --- a/src/harness/userRunner.ts +++ /dev/null @@ -1,51 +0,0 @@ -/// -/// -class UserCodeRunner extends RunnerBase { - private static readonly testDir = "tests/cases/user/"; - public enumerateTestFiles() { - return Harness.IO.getDirectories(UserCodeRunner.testDir); - } - - public kind(): TestRunnerKind { - return "user"; - } - - /** Setup the runner's tests so that they are ready to be executed by the harness - * The first test should be a describe/it block that sets up the harness's compiler instance appropriately - */ - public initializeTests(): void { - // Read in and evaluate the test list - const testList = this.tests && this.tests.length ? this.tests : this.enumerateTestFiles(); - - describe(`${this.kind()} code samples`, () => { - for (const test of testList) { - this.runTest(test); - } - }); - } - - private runTest(directoryName: string) { - describe(directoryName, () => { - const cp = require("child_process"); - const path = require("path"); - - it("should build successfully", () => { - const cwd = path.join(__dirname, "../../", UserCodeRunner.testDir, directoryName); - const timeout = 600000; // 10 minutes - const stdio = isWorker ? "pipe" : "inherit"; - const install = cp.spawnSync(`npm`, ["i"], { cwd, timeout, shell: true, stdio }); - if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed!`); - Harness.Baseline.runBaseline(`${this.kind()}/${directoryName}.log`, () => { - const result = cp.spawnSync(`node`, [path.join(__dirname, "tsc.js")], { cwd, timeout, shell: true }); - return `Exit Code: ${result.status} -Standard output: -${result.stdout.toString().replace(/\r\n/g, "\n")} - - -Standard error: -${result.stderr.toString().replace(/\r\n/g, "\n")}`; - }); - }); - }); - } -} From 397b5497a33ce30be6d86ecd86576287e42073a3 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 8 Nov 2017 13:29:28 -0800 Subject: [PATCH 35/73] Remove positive baselines for user tests --- tests/baselines/reference/user/ajv.log | 6 ------ tests/baselines/reference/user/antd.log | 6 ------ tests/baselines/reference/user/axios.log | 6 ------ tests/baselines/reference/user/bignumber.js.log | 6 ------ tests/baselines/reference/user/discord.js.log | 6 ------ tests/baselines/reference/user/eventemitter2.log | 6 ------ tests/baselines/reference/user/eventemitter3.log | 6 ------ tests/baselines/reference/user/firebase.log | 6 ------ tests/baselines/reference/user/github.log | 6 ------ tests/baselines/reference/user/immutable.log | 6 ------ tests/baselines/reference/user/isobject.log | 6 ------ tests/baselines/reference/user/jimp.log | 6 ------ tests/baselines/reference/user/jsonschema.log | 6 ------ tests/baselines/reference/user/keycode.log | 6 ------ tests/baselines/reference/user/localforage.log | 6 ------ tests/baselines/reference/user/log4js.log | 6 ------ tests/baselines/reference/user/mobx.log | 6 ------ tests/baselines/reference/user/moment.log | 6 ------ tests/baselines/reference/user/mqtt.log | 6 ------ tests/baselines/reference/user/parse5.log | 6 ------ tests/baselines/reference/user/portfinder.log | 6 ------ tests/baselines/reference/user/postcss.log | 6 ------ tests/baselines/reference/user/protobufjs.log | 6 ------ tests/baselines/reference/user/redux.log | 6 ------ tests/baselines/reference/user/reselect.log | 6 ------ tests/baselines/reference/user/should.log | 6 ------ tests/baselines/reference/user/sift.log | 6 ------ tests/baselines/reference/user/soap.log | 6 ------ tests/baselines/reference/user/sugar.log | 6 ------ tests/baselines/reference/user/tslint.log | 6 ------ tests/baselines/reference/user/vue.log | 6 ------ tests/baselines/reference/user/vuex.log | 6 ------ tests/baselines/reference/user/xlsx.log | 6 ------ tests/baselines/reference/user/xpath.log | 6 ------ tests/baselines/reference/user/zone.js.log | 6 ------ 35 files changed, 210 deletions(-) delete mode 100644 tests/baselines/reference/user/ajv.log delete mode 100644 tests/baselines/reference/user/antd.log delete mode 100644 tests/baselines/reference/user/axios.log delete mode 100644 tests/baselines/reference/user/bignumber.js.log delete mode 100644 tests/baselines/reference/user/discord.js.log delete mode 100644 tests/baselines/reference/user/eventemitter2.log delete mode 100644 tests/baselines/reference/user/eventemitter3.log delete mode 100644 tests/baselines/reference/user/firebase.log delete mode 100644 tests/baselines/reference/user/github.log delete mode 100644 tests/baselines/reference/user/immutable.log delete mode 100644 tests/baselines/reference/user/isobject.log delete mode 100644 tests/baselines/reference/user/jimp.log delete mode 100644 tests/baselines/reference/user/jsonschema.log delete mode 100644 tests/baselines/reference/user/keycode.log delete mode 100644 tests/baselines/reference/user/localforage.log delete mode 100644 tests/baselines/reference/user/log4js.log delete mode 100644 tests/baselines/reference/user/mobx.log delete mode 100644 tests/baselines/reference/user/moment.log delete mode 100644 tests/baselines/reference/user/mqtt.log delete mode 100644 tests/baselines/reference/user/parse5.log delete mode 100644 tests/baselines/reference/user/portfinder.log delete mode 100644 tests/baselines/reference/user/postcss.log delete mode 100644 tests/baselines/reference/user/protobufjs.log delete mode 100644 tests/baselines/reference/user/redux.log delete mode 100644 tests/baselines/reference/user/reselect.log delete mode 100644 tests/baselines/reference/user/should.log delete mode 100644 tests/baselines/reference/user/sift.log delete mode 100644 tests/baselines/reference/user/soap.log delete mode 100644 tests/baselines/reference/user/sugar.log delete mode 100644 tests/baselines/reference/user/tslint.log delete mode 100644 tests/baselines/reference/user/vue.log delete mode 100644 tests/baselines/reference/user/vuex.log delete mode 100644 tests/baselines/reference/user/xlsx.log delete mode 100644 tests/baselines/reference/user/xpath.log delete mode 100644 tests/baselines/reference/user/zone.js.log diff --git a/tests/baselines/reference/user/ajv.log b/tests/baselines/reference/user/ajv.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/ajv.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/antd.log b/tests/baselines/reference/user/antd.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/antd.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/axios.log b/tests/baselines/reference/user/axios.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/axios.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/bignumber.js.log b/tests/baselines/reference/user/bignumber.js.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/bignumber.js.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/discord.js.log b/tests/baselines/reference/user/discord.js.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/discord.js.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/eventemitter2.log b/tests/baselines/reference/user/eventemitter2.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/eventemitter2.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/eventemitter3.log b/tests/baselines/reference/user/eventemitter3.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/eventemitter3.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/firebase.log b/tests/baselines/reference/user/firebase.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/firebase.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/github.log b/tests/baselines/reference/user/github.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/github.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/immutable.log b/tests/baselines/reference/user/immutable.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/immutable.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/isobject.log b/tests/baselines/reference/user/isobject.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/isobject.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/jimp.log b/tests/baselines/reference/user/jimp.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/jimp.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/jsonschema.log b/tests/baselines/reference/user/jsonschema.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/jsonschema.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/keycode.log b/tests/baselines/reference/user/keycode.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/keycode.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/localforage.log b/tests/baselines/reference/user/localforage.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/localforage.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/log4js.log b/tests/baselines/reference/user/log4js.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/log4js.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/mobx.log b/tests/baselines/reference/user/mobx.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/mobx.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/moment.log b/tests/baselines/reference/user/moment.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/moment.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/mqtt.log b/tests/baselines/reference/user/mqtt.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/mqtt.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/parse5.log b/tests/baselines/reference/user/parse5.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/parse5.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/portfinder.log b/tests/baselines/reference/user/portfinder.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/portfinder.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/postcss.log b/tests/baselines/reference/user/postcss.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/postcss.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/protobufjs.log b/tests/baselines/reference/user/protobufjs.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/protobufjs.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/redux.log b/tests/baselines/reference/user/redux.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/redux.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/reselect.log b/tests/baselines/reference/user/reselect.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/reselect.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/should.log b/tests/baselines/reference/user/should.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/should.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/sift.log b/tests/baselines/reference/user/sift.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/sift.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/soap.log b/tests/baselines/reference/user/soap.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/soap.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/sugar.log b/tests/baselines/reference/user/sugar.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/sugar.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/tslint.log b/tests/baselines/reference/user/tslint.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/tslint.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/vue.log b/tests/baselines/reference/user/vue.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/vue.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/vuex.log b/tests/baselines/reference/user/vuex.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/vuex.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/xlsx.log b/tests/baselines/reference/user/xlsx.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/xlsx.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/xpath.log b/tests/baselines/reference/user/xpath.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/xpath.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: diff --git a/tests/baselines/reference/user/zone.js.log b/tests/baselines/reference/user/zone.js.log deleted file mode 100644 index 15b10503c1f..00000000000 --- a/tests/baselines/reference/user/zone.js.log +++ /dev/null @@ -1,6 +0,0 @@ -Exit Code: 0 -Standard output: - - - -Standard error: From 5ad7e9516b1e1b3cf644497dfc8f66f6b9bbaed6 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 8 Nov 2017 13:39:03 -0800 Subject: [PATCH 36/73] Remove unnecessary wrapper classes in ts.formatting.Rule (#19744) * Remove unnecessary wrapper classes in ts.formatting.Rule * RulesProvider -> immutable FormatContext * Remove Rules class, just use a list of rules * Remove Shared namespace, replace Shared.TokenRange with TokenRange * Simplify TokenRange * Separate Rule and RuleSpec * Move FormattingRequestKind to formattingContext.ts * Simplify references * Fix lint * Revert removal of trailing newlines --- src/harness/tsconfig.json | 9 - src/harness/unittests/extractTestHelpers.ts | 52 +- src/harness/unittests/textChanges.ts | 56 +- src/services/codefixes/importFixes.ts | 2 +- src/services/completions.ts | 8 +- src/services/formatting/formatting.ts | 75 +- src/services/formatting/formattingContext.ts | 11 +- .../formatting/formattingRequestKind.ts | 13 - src/services/formatting/references.ts | 12 - src/services/formatting/rule.ts | 34 +- src/services/formatting/ruleAction.ts | 11 - src/services/formatting/ruleDescriptor.ts | 30 - src/services/formatting/ruleFlag.ts | 10 - src/services/formatting/ruleOperation.ts | 21 - .../formatting/ruleOperationContext.ts | 32 - src/services/formatting/rules.ts | 1490 +++++++---------- src/services/formatting/rulesMap.ts | 197 +-- src/services/formatting/rulesProvider.ts | 30 - src/services/formatting/smartIndenter.ts | 2 - src/services/formatting/tokenRange.ts | 124 -- .../refactors/convertFunctionToEs6Class.ts | 2 +- src/services/services.ts | 47 +- src/services/textChanges.ts | 16 +- src/services/utilities.ts | 25 +- 24 files changed, 853 insertions(+), 1456 deletions(-) delete mode 100644 src/services/formatting/formattingRequestKind.ts delete mode 100644 src/services/formatting/references.ts delete mode 100644 src/services/formatting/ruleAction.ts delete mode 100644 src/services/formatting/ruleDescriptor.ts delete mode 100644 src/services/formatting/ruleFlag.ts delete mode 100644 src/services/formatting/ruleOperation.ts delete mode 100644 src/services/formatting/ruleOperationContext.ts delete mode 100644 src/services/formatting/rulesProvider.ts delete mode 100644 src/services/formatting/tokenRange.ts diff --git a/src/harness/tsconfig.json b/src/harness/tsconfig.json index 6e61b7690bc..45430b5c506 100644 --- a/src/harness/tsconfig.json +++ b/src/harness/tsconfig.json @@ -60,20 +60,11 @@ "../services/jsTyping.ts", "../services/formatting/formatting.ts", "../services/formatting/formattingContext.ts", - "../services/formatting/formattingRequestKind.ts", "../services/formatting/formattingScanner.ts", - "../services/formatting/references.ts", "../services/formatting/rule.ts", - "../services/formatting/ruleAction.ts", - "../services/formatting/ruleDescriptor.ts", - "../services/formatting/ruleFlag.ts", - "../services/formatting/ruleOperation.ts", - "../services/formatting/ruleOperationContext.ts", "../services/formatting/rules.ts", "../services/formatting/rulesMap.ts", - "../services/formatting/rulesProvider.ts", "../services/formatting/smartIndenter.ts", - "../services/formatting/tokenRange.ts", "../services/codeFixProvider.ts", "../services/codefixes/fixes.ts", "../services/codefixes/helpers.ts", diff --git a/src/harness/unittests/extractTestHelpers.ts b/src/harness/unittests/extractTestHelpers.ts index ae3f663aa51..a04f443c3c9 100644 --- a/src/harness/unittests/extractTestHelpers.ts +++ b/src/harness/unittests/extractTestHelpers.ts @@ -67,33 +67,27 @@ namespace ts { } export const newLineCharacter = "\n"; - export const getRuleProvider = memoize(getRuleProviderInternal); - function getRuleProviderInternal() { - const options = { - indentSize: 4, - tabSize: 4, - newLineCharacter, - convertTabsToSpaces: true, - indentStyle: ts.IndentStyle.Smart, - insertSpaceAfterConstructor: false, - insertSpaceAfterCommaDelimiter: true, - insertSpaceAfterSemicolonInForStatements: true, - insertSpaceBeforeAndAfterBinaryOperators: true, - insertSpaceAfterKeywordsInControlFlowStatements: true, - insertSpaceAfterFunctionKeywordForAnonymousFunctions: false, - insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, - insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, - insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true, - insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false, - insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false, - insertSpaceBeforeFunctionParenthesis: false, - placeOpenBraceOnNewLineForFunctions: false, - placeOpenBraceOnNewLineForControlBlocks: false, - }; - const rulesProvider = new formatting.RulesProvider(); - rulesProvider.ensureUpToDate(options); - return rulesProvider; - } + export const testFormatOptions: ts.FormatCodeSettings = { + indentSize: 4, + tabSize: 4, + newLineCharacter, + convertTabsToSpaces: true, + indentStyle: ts.IndentStyle.Smart, + insertSpaceAfterConstructor: false, + insertSpaceAfterCommaDelimiter: true, + insertSpaceAfterSemicolonInForStatements: true, + insertSpaceBeforeAndAfterBinaryOperators: true, + insertSpaceAfterKeywordsInControlFlowStatements: true, + insertSpaceAfterFunctionKeywordForAnonymousFunctions: false, + insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, + insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, + insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true, + insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false, + insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false, + insertSpaceBeforeFunctionParenthesis: false, + placeOpenBraceOnNewLineForFunctions: false, + placeOpenBraceOnNewLineForControlBlocks: false, + }; const notImplementedHost: LanguageServiceHost = { getCompilationSettings: notImplemented, @@ -133,7 +127,7 @@ namespace ts { startPosition: selectionRange.start, endPosition: selectionRange.end, host: notImplementedHost, - rulesProvider: getRuleProvider() + formatContext: formatting.getFormatContext(testFormatOptions), }; const rangeToExtract = refactor.extractSymbol.getRangeToExtract(sourceFile, createTextSpanFromBounds(selectionRange.start, selectionRange.end)); assert.equal(rangeToExtract.errors, undefined, rangeToExtract.errors && "Range error: " + rangeToExtract.errors[0].messageText); @@ -197,7 +191,7 @@ namespace ts { startPosition: selectionRange.start, endPosition: selectionRange.end, host: notImplementedHost, - rulesProvider: getRuleProvider() + formatContext: formatting.getFormatContext(testFormatOptions), }; const rangeToExtract = refactor.extractSymbol.getRangeToExtract(sourceFile, createTextSpanFromBounds(selectionRange.start, selectionRange.end)); assert.isUndefined(rangeToExtract.errors, rangeToExtract.errors && "Range error: " + rangeToExtract.errors[0].messageText); diff --git a/src/harness/unittests/textChanges.ts b/src/harness/unittests/textChanges.ts index aa0bbb253fa..ed571b37399 100644 --- a/src/harness/unittests/textChanges.ts +++ b/src/harness/unittests/textChanges.ts @@ -23,60 +23,8 @@ namespace ts { const printerOptions = { newLine: NewLineKind.LineFeed }; const newLineCharacter = getNewLineCharacter(printerOptions); - const getRuleProviderDefault = memoize(() => { - const options = { - indentSize: 4, - tabSize: 4, - newLineCharacter, - convertTabsToSpaces: true, - indentStyle: ts.IndentStyle.Smart, - insertSpaceAfterConstructor: false, - insertSpaceAfterCommaDelimiter: true, - insertSpaceAfterSemicolonInForStatements: true, - insertSpaceBeforeAndAfterBinaryOperators: true, - insertSpaceAfterKeywordsInControlFlowStatements: true, - insertSpaceAfterFunctionKeywordForAnonymousFunctions: false, - insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, - insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, - insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true, - insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false, - insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false, - insertSpaceBeforeFunctionParenthesis: false, - placeOpenBraceOnNewLineForFunctions: false, - placeOpenBraceOnNewLineForControlBlocks: false, - }; - const rulesProvider = new formatting.RulesProvider(); - rulesProvider.ensureUpToDate(options); - return rulesProvider; - }); - const getRuleProviderNewlineBrace = memoize(() => { - const options = { - indentSize: 4, - tabSize: 4, - newLineCharacter, - convertTabsToSpaces: true, - indentStyle: ts.IndentStyle.Smart, - insertSpaceAfterConstructor: false, - insertSpaceAfterCommaDelimiter: true, - insertSpaceAfterSemicolonInForStatements: true, - insertSpaceBeforeAndAfterBinaryOperators: true, - insertSpaceAfterKeywordsInControlFlowStatements: true, - insertSpaceAfterFunctionKeywordForAnonymousFunctions: false, - insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, - insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, - insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true, - insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces: false, - insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces: false, - insertSpaceBeforeFunctionParenthesis: false, - placeOpenBraceOnNewLineForFunctions: true, - placeOpenBraceOnNewLineForControlBlocks: false, - }; - const rulesProvider = new formatting.RulesProvider(); - rulesProvider.ensureUpToDate(options); - return rulesProvider; - }); - function getRuleProvider(placeOpenBraceOnNewLineForFunctions: boolean) { - return placeOpenBraceOnNewLineForFunctions ? getRuleProviderNewlineBrace() : getRuleProviderDefault(); + function getRuleProvider(placeOpenBraceOnNewLineForFunctions: boolean): formatting.FormatContext { + return formatting.getFormatContext(placeOpenBraceOnNewLineForFunctions ? { ...testFormatOptions, placeOpenBraceOnNewLineForFunctions: true } : testFormatOptions); } // validate that positions that were recovered from the printed text actually match positions that will be created if the same text is parsed. diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index e0e57801cf8..a0c7ffd75ea 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -166,7 +166,7 @@ namespace ts.codefix { return { host: context.host, newLineCharacter: context.newLineCharacter, - rulesProvider: context.rulesProvider, + formatContext: context.formatContext, sourceFile: context.sourceFile, checker, compilerOptions: context.program.getCompilerOptions(), diff --git a/src/services/completions.ts b/src/services/completions.ts index 3c233f4dbe8..f66242ca864 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -415,7 +415,7 @@ namespace ts.Completions { entryId: CompletionEntryIdentifier, allSourceFiles: ReadonlyArray, host: LanguageServiceHost, - rulesProvider: formatting.RulesProvider, + formatContext: formatting.FormatContext, ): CompletionEntryDetails { const { name, source } = entryId; // Compute all the completion symbols again. @@ -436,7 +436,7 @@ namespace ts.Completions { } case "symbol": { const { symbol, location, symbolToOriginInfoMap } = symbolCompletion; - const codeActions = getCompletionEntryCodeActions(symbolToOriginInfoMap, symbol, typeChecker, host, compilerOptions, sourceFile, rulesProvider); + const codeActions = getCompletionEntryCodeActions(symbolToOriginInfoMap, symbol, typeChecker, host, compilerOptions, sourceFile, formatContext); const kindModifiers = SymbolDisplay.getSymbolModifiers(symbol); const { displayParts, documentation, symbolKind, tags } = SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, location, location, SemanticMeaning.All); return { name, kindModifiers, kind: symbolKind, displayParts, documentation, tags, codeActions, source: source === undefined ? undefined : [textPart(source)] }; @@ -467,7 +467,7 @@ namespace ts.Completions { host: LanguageServiceHost, compilerOptions: CompilerOptions, sourceFile: SourceFile, - rulesProvider: formatting.RulesProvider, + formatContext: formatting.FormatContext, ): CodeAction[] | undefined { const symbolOriginInfo = symbolToOriginInfoMap[getSymbolId(symbol)]; if (!symbolOriginInfo) { @@ -481,7 +481,7 @@ namespace ts.Completions { newLineCharacter: host.getNewLine(), compilerOptions, sourceFile, - rulesProvider, + formatContext, symbolName: symbol.name, getCanonicalFileName: createGetCanonicalFileName(host.useCaseSensitiveFileNames ? host.useCaseSensitiveFileNames() : false), symbolToken: undefined, diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index 529fdae0545..b8122827491 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -1,10 +1,14 @@ -/// -/// -/// -/// +/// +/// +/// +/// /* @internal */ namespace ts.formatting { + export interface FormatContext { + readonly options: ts.FormatCodeSettings; + readonly getRule: ts.formatting.RulesMap; + } export interface TextRangeWithKind extends TextRange { kind: SyntaxKind; @@ -67,7 +71,7 @@ namespace ts.formatting { delta: number; } - export function formatOnEnter(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[] { + export function formatOnEnter(position: number, sourceFile: SourceFile, formatContext: FormatContext): TextChange[] { const line = sourceFile.getLineAndCharacterOfPosition(position).line; if (line === 0) { return []; @@ -93,15 +97,15 @@ namespace ts.formatting { // end value is exclusive so add 1 to the result end: endOfFormatSpan + 1 }; - return formatSpan(span, sourceFile, options, rulesProvider, FormattingRequestKind.FormatOnEnter); + return formatSpan(span, sourceFile, formatContext, FormattingRequestKind.FormatOnEnter); } - export function formatOnSemicolon(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[] { + export function formatOnSemicolon(position: number, sourceFile: SourceFile, formatContext: FormatContext): TextChange[] { const semicolon = findImmediatelyPrecedingTokenOfKind(position, SyntaxKind.SemicolonToken, sourceFile); - return formatNodeLines(findOutermostNodeWithinListLevel(semicolon), sourceFile, options, rulesProvider, FormattingRequestKind.FormatOnSemicolon); + return formatNodeLines(findOutermostNodeWithinListLevel(semicolon), sourceFile, formatContext, FormattingRequestKind.FormatOnSemicolon); } - export function formatOnOpeningCurly(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[] { + export function formatOnOpeningCurly(position: number, sourceFile: SourceFile, formatContext: FormatContext): TextChange[] { const openingCurly = findImmediatelyPrecedingTokenOfKind(position, SyntaxKind.OpenBraceToken, sourceFile); if (!openingCurly) { return []; @@ -126,29 +130,29 @@ namespace ts.formatting { end: position }; - return formatSpan(textRange, sourceFile, options, rulesProvider, FormattingRequestKind.FormatOnOpeningCurlyBrace); + return formatSpan(textRange, sourceFile, formatContext, FormattingRequestKind.FormatOnOpeningCurlyBrace); } - export function formatOnClosingCurly(position: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[] { + export function formatOnClosingCurly(position: number, sourceFile: SourceFile, formatContext: FormatContext): TextChange[] { const precedingToken = findImmediatelyPrecedingTokenOfKind(position, SyntaxKind.CloseBraceToken, sourceFile); - return formatNodeLines(findOutermostNodeWithinListLevel(precedingToken), sourceFile, options, rulesProvider, FormattingRequestKind.FormatOnClosingCurlyBrace); + return formatNodeLines(findOutermostNodeWithinListLevel(precedingToken), sourceFile, formatContext, FormattingRequestKind.FormatOnClosingCurlyBrace); } - export function formatDocument(sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[] { + export function formatDocument(sourceFile: SourceFile, formatContext: FormatContext): TextChange[] { const span = { pos: 0, end: sourceFile.text.length }; - return formatSpan(span, sourceFile, options, rulesProvider, FormattingRequestKind.FormatDocument); + return formatSpan(span, sourceFile, formatContext, FormattingRequestKind.FormatDocument); } - export function formatSelection(start: number, end: number, sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeSettings): TextChange[] { + export function formatSelection(start: number, end: number, sourceFile: SourceFile, formatContext: FormatContext): TextChange[] { // format from the beginning of the line const span = { pos: getLineStartPositionForPosition(start, sourceFile), end, }; - return formatSpan(span, sourceFile, options, rulesProvider, FormattingRequestKind.FormatSelection); + return formatSpan(span, sourceFile, formatContext, FormattingRequestKind.FormatSelection); } /** @@ -337,7 +341,7 @@ namespace ts.formatting { } /* @internal */ - export function formatNodeGivenIndentation(node: Node, sourceFileLike: SourceFileLike, languageVariant: LanguageVariant, initialIndentation: number, delta: number, rulesProvider: RulesProvider): TextChange[] { + export function formatNodeGivenIndentation(node: Node, sourceFileLike: SourceFileLike, languageVariant: LanguageVariant, initialIndentation: number, delta: number, formatContext: FormatContext): TextChange[] { const range = { pos: 0, end: sourceFileLike.text.length }; return getFormattingScanner(sourceFileLike.text, languageVariant, range.pos, range.end, scanner => formatSpanWorker( range, @@ -345,14 +349,13 @@ namespace ts.formatting { initialIndentation, delta, scanner, - rulesProvider.getFormatOptions(), - rulesProvider, + formatContext, FormattingRequestKind.FormatSelection, _ => false, // assume that node does not have any errors sourceFileLike)); } - function formatNodeLines(node: Node, sourceFile: SourceFile, options: FormatCodeSettings, rulesProvider: RulesProvider, requestKind: FormattingRequestKind): TextChange[] { + function formatNodeLines(node: Node, sourceFile: SourceFile, formatContext: FormatContext, requestKind: FormattingRequestKind): TextChange[] { if (!node) { return []; } @@ -362,24 +365,19 @@ namespace ts.formatting { end: node.end }; - return formatSpan(span, sourceFile, options, rulesProvider, requestKind); + return formatSpan(span, sourceFile, formatContext, requestKind); } - function formatSpan(originalRange: TextRange, - sourceFile: SourceFile, - options: FormatCodeSettings, - rulesProvider: RulesProvider, - requestKind: FormattingRequestKind): TextChange[] { + function formatSpan(originalRange: TextRange, sourceFile: SourceFile, formatContext: FormatContext, requestKind: FormattingRequestKind): TextChange[] { // find the smallest node that fully wraps the range and compute the initial indentation for the node const enclosingNode = findEnclosingNode(originalRange, sourceFile); return getFormattingScanner(sourceFile.text, sourceFile.languageVariant, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end, scanner => formatSpanWorker( originalRange, enclosingNode, - SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, options), - getOwnOrInheritedDelta(enclosingNode, options, sourceFile), + SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, formatContext.options), + getOwnOrInheritedDelta(enclosingNode, formatContext.options, sourceFile), scanner, - options, - rulesProvider, + formatContext, requestKind, prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange), sourceFile)); @@ -390,8 +388,7 @@ namespace ts.formatting { initialIndentation: number, delta: number, formattingScanner: FormattingScanner, - options: FormatCodeSettings, - rulesProvider: RulesProvider, + { options, getRule }: FormatContext, requestKind: FormattingRequestKind, rangeContainsError: (r: TextRange) => boolean, sourceFile: SourceFileLike): TextChange[] { @@ -917,14 +914,14 @@ namespace ts.formatting { formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode); - const rule = rulesProvider.getRulesMap().GetRule(formattingContext); + const rule = getRule(formattingContext); let trimTrailingWhitespaces: boolean; let lineAdded: boolean; if (rule) { applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine); - if (rule.operation.action & (RuleAction.Space | RuleAction.Delete) && currentStartLine !== previousStartLine) { + if (rule.action & (RuleAction.Space | RuleAction.Delete) && currentStartLine !== previousStartLine) { lineAdded = false; // Handle the case where the next line is moved to be the end of this line. // In this case we don't indent the next line in the next pass. @@ -932,7 +929,7 @@ namespace ts.formatting { dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ false); } } - else if (rule.operation.action & RuleAction.NewLine && currentStartLine === previousStartLine) { + else if (rule.action & RuleAction.NewLine && currentStartLine === previousStartLine) { lineAdded = true; // Handle the case where token2 is moved to the new line. // In this case we indent token2 in the next pass but we set @@ -943,7 +940,7 @@ namespace ts.formatting { } // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line - trimTrailingWhitespaces = !(rule.operation.action & RuleAction.Delete) && rule.flag !== RuleFlags.CanDeleteNewLines; + trimTrailingWhitespaces = !(rule.action & RuleAction.Delete) && rule.flags !== RuleFlags.CanDeleteNewLines; } else { trimTrailingWhitespaces = true; @@ -1118,7 +1115,7 @@ namespace ts.formatting { currentRange: TextRangeWithKind, currentStartLine: number): void { - switch (rule.operation.action) { + switch (rule.action) { case RuleAction.Ignore: // no action required return; @@ -1132,7 +1129,7 @@ namespace ts.formatting { // exit early if we on different lines and rule cannot change number of newlines // if line1 and line2 are on subsequent lines then no edits are required - ok to exit // if line1 and line2 are separated with more than one newline - ok to exit since we cannot delete extra new lines - if (rule.flag !== RuleFlags.CanDeleteNewLines && previousStartLine !== currentStartLine) { + if (rule.flags !== RuleFlags.CanDeleteNewLines && previousStartLine !== currentStartLine) { return; } @@ -1144,7 +1141,7 @@ namespace ts.formatting { break; case RuleAction.Space: // exit early if we on different lines and rule cannot change number of newlines - if (rule.flag !== RuleFlags.CanDeleteNewLines && previousStartLine !== currentStartLine) { + if (rule.flags !== RuleFlags.CanDeleteNewLines && previousStartLine !== currentStartLine) { return; } diff --git a/src/services/formatting/formattingContext.ts b/src/services/formatting/formattingContext.ts index 043df72f434..2ba987e4af3 100644 --- a/src/services/formatting/formattingContext.ts +++ b/src/services/formatting/formattingContext.ts @@ -1,7 +1,14 @@ -/// - /* @internal */ namespace ts.formatting { + export const enum FormattingRequestKind { + FormatDocument, + FormatSelection, + FormatOnEnter, + FormatOnSemicolon, + FormatOnOpeningCurlyBrace, + FormatOnClosingCurlyBrace + } + export class FormattingContext { public currentTokenSpan: TextRangeWithKind; public nextTokenSpan: TextRangeWithKind; diff --git a/src/services/formatting/formattingRequestKind.ts b/src/services/formatting/formattingRequestKind.ts deleted file mode 100644 index 6c671e1b888..00000000000 --- a/src/services/formatting/formattingRequestKind.ts +++ /dev/null @@ -1,13 +0,0 @@ -/// - -/* @internal */ -namespace ts.formatting { - export const enum FormattingRequestKind { - FormatDocument, - FormatSelection, - FormatOnEnter, - FormatOnSemicolon, - FormatOnOpeningCurlyBrace, - FormatOnClosingCurlyBrace - } -} \ No newline at end of file diff --git a/src/services/formatting/references.ts b/src/services/formatting/references.ts deleted file mode 100644 index 318f10c664e..00000000000 --- a/src/services/formatting/references.ts +++ /dev/null @@ -1,12 +0,0 @@ -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// \ No newline at end of file diff --git a/src/services/formatting/rule.ts b/src/services/formatting/rule.ts index 8fd432586b4..aa1bb6b43e9 100644 --- a/src/services/formatting/rule.ts +++ b/src/services/formatting/rule.ts @@ -1,14 +1,30 @@ -/// - /* @internal */ namespace ts.formatting { - export class Rule { + export interface Rule { // Used for debugging to identify each rule based on the property name it's assigned to. - public debugName?: string; - constructor( - readonly descriptor: RuleDescriptor, - readonly operation: RuleOperation, - readonly flag: RuleFlags = RuleFlags.None) { - } + readonly debugName: string; + readonly context: ReadonlyArray; + readonly action: RuleAction; + readonly flags: RuleFlags; + } + + export type ContextPredicate = (context: FormattingContext) => boolean; + export const anyContext: ReadonlyArray = emptyArray; + + export const enum RuleAction { + Ignore = 1 << 0, + Space = 1 << 1, + NewLine = 1 << 2, + Delete = 1 << 3, + } + + export const enum RuleFlags { + None, + CanDeleteNewLines, + } + + export interface TokenRange { + readonly tokens: ReadonlyArray; + readonly isSpecific: boolean; } } \ No newline at end of file diff --git a/src/services/formatting/ruleAction.ts b/src/services/formatting/ruleAction.ts deleted file mode 100644 index 13e9043e1c6..00000000000 --- a/src/services/formatting/ruleAction.ts +++ /dev/null @@ -1,11 +0,0 @@ -/// - -/* @internal */ -namespace ts.formatting { - export const enum RuleAction { - Ignore = 0x00000001, - Space = 0x00000002, - NewLine = 0x00000004, - Delete = 0x00000008 - } -} \ No newline at end of file diff --git a/src/services/formatting/ruleDescriptor.ts b/src/services/formatting/ruleDescriptor.ts deleted file mode 100644 index b8529496956..00000000000 --- a/src/services/formatting/ruleDescriptor.ts +++ /dev/null @@ -1,30 +0,0 @@ -/// - -/* @internal */ -namespace ts.formatting { - export class RuleDescriptor { - constructor(public leftTokenRange: Shared.TokenRange, public rightTokenRange: Shared.TokenRange) { - } - - public toString(): string { - return "[leftRange=" + this.leftTokenRange + "," + - "rightRange=" + this.rightTokenRange + "]"; - } - - static create1(left: SyntaxKind, right: SyntaxKind): RuleDescriptor { - return RuleDescriptor.create4(Shared.TokenRange.FromToken(left), Shared.TokenRange.FromToken(right)); - } - - static create2(left: Shared.TokenRange, right: SyntaxKind): RuleDescriptor { - return RuleDescriptor.create4(left, Shared.TokenRange.FromToken(right)); - } - - static create3(left: SyntaxKind, right: Shared.TokenRange): RuleDescriptor { - return RuleDescriptor.create4(Shared.TokenRange.FromToken(left), right); - } - - static create4(left: Shared.TokenRange, right: Shared.TokenRange): RuleDescriptor { - return new RuleDescriptor(left, right); - } - } -} \ No newline at end of file diff --git a/src/services/formatting/ruleFlag.ts b/src/services/formatting/ruleFlag.ts deleted file mode 100644 index 7619f232ad4..00000000000 --- a/src/services/formatting/ruleFlag.ts +++ /dev/null @@ -1,10 +0,0 @@ -/// - - -/* @internal */ -namespace ts.formatting { - export const enum RuleFlags { - None, - CanDeleteNewLines - } -} \ No newline at end of file diff --git a/src/services/formatting/ruleOperation.ts b/src/services/formatting/ruleOperation.ts deleted file mode 100644 index 462c27352d8..00000000000 --- a/src/services/formatting/ruleOperation.ts +++ /dev/null @@ -1,21 +0,0 @@ -/// - -/* @internal */ -namespace ts.formatting { - export class RuleOperation { - constructor(readonly context: RuleOperationContext, readonly action: RuleAction) {} - - public toString(): string { - return "[context=" + this.context + "," + - "action=" + this.action + "]"; - } - - static create1(action: RuleAction) { - return RuleOperation.create2(RuleOperationContext.any, action); - } - - static create2(context: RuleOperationContext, action: RuleAction) { - return new RuleOperation(context, action); - } - } -} \ No newline at end of file diff --git a/src/services/formatting/ruleOperationContext.ts b/src/services/formatting/ruleOperationContext.ts deleted file mode 100644 index c433d106372..00000000000 --- a/src/services/formatting/ruleOperationContext.ts +++ /dev/null @@ -1,32 +0,0 @@ -/// - -/* @internal */ -namespace ts.formatting { - - export class RuleOperationContext { - private readonly customContextChecks: ((context: FormattingContext) => boolean)[]; - - constructor(...funcs: ((context: FormattingContext) => boolean)[]) { - this.customContextChecks = funcs; - } - - static readonly any: RuleOperationContext = new RuleOperationContext(); - - public IsAny(): boolean { - return this === RuleOperationContext.any; - } - - public InContext(context: FormattingContext): boolean { - if (this.IsAny()) { - return true; - } - - for (const check of this.customContextChecks) { - if (!check(context)) { - return false; - } - } - return true; - } - } -} \ No newline at end of file diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index c5b59e818eb..8214ffd6f2d 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -1,929 +1,723 @@ -/// - /* @internal */ namespace ts.formatting { - // tslint:disable variable-name (TODO) - export class Rules { - public IgnoreBeforeComment: Rule; - public IgnoreAfterLineComment: Rule; + export interface RuleSpec { + readonly leftTokenRange: TokenRange; + readonly rightTokenRange: TokenRange; + readonly rule: Rule; + } - // Space after keyword but not before ; or : or ? - public NoSpaceBeforeSemicolon: Rule; - public NoSpaceBeforeColon: Rule; - public NoSpaceBeforeQuestionMark: Rule; - public SpaceAfterColon: Rule; - // insert space after '?' only when it is used in conditional operator - public SpaceAfterQuestionMarkInConditionalOperator: Rule; - // in other cases there should be no space between '?' and next token - public NoSpaceAfterQuestionMark: Rule; + export function getAllRules(): RuleSpec[] { + const allTokens: SyntaxKind[] = []; + for (let token = SyntaxKind.FirstToken; token <= SyntaxKind.LastToken; token++) { + allTokens.push(token); + } + function anyTokenExcept(token: SyntaxKind): TokenRange { + return { tokens: allTokens.filter(t => t !== token), isSpecific: false }; + } - public SpaceAfterSemicolon: Rule; + const anyToken: TokenRange = { tokens: allTokens, isSpecific: false }; + const anyTokenIncludingMultilineComments = tokenRangeFrom([...allTokens, SyntaxKind.MultiLineCommentTrivia]); + const keywords = tokenRangeFromRange(SyntaxKind.FirstKeyword, SyntaxKind.LastKeyword); + const binaryOperators = tokenRangeFromRange(SyntaxKind.FirstBinaryOperator, SyntaxKind.LastBinaryOperator); + const binaryKeywordOperators = [SyntaxKind.InKeyword, SyntaxKind.InstanceOfKeyword, SyntaxKind.OfKeyword, SyntaxKind.AsKeyword, SyntaxKind.IsKeyword]; + const unaryPrefixOperators = [SyntaxKind.PlusPlusToken, SyntaxKind.MinusMinusToken, SyntaxKind.TildeToken, SyntaxKind.ExclamationToken]; + const unaryPrefixExpressions = [ + SyntaxKind.NumericLiteral, SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, + SyntaxKind.OpenBraceToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]; + const unaryPreincrementExpressions = [SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]; + const unaryPostincrementExpressions = [SyntaxKind.Identifier, SyntaxKind.CloseParenToken, SyntaxKind.CloseBracketToken, SyntaxKind.NewKeyword]; + const unaryPredecrementExpressions = [SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]; + const unaryPostdecrementExpressions = [SyntaxKind.Identifier, SyntaxKind.CloseParenToken, SyntaxKind.CloseBracketToken, SyntaxKind.NewKeyword]; + const comments = [SyntaxKind.SingleLineCommentTrivia, SyntaxKind.MultiLineCommentTrivia]; + const typeNames = [SyntaxKind.Identifier, ...typeKeywords]; - // Space/new line after }. - public SpaceAfterCloseBrace: Rule; - - // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied - // Also should not apply to }) - public SpaceBetweenCloseBraceAndElse: Rule; - public SpaceBetweenCloseBraceAndWhile: Rule; - public NoSpaceAfterCloseBrace: Rule; - - // No space for dot - public NoSpaceBeforeDot: Rule; - public NoSpaceAfterDot: Rule; - - // No space before and after indexer - public NoSpaceBeforeOpenBracket: Rule; - public NoSpaceAfterCloseBracket: Rule; - - // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}. - public SpaceAfterOpenBrace: Rule; - public SpaceBeforeCloseBrace: Rule; - public NoSpaceAfterOpenBrace: Rule; - public NoSpaceBeforeCloseBrace: Rule; - public NoSpaceBetweenEmptyBraceBrackets: Rule; - - // Insert new line after { and before } in multi-line contexts. - public NewLineAfterOpenBraceInBlockContext: Rule; - - // For functions and control block place } on a new line [multi-line rule] - public NewLineBeforeCloseBraceInBlockContext: Rule; - - // Special handling of unary operators. - // Prefix operators generally shouldn't have a space between - // them and their target unary expression. - public NoSpaceAfterUnaryPrefixOperator: Rule; - public NoSpaceAfterUnaryPreincrementOperator: Rule; - public NoSpaceAfterUnaryPredecrementOperator: Rule; - public NoSpaceBeforeUnaryPostincrementOperator: Rule; - public NoSpaceBeforeUnaryPostdecrementOperator: Rule; - - // More unary operator special-casing. - // DevDiv 181814: Be careful when removing leading whitespace - // around unary operators. Examples: - // 1 - -2 --X--> 1--2 - // a + ++b --X--> a+++b - public SpaceAfterPostincrementWhenFollowedByAdd: Rule; - public SpaceAfterAddWhenFollowedByUnaryPlus: Rule; - public SpaceAfterAddWhenFollowedByPreincrement: Rule; - public SpaceAfterPostdecrementWhenFollowedBySubtract: Rule; - public SpaceAfterSubtractWhenFollowedByUnaryMinus: Rule; - public SpaceAfterSubtractWhenFollowedByPredecrement: Rule; - - public NoSpaceBeforeComma: Rule; - - public SpaceAfterCertainKeywords: Rule; - public NoSpaceAfterNewKeywordOnConstructorSignature: Rule; - public SpaceAfterLetConstInVariableDeclaration: Rule; - public NoSpaceBeforeOpenParenInFuncCall: Rule; - public SpaceAfterFunctionInFuncDecl: Rule; - public SpaceBeforeOpenParenInFuncDecl: Rule; - public NoSpaceBeforeOpenParenInFuncDecl: Rule; - public SpaceAfterVoidOperator: Rule; - - public NoSpaceBetweenReturnAndSemicolon: Rule; - - // Add a space between statements. All keywords except (do,else,case) has open/close parens after them. - // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any] - public SpaceBetweenStatements: Rule; - - // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter. - public SpaceAfterTryFinally: Rule; - - // For get/set members, we check for (identifier,identifier) since get/set don't have tokens and they are represented as just an identifier token. - // Though, we do extra check on the context to make sure we are dealing with get/set node. Example: - // get x() {} - // set x(val) {} - public SpaceAfterGetSetInMember: Rule; - - // Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options. - public SpaceBeforeBinaryKeywordOperator: Rule; - public SpaceAfterBinaryKeywordOperator: Rule; - - // TypeScript-specific rules - - // Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses - public SpaceAfterConstructor: Rule; - public NoSpaceAfterConstructor: Rule; - - // Use of module as a function call. e.g.: import m2 = module("m2"); - public NoSpaceAfterModuleImport: Rule; - - // Add a space around certain TypeScript keywords - public SpaceAfterCertainTypeScriptKeywords: Rule; - public SpaceBeforeCertainTypeScriptKeywords: Rule; - - // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" { - public SpaceAfterModuleName: Rule; - - // Lambda expressions - public SpaceBeforeArrow: Rule; - public SpaceAfterArrow: Rule; - - // Optional parameters and let args - public NoSpaceAfterEllipsis: Rule; - public NoSpaceAfterOptionalParameters: Rule; - - // generics - public NoSpaceBeforeOpenAngularBracket: Rule; - public NoSpaceBetweenCloseParenAndAngularBracket: Rule; - public NoSpaceAfterOpenAngularBracket: Rule; - public NoSpaceBeforeCloseAngularBracket: Rule; - public NoSpaceAfterCloseAngularBracket: Rule; - - // Remove spaces in empty interface literals. e.g.: x: {} - public NoSpaceBetweenEmptyInterfaceBraceBrackets: Rule; - - // These rules are higher in priority than user-configurable rules. - public HighPriorityCommonRules: Rule[]; - - // These rules are applied after high priority rules. - public UserConfigurableRules: Rule[]; - - // These rules are lower in priority than user-configurable rules. - public LowPriorityCommonRules: Rule[]; - - /// - /// Rules controlled by user options - /// - - // Insert space after comma delimiter - public SpaceAfterComma: Rule; - public NoSpaceAfterComma: Rule; - - // Insert space before and after binary operators - public SpaceBeforeBinaryOperator: Rule; - public SpaceAfterBinaryOperator: Rule; - public NoSpaceBeforeBinaryOperator: Rule; - public NoSpaceAfterBinaryOperator: Rule; - - // Insert space after keywords in control flow statements - public SpaceAfterKeywordInControl: Rule; - public NoSpaceAfterKeywordInControl: Rule; - - // Open Brace braces after function + // Place a space before open brace in a function declaration // TypeScript: Function can have return types, which can be made of tons of different token kinds - public FunctionOpenBraceLeftTokenRange: Shared.TokenRange; - public SpaceBeforeOpenBraceInFunction: Rule; - public NewLineBeforeOpenBraceInFunction: Rule; + const functionOpenBraceLeftTokenRange = anyTokenIncludingMultilineComments; - // Open Brace braces after TypeScript module/class/interface - public TypeScriptOpenBraceLeftTokenRange: Shared.TokenRange; - public SpaceBeforeOpenBraceInTypeScriptDeclWithBlock: Rule; - public NewLineBeforeOpenBraceInTypeScriptDeclWithBlock: Rule; + // Place a space before open brace in a TypeScript declaration that has braces as children (class, module, enum, etc) + const typeScriptOpenBraceLeftTokenRange = tokenRangeFrom([SyntaxKind.Identifier, SyntaxKind.MultiLineCommentTrivia, SyntaxKind.ClassKeyword, SyntaxKind.ExportKeyword, SyntaxKind.ImportKeyword]); - // Open Brace braces after control block - public ControlOpenBraceLeftTokenRange: Shared.TokenRange; - public SpaceBeforeOpenBraceInControl: Rule; - public NewLineBeforeOpenBraceInControl: Rule; - - // Insert space after semicolon in for statement - public SpaceAfterSemicolonInFor: Rule; - public NoSpaceAfterSemicolonInFor: Rule; - - // Insert space after opening and before closing nonempty parenthesis - public SpaceAfterOpenParen: Rule; - public SpaceBeforeCloseParen: Rule; - public SpaceBetweenOpenParens: Rule; - public NoSpaceBetweenParens: Rule; - public NoSpaceAfterOpenParen: Rule; - public NoSpaceBeforeCloseParen: Rule; - - // Insert space after opening and before closing nonempty brackets - public SpaceAfterOpenBracket: Rule; - public SpaceBeforeCloseBracket: Rule; - public NoSpaceBetweenBrackets: Rule; - public NoSpaceAfterOpenBracket: Rule; - public NoSpaceBeforeCloseBracket: Rule; - - // Insert space after function keyword for anonymous functions - public SpaceAfterAnonymousFunctionKeyword: Rule; - public NoSpaceAfterAnonymousFunctionKeyword: Rule; - - // Insert space after @ in decorator - public SpaceBeforeAt: Rule; - public NoSpaceAfterAt: Rule; - public SpaceAfterDecorator: Rule; - - // Generator: function* - public NoSpaceBetweenFunctionKeywordAndStar: Rule; - public SpaceAfterStarInGeneratorDeclaration: Rule; - public NoSpaceBetweenYieldKeywordAndStar: Rule; - public SpaceBetweenYieldOrYieldStarAndOperand: Rule; - - // Async functions - public SpaceBetweenAsyncAndOpenParen: Rule; - public SpaceBetweenAsyncAndFunctionKeyword: Rule; - - // Template strings - public NoSpaceBetweenTagAndTemplateString: Rule; - public NoSpaceAfterTemplateHeadAndMiddle: Rule; - public SpaceAfterTemplateHeadAndMiddle: Rule; - public NoSpaceBeforeTemplateMiddleAndTail: Rule; - public SpaceBeforeTemplateMiddleAndTail: Rule; - - // No space after { and before } in JSX expression - public NoSpaceAfterOpenBraceInJsxExpression: Rule; - public SpaceAfterOpenBraceInJsxExpression: Rule; - public NoSpaceBeforeCloseBraceInJsxExpression: Rule; - public SpaceBeforeCloseBraceInJsxExpression: Rule; - - // JSX opening elements - public SpaceBeforeJsxAttribute: Rule; - public SpaceBeforeSlashInJsxOpeningElement: Rule; - public NoSpaceBeforeGreaterThanTokenInJsxOpeningElement: Rule; - public NoSpaceBeforeEqualInJsxAttribute: Rule; - public NoSpaceAfterEqualInJsxAttribute: Rule; - - // No space after type assertions - public NoSpaceAfterTypeAssertion: Rule; - public SpaceAfterTypeAssertion: Rule; - - // No space before non-null assertion operator - public NoSpaceBeforeNonNullAssertionOperator: Rule; - - constructor() { - /// - /// Common Rules - /// + // Place a space before open brace in a control flow construct + const controlOpenBraceLeftTokenRange = tokenRangeFrom([SyntaxKind.CloseParenToken, SyntaxKind.MultiLineCommentTrivia, SyntaxKind.DoKeyword, SyntaxKind.TryKeyword, SyntaxKind.FinallyKeyword, SyntaxKind.ElseKeyword]); + // These rules are higher in priority than user-configurable + const highPriorityCommonRules = [ // Leave comments alone - this.IgnoreBeforeComment = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.Comments), RuleOperation.create1(RuleAction.Ignore)); - this.IgnoreAfterLineComment = new Rule(RuleDescriptor.create3(SyntaxKind.SingleLineCommentTrivia, Shared.TokenRange.Any), RuleOperation.create1(RuleAction.Ignore)); + rule("IgnoreBeforeComment", anyToken, comments, anyContext, RuleAction.Ignore), + rule("IgnoreAfterLineComment", SyntaxKind.SingleLineCommentTrivia, anyToken, anyContext, RuleAction.Ignore), - // Space after keyword but not before ; or : or ? - this.NoSpaceBeforeSemicolon = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.SemicolonToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceBeforeColon = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.ColonToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete)); - this.NoSpaceBeforeQuestionMark = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.QuestionToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete)); - this.SpaceAfterColon = new Rule(RuleDescriptor.create3(SyntaxKind.ColonToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Space)); - this.SpaceAfterQuestionMarkInConditionalOperator = new Rule(RuleDescriptor.create3(SyntaxKind.QuestionToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsConditionalOperatorContext), RuleAction.Space)); - this.NoSpaceAfterQuestionMark = new Rule(RuleDescriptor.create3(SyntaxKind.QuestionToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.SpaceAfterSemicolon = new Rule(RuleDescriptor.create3(SyntaxKind.SemicolonToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); + rule("NoSpaceBeforeColon", anyToken, SyntaxKind.ColonToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.Delete), + rule("SpaceAfterColon", SyntaxKind.ColonToken, anyToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.Space), + rule("NoSpaceBeforeQuestionMark", anyToken, SyntaxKind.QuestionToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.Delete), + // insert space after '?' only when it is used in conditional operator + rule("SpaceAfterQuestionMarkInConditionalOperator", SyntaxKind.QuestionToken, anyToken, [isNonJsxSameLineTokenContext, isConditionalOperatorContext], RuleAction.Space), - // Space after }. - this.SpaceAfterCloseBrace = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBraceToken, Shared.TokenRange.FromRange(SyntaxKind.FirstToken, SyntaxKind.LastToken, [SyntaxKind.CloseParenToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsAfterCodeBlockContext), RuleAction.Space)); + // in other cases there should be no space between '?' and next token + rule("NoSpaceAfterQuestionMark", SyntaxKind.QuestionToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.Delete), - // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied - this.SpaceBetweenCloseBraceAndElse = new Rule(RuleDescriptor.create1(SyntaxKind.CloseBraceToken, SyntaxKind.ElseKeyword), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - this.SpaceBetweenCloseBraceAndWhile = new Rule(RuleDescriptor.create1(SyntaxKind.CloseBraceToken, SyntaxKind.WhileKeyword), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - this.NoSpaceAfterCloseBrace = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBraceToken, Shared.TokenRange.FromTokens([SyntaxKind.CloseBracketToken, SyntaxKind.CommaToken, SyntaxKind.SemicolonToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - - // No space for dot - this.NoSpaceBeforeDot = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.DotToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceAfterDot = new Rule(RuleDescriptor.create3(SyntaxKind.DotToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - - // No space before and after indexer - this.NoSpaceBeforeOpenBracket = new Rule( - RuleDescriptor.create2(Shared.TokenRange.AnyExcept(SyntaxKind.AsyncKeyword), SyntaxKind.OpenBracketToken), - RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceAfterCloseBracket = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext), RuleAction.Delete)); - - // Place a space before open brace in a function declaration - this.FunctionOpenBraceLeftTokenRange = Shared.TokenRange.AnyIncludingMultilineComments; - this.SpaceBeforeOpenBraceInFunction = new Rule(RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), Rules.IsFunctionDeclContext, Rules.IsBeforeBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeBlockContext), RuleAction.Space), RuleFlags.CanDeleteNewLines); - - // Place a space before open brace in a TypeScript declaration that has braces as children (class, module, enum, etc) - this.TypeScriptOpenBraceLeftTokenRange = Shared.TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.MultiLineCommentTrivia, SyntaxKind.ClassKeyword, SyntaxKind.ExportKeyword, SyntaxKind.ImportKeyword]); - this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock = new Rule(RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), Rules.IsTypeScriptDeclWithBlockContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeBlockContext), RuleAction.Space), RuleFlags.CanDeleteNewLines); - - // Place a space before open brace in a control flow construct - this.ControlOpenBraceLeftTokenRange = Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.MultiLineCommentTrivia, SyntaxKind.DoKeyword, SyntaxKind.TryKeyword, SyntaxKind.FinallyKeyword, SyntaxKind.ElseKeyword]); - this.SpaceBeforeOpenBraceInControl = new Rule(RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForControlBlocks"), Rules.IsControlDeclContext, Rules.IsNotFormatOnEnter, Rules.IsSameLineTokenOrBeforeBlockContext), RuleAction.Space), RuleFlags.CanDeleteNewLines); - - // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}. - this.SpaceAfterOpenBrace = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBraceToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), Rules.IsBraceWrappedContext), RuleAction.Space)); - this.SpaceBeforeCloseBrace = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), Rules.IsBraceWrappedContext), RuleAction.Space)); - this.NoSpaceAfterOpenBrace = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBraceToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceBeforeCloseBrace = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceBetweenEmptyBraceBrackets = new Rule(RuleDescriptor.create1(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsObjectContext), RuleAction.Delete)); - - // Insert new line after { and before } in multi-line contexts. - this.NewLineAfterOpenBraceInBlockContext = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBraceToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsMultilineBlockContext), RuleAction.NewLine)); - - // For functions and control block place } on a new line [multi-line rule] - this.NewLineBeforeCloseBraceInBlockContext = new Rule(RuleDescriptor.create2(Shared.TokenRange.AnyIncludingMultilineComments, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsMultilineBlockContext), RuleAction.NewLine)); + rule("NoSpaceBeforeDot", anyToken, SyntaxKind.DotToken, [isNonJsxSameLineTokenContext], RuleAction.Delete), + rule("NoSpaceAfterDot", SyntaxKind.DotToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.Delete), // Special handling of unary operators. // Prefix operators generally shouldn't have a space between // them and their target unary expression. - this.NoSpaceAfterUnaryPrefixOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.UnaryPrefixOperators, Shared.TokenRange.UnaryPrefixExpressions), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete)); - this.NoSpaceAfterUnaryPreincrementOperator = new Rule(RuleDescriptor.create3(SyntaxKind.PlusPlusToken, Shared.TokenRange.UnaryPreincrementExpressions), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceAfterUnaryPredecrementOperator = new Rule(RuleDescriptor.create3(SyntaxKind.MinusMinusToken, Shared.TokenRange.UnaryPredecrementExpressions), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceBeforeUnaryPostincrementOperator = new Rule(RuleDescriptor.create2(Shared.TokenRange.UnaryPostincrementExpressions, SyntaxKind.PlusPlusToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceBeforeUnaryPostdecrementOperator = new Rule(RuleDescriptor.create2(Shared.TokenRange.UnaryPostdecrementExpressions, SyntaxKind.MinusMinusToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); + rule("NoSpaceAfterUnaryPrefixOperator", unaryPrefixOperators, unaryPrefixExpressions, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.Delete), + rule("NoSpaceAfterUnaryPreincrementOperator", SyntaxKind.PlusPlusToken, unaryPreincrementExpressions, [isNonJsxSameLineTokenContext], RuleAction.Delete), + rule("NoSpaceAfterUnaryPredecrementOperator", SyntaxKind.MinusMinusToken, unaryPredecrementExpressions, [isNonJsxSameLineTokenContext], RuleAction.Delete), + rule("NoSpaceBeforeUnaryPostincrementOperator", unaryPostincrementExpressions, SyntaxKind.PlusPlusToken, [isNonJsxSameLineTokenContext], RuleAction.Delete), + rule("NoSpaceBeforeUnaryPostdecrementOperator", unaryPostdecrementExpressions, SyntaxKind.MinusMinusToken, [isNonJsxSameLineTokenContext], RuleAction.Delete), // More unary operator special-casing. // DevDiv 181814: Be careful when removing leading whitespace // around unary operators. Examples: // 1 - -2 --X--> 1--2 // a + ++b --X--> a+++b - this.SpaceAfterPostincrementWhenFollowedByAdd = new Rule(RuleDescriptor.create1(SyntaxKind.PlusPlusToken, SyntaxKind.PlusToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space)); - this.SpaceAfterAddWhenFollowedByUnaryPlus = new Rule(RuleDescriptor.create1(SyntaxKind.PlusToken, SyntaxKind.PlusToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space)); - this.SpaceAfterAddWhenFollowedByPreincrement = new Rule(RuleDescriptor.create1(SyntaxKind.PlusToken, SyntaxKind.PlusPlusToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space)); - this.SpaceAfterPostdecrementWhenFollowedBySubtract = new Rule(RuleDescriptor.create1(SyntaxKind.MinusMinusToken, SyntaxKind.MinusToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space)); - this.SpaceAfterSubtractWhenFollowedByUnaryMinus = new Rule(RuleDescriptor.create1(SyntaxKind.MinusToken, SyntaxKind.MinusToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space)); - this.SpaceAfterSubtractWhenFollowedByPredecrement = new Rule(RuleDescriptor.create1(SyntaxKind.MinusToken, SyntaxKind.MinusMinusToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space)); + rule("SpaceAfterPostincrementWhenFollowedByAdd", SyntaxKind.PlusPlusToken, SyntaxKind.PlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space), + rule("SpaceAfterAddWhenFollowedByUnaryPlus", SyntaxKind.PlusToken, SyntaxKind.PlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space), + rule("SpaceAfterAddWhenFollowedByPreincrement", SyntaxKind.PlusToken, SyntaxKind.PlusPlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space), + rule("SpaceAfterPostdecrementWhenFollowedBySubtract", SyntaxKind.MinusMinusToken, SyntaxKind.MinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space), + rule("SpaceAfterSubtractWhenFollowedByUnaryMinus", SyntaxKind.MinusToken, SyntaxKind.MinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space), + rule("SpaceAfterSubtractWhenFollowedByPredecrement", SyntaxKind.MinusToken, SyntaxKind.MinusMinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space), - this.NoSpaceBeforeComma = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CommaToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); + rule("NoSpaceAfterCloseBrace", SyntaxKind.CloseBraceToken, [SyntaxKind.CloseBracketToken, SyntaxKind.CommaToken, SyntaxKind.SemicolonToken], [isNonJsxSameLineTokenContext], RuleAction.Delete), + // For functions and control block place } on a new line [multi-line rule] + rule("NewLineBeforeCloseBraceInBlockContext", anyTokenIncludingMultilineComments, SyntaxKind.CloseBraceToken, [isMultilineBlockContext], RuleAction.NewLine), - this.SpaceAfterCertainKeywords = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.VarKeyword, SyntaxKind.ThrowKeyword, SyntaxKind.NewKeyword, SyntaxKind.DeleteKeyword, SyntaxKind.ReturnKeyword, SyntaxKind.TypeOfKeyword, SyntaxKind.AwaitKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - this.NoSpaceAfterNewKeywordOnConstructorSignature = new Rule(RuleDescriptor.create1(SyntaxKind.NewKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsConstructorSignatureContext), RuleAction.Delete)); - this.SpaceAfterLetConstInVariableDeclaration = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.LetKeyword, SyntaxKind.ConstKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsStartOfVariableDeclarationList), RuleAction.Space)); - this.NoSpaceBeforeOpenParenInFuncCall = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsFunctionCallOrNewContext, Rules.IsPreviousTokenNotComma), RuleAction.Delete)); - this.SpaceAfterFunctionInFuncDecl = new Rule(RuleDescriptor.create3(SyntaxKind.FunctionKeyword, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Space)); - this.SpaceBeforeOpenParenInFuncDecl = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceBeforeFunctionParenthesis"), Rules.IsNonJsxSameLineTokenContext, Rules.IsFunctionDeclContext), RuleAction.Space)); - this.NoSpaceBeforeOpenParenInFuncDecl = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceBeforeFunctionParenthesis"), Rules.IsNonJsxSameLineTokenContext, Rules.IsFunctionDeclContext), RuleAction.Delete)); - this.SpaceAfterVoidOperator = new Rule(RuleDescriptor.create3(SyntaxKind.VoidKeyword, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsVoidOpContext), RuleAction.Space)); + // Space/new line after }. + rule("SpaceAfterCloseBrace", SyntaxKind.CloseBraceToken, anyTokenExcept(SyntaxKind.CloseParenToken), [isNonJsxSameLineTokenContext, isAfterCodeBlockContext], RuleAction.Space), + // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied + // Also should not apply to }) + rule("SpaceBetweenCloseBraceAndElse", SyntaxKind.CloseBraceToken, SyntaxKind.ElseKeyword, [isNonJsxSameLineTokenContext], RuleAction.Space), + rule("SpaceBetweenCloseBraceAndWhile", SyntaxKind.CloseBraceToken, SyntaxKind.WhileKeyword, [isNonJsxSameLineTokenContext], RuleAction.Space), + rule("NoSpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectContext], RuleAction.Delete), - this.NoSpaceBetweenReturnAndSemicolon = new Rule(RuleDescriptor.create1(SyntaxKind.ReturnKeyword, SyntaxKind.SemicolonToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); + rule("NoSpaceBetweenFunctionKeywordAndStar", SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken, [isFunctionDeclarationOrFunctionExpressionContext], RuleAction.Delete), + rule("SpaceAfterStarInGeneratorDeclaration", SyntaxKind.AsteriskToken, [SyntaxKind.Identifier, SyntaxKind.OpenParenToken], [isFunctionDeclarationOrFunctionExpressionContext], RuleAction.Space), - // Add a space between statements. All keywords except (do,else,case) has open/close parens after them. - // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any] - this.SpaceBetweenStatements = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.DoKeyword, SyntaxKind.ElseKeyword, SyntaxKind.CaseKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext, Rules.IsNotForContext), RuleAction.Space)); - - // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter. - this.SpaceAfterTryFinally = new Rule(RuleDescriptor.create2(Shared.TokenRange.FromTokens([SyntaxKind.TryKeyword, SyntaxKind.FinallyKeyword]), SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); + rule("SpaceAfterFunctionInFuncDecl", SyntaxKind.FunctionKeyword, anyToken, [isFunctionDeclContext], RuleAction.Space), + // Insert new line after { and before } in multi-line contexts. + rule("NewLineAfterOpenBraceInBlockContext", SyntaxKind.OpenBraceToken, anyToken, [isMultilineBlockContext], RuleAction.NewLine), + // For get/set members, we check for (identifier,identifier) since get/set don't have tokens and they are represented as just an identifier token. + // Though, we do extra check on the context to make sure we are dealing with get/set node. Example: // get x() {} // set x(val) {} - this.SpaceAfterGetSetInMember = new Rule(RuleDescriptor.create2(Shared.TokenRange.FromTokens([SyntaxKind.GetKeyword, SyntaxKind.SetKeyword]), SyntaxKind.Identifier), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Space)); + rule("SpaceAfterGetSetInMember", [SyntaxKind.GetKeyword, SyntaxKind.SetKeyword], SyntaxKind.Identifier, [isFunctionDeclContext], RuleAction.Space), + + rule("NoSpaceBetweenYieldKeywordAndStar", SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], RuleAction.Delete), + rule("SpaceBetweenYieldOrYieldStarAndOperand", [SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken], anyToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], RuleAction.Space), + + rule("NoSpaceBetweenReturnAndSemicolon", SyntaxKind.ReturnKeyword, SyntaxKind.SemicolonToken, [isNonJsxSameLineTokenContext], RuleAction.Delete), + rule("SpaceAfterCertainKeywords", [SyntaxKind.VarKeyword, SyntaxKind.ThrowKeyword, SyntaxKind.NewKeyword, SyntaxKind.DeleteKeyword, SyntaxKind.ReturnKeyword, SyntaxKind.TypeOfKeyword, SyntaxKind.AwaitKeyword], anyToken, [isNonJsxSameLineTokenContext], RuleAction.Space), + rule("SpaceAfterLetConstInVariableDeclaration", [SyntaxKind.LetKeyword, SyntaxKind.ConstKeyword], anyToken, [isNonJsxSameLineTokenContext, isStartOfVariableDeclarationList], RuleAction.Space), + rule("NoSpaceBeforeOpenParenInFuncCall", anyToken, SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isFunctionCallOrNewContext, isPreviousTokenNotComma], RuleAction.Delete), // Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options. - this.SpaceBeforeBinaryKeywordOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.BinaryKeywordOperators), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space)); - this.SpaceAfterBinaryKeywordOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.BinaryKeywordOperators, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space)); + rule("SpaceBeforeBinaryKeywordOperator", anyToken, binaryKeywordOperators, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space), + rule("SpaceAfterBinaryKeywordOperator", binaryKeywordOperators, anyToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space), - // TypeScript-specific higher priority rules - - this.SpaceAfterConstructor = new Rule(RuleDescriptor.create1(SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterConstructor"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - this.NoSpaceAfterConstructor = new Rule(RuleDescriptor.create1(SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceAfterConstructor"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - - // Use of module as a function call. e.g.: import m2 = module("m2"); - this.NoSpaceAfterModuleImport = new Rule(RuleDescriptor.create2(Shared.TokenRange.FromTokens([SyntaxKind.ModuleKeyword, SyntaxKind.RequireKeyword]), SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - - // Add a space around certain TypeScript keywords - this.SpaceAfterCertainTypeScriptKeywords = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.AbstractKeyword, SyntaxKind.ClassKeyword, SyntaxKind.DeclareKeyword, SyntaxKind.DefaultKeyword, SyntaxKind.EnumKeyword, SyntaxKind.ExportKeyword, SyntaxKind.ExtendsKeyword, SyntaxKind.GetKeyword, SyntaxKind.ImplementsKeyword, SyntaxKind.ImportKeyword, SyntaxKind.InterfaceKeyword, SyntaxKind.ModuleKeyword, SyntaxKind.NamespaceKeyword, SyntaxKind.PrivateKeyword, SyntaxKind.PublicKeyword, SyntaxKind.ProtectedKeyword, SyntaxKind.ReadonlyKeyword, SyntaxKind.SetKeyword, SyntaxKind.StaticKeyword, SyntaxKind.TypeKeyword, SyntaxKind.FromKeyword, SyntaxKind.KeyOfKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - this.SpaceBeforeCertainTypeScriptKeywords = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.FromTokens([SyntaxKind.ExtendsKeyword, SyntaxKind.ImplementsKeyword, SyntaxKind.FromKeyword])), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - - // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" { - this.SpaceAfterModuleName = new Rule(RuleDescriptor.create1(SyntaxKind.StringLiteral, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsModuleDeclContext), RuleAction.Space)); - - // Lambda expressions - this.SpaceBeforeArrow = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.EqualsGreaterThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - this.SpaceAfterArrow = new Rule(RuleDescriptor.create3(SyntaxKind.EqualsGreaterThanToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - - // Optional parameters and let args - this.NoSpaceAfterEllipsis = new Rule(RuleDescriptor.create1(SyntaxKind.DotDotDotToken, SyntaxKind.Identifier), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceAfterOptionalParameters = new Rule(RuleDescriptor.create3(SyntaxKind.QuestionToken, Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.CommaToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete)); - - // generics and type assertions - this.NoSpaceBeforeOpenAngularBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.TypeNames, SyntaxKind.LessThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); - this.NoSpaceBetweenCloseParenAndAngularBracket = new Rule(RuleDescriptor.create1(SyntaxKind.CloseParenToken, SyntaxKind.LessThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); - this.NoSpaceAfterOpenAngularBracket = new Rule(RuleDescriptor.create3(SyntaxKind.LessThanToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); - this.NoSpaceBeforeCloseAngularBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.GreaterThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); - this.NoSpaceAfterCloseAngularBracket = new Rule(RuleDescriptor.create3(SyntaxKind.GreaterThanToken, Shared.TokenRange.FromTokens([SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.GreaterThanToken, SyntaxKind.CommaToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); - - // Remove spaces in empty interface literals. e.g.: x: {} - this.NoSpaceBetweenEmptyInterfaceBraceBrackets = new Rule(RuleDescriptor.create1(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsObjectTypeContext), RuleAction.Delete)); - - // decorators - this.SpaceBeforeAt = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.AtToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - this.NoSpaceAfterAt = new Rule(RuleDescriptor.create3(SyntaxKind.AtToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.SpaceAfterDecorator = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.FromTokens([SyntaxKind.AbstractKeyword, SyntaxKind.Identifier, SyntaxKind.ExportKeyword, SyntaxKind.DefaultKeyword, SyntaxKind.ClassKeyword, SyntaxKind.StaticKeyword, SyntaxKind.PublicKeyword, SyntaxKind.PrivateKeyword, SyntaxKind.ProtectedKeyword, SyntaxKind.GetKeyword, SyntaxKind.SetKeyword, SyntaxKind.OpenBracketToken, SyntaxKind.AsteriskToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsEndOfDecoratorContextOnSameLine), RuleAction.Space)); - - this.NoSpaceBetweenFunctionKeywordAndStar = new Rule(RuleDescriptor.create1(SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclarationOrFunctionExpressionContext), RuleAction.Delete)); - this.SpaceAfterStarInGeneratorDeclaration = new Rule(RuleDescriptor.create3(SyntaxKind.AsteriskToken, Shared.TokenRange.FromTokens([SyntaxKind.Identifier, SyntaxKind.OpenParenToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclarationOrFunctionExpressionContext), RuleAction.Space)); - this.NoSpaceBetweenYieldKeywordAndStar = new Rule(RuleDescriptor.create1(SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsYieldOrYieldStarWithOperand), RuleAction.Delete)); - this.SpaceBetweenYieldOrYieldStarAndOperand = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsYieldOrYieldStarWithOperand), RuleAction.Space)); + rule("SpaceAfterVoidOperator", SyntaxKind.VoidKeyword, anyToken, [isNonJsxSameLineTokenContext, isVoidOpContext], RuleAction.Space), // Async-await - this.SpaceBetweenAsyncAndOpenParen = new Rule(RuleDescriptor.create1(SyntaxKind.AsyncKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsArrowFunctionContext, Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - this.SpaceBetweenAsyncAndFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.AsyncKeyword, SyntaxKind.FunctionKeyword), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); + rule("SpaceBetweenAsyncAndOpenParen", SyntaxKind.AsyncKeyword, SyntaxKind.OpenParenToken, [isArrowFunctionContext, isNonJsxSameLineTokenContext], RuleAction.Space), + rule("SpaceBetweenAsyncAndFunctionKeyword", SyntaxKind.AsyncKeyword, SyntaxKind.FunctionKeyword, [isNonJsxSameLineTokenContext], RuleAction.Space), // template string - this.NoSpaceBetweenTagAndTemplateString = new Rule(RuleDescriptor.create3(SyntaxKind.Identifier, Shared.TokenRange.FromTokens([SyntaxKind.NoSubstitutionTemplateLiteral, SyntaxKind.TemplateHead])), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); + rule("NoSpaceBetweenTagAndTemplateString", SyntaxKind.Identifier, [SyntaxKind.NoSubstitutionTemplateLiteral, SyntaxKind.TemplateHead], [isNonJsxSameLineTokenContext], RuleAction.Delete), - // jsx opening element - this.SpaceBeforeJsxAttribute = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.Identifier), RuleOperation.create2(new RuleOperationContext(Rules.IsNextTokenParentJsxAttribute, Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - this.SpaceBeforeSlashInJsxOpeningElement = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.SlashToken), RuleOperation.create2(new RuleOperationContext(Rules.IsJsxSelfClosingElementContext, Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - this.NoSpaceBeforeGreaterThanTokenInJsxOpeningElement = new Rule(RuleDescriptor.create1(SyntaxKind.SlashToken, SyntaxKind.GreaterThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsJsxSelfClosingElementContext, Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceBeforeEqualInJsxAttribute = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.EqualsToken), RuleOperation.create2(new RuleOperationContext(Rules.IsJsxAttributeContext, Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceAfterEqualInJsxAttribute = new Rule(RuleDescriptor.create3(SyntaxKind.EqualsToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsJsxAttributeContext, Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); + // JSX opening elements + rule("SpaceBeforeJsxAttribute", anyToken, SyntaxKind.Identifier, [isNextTokenParentJsxAttribute, isNonJsxSameLineTokenContext], RuleAction.Space), + rule("SpaceBeforeSlashInJsxOpeningElement", anyToken, SyntaxKind.SlashToken, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], RuleAction.Space), + rule("NoSpaceBeforeGreaterThanTokenInJsxOpeningElement", SyntaxKind.SlashToken, SyntaxKind.GreaterThanToken, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], RuleAction.Delete), + rule("NoSpaceBeforeEqualInJsxAttribute", anyToken, SyntaxKind.EqualsToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], RuleAction.Delete), + rule("NoSpaceAfterEqualInJsxAttribute", SyntaxKind.EqualsToken, anyToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], RuleAction.Delete), - // No space before non-null assertion operator - this.NoSpaceBeforeNonNullAssertionOperator = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.ExclamationToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext, Rules.IsNonNullAssertionContext), RuleAction.Delete)); + // TypeScript-specific rules + // Use of module as a function call. e.g.: import m2 = module("m2"); + rule("NoSpaceAfterModuleImport", [SyntaxKind.ModuleKeyword, SyntaxKind.RequireKeyword], SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext], RuleAction.Delete), + // Add a space around certain TypeScript keywords + rule( + "SpaceAfterCertainTypeScriptKeywords", + [ + SyntaxKind.AbstractKeyword, + SyntaxKind.ClassKeyword, + SyntaxKind.DeclareKeyword, + SyntaxKind.DefaultKeyword, + SyntaxKind.EnumKeyword, + SyntaxKind.ExportKeyword, + SyntaxKind.ExtendsKeyword, + SyntaxKind.GetKeyword, + SyntaxKind.ImplementsKeyword, + SyntaxKind.ImportKeyword, + SyntaxKind.InterfaceKeyword, + SyntaxKind.ModuleKeyword, + SyntaxKind.NamespaceKeyword, + SyntaxKind.PrivateKeyword, + SyntaxKind.PublicKeyword, + SyntaxKind.ProtectedKeyword, + SyntaxKind.ReadonlyKeyword, + SyntaxKind.SetKeyword, + SyntaxKind.StaticKeyword, + SyntaxKind.TypeKeyword, + SyntaxKind.FromKeyword, + SyntaxKind.KeyOfKeyword, + ], + anyToken, + [isNonJsxSameLineTokenContext], + RuleAction.Space), + rule( + "SpaceBeforeCertainTypeScriptKeywords", + anyToken, + [SyntaxKind.ExtendsKeyword, SyntaxKind.ImplementsKeyword, SyntaxKind.FromKeyword], + [isNonJsxSameLineTokenContext], + RuleAction.Space), + // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" { + rule("SpaceAfterModuleName", SyntaxKind.StringLiteral, SyntaxKind.OpenBraceToken, [isModuleDeclContext], RuleAction.Space), - /// - /// Rules controlled by user options - /// + // Lambda expressions + rule("SpaceBeforeArrow", anyToken, SyntaxKind.EqualsGreaterThanToken, [isNonJsxSameLineTokenContext], RuleAction.Space), + rule("SpaceAfterArrow", SyntaxKind.EqualsGreaterThanToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.Space), - // Insert space after comma delimiter - this.SpaceAfterComma = new Rule(RuleDescriptor.create3(SyntaxKind.CommaToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterCommaDelimiter"), Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext, Rules.IsNextTokenNotCloseBracket), RuleAction.Space)); - this.NoSpaceAfterComma = new Rule(RuleDescriptor.create3(SyntaxKind.CommaToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), Rules.IsNonJsxSameLineTokenContext, Rules.IsNonJsxElementContext), RuleAction.Delete)); + // Optional parameters and let args + rule("NoSpaceAfterEllipsis", SyntaxKind.DotDotDotToken, SyntaxKind.Identifier, [isNonJsxSameLineTokenContext], RuleAction.Delete), + rule("NoSpaceAfterOptionalParameters", SyntaxKind.QuestionToken, [SyntaxKind.CloseParenToken, SyntaxKind.CommaToken], [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.Delete), - // Insert space before and after binary operators - this.SpaceBeforeBinaryOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.BinaryOperators), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space)); - this.SpaceAfterBinaryOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.BinaryOperators, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Space)); - this.NoSpaceBeforeBinaryOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.BinaryOperators), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Delete)); - this.NoSpaceAfterBinaryOperator = new Rule(RuleDescriptor.create4(Shared.TokenRange.BinaryOperators, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), Rules.IsNonJsxSameLineTokenContext, Rules.IsBinaryOpContext), RuleAction.Delete)); + // Remove spaces in empty interface literals. e.g.: x: {} + rule("NoSpaceBetweenEmptyInterfaceBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectTypeContext], RuleAction.Delete), + + // generics and type assertions + rule("NoSpaceBeforeOpenAngularBracket", typeNames, SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.Delete), + rule("NoSpaceBetweenCloseParenAndAngularBracket", SyntaxKind.CloseParenToken, SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.Delete), + rule("NoSpaceAfterOpenAngularBracket", SyntaxKind.LessThanToken, anyToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.Delete), + rule("NoSpaceBeforeCloseAngularBracket", anyToken, SyntaxKind.GreaterThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.Delete), + rule("NoSpaceAfterCloseAngularBracket", + SyntaxKind.GreaterThanToken, + [SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.GreaterThanToken, SyntaxKind.CommaToken], + [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], + RuleAction.Delete), + + // decorators + rule("SpaceBeforeAt", anyToken, SyntaxKind.AtToken, [isNonJsxSameLineTokenContext], RuleAction.Space), + rule("NoSpaceAfterAt", SyntaxKind.AtToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.Delete), + // Insert space after @ in decorator + rule("SpaceAfterDecorator", + anyToken, + [ + SyntaxKind.AbstractKeyword, + SyntaxKind.Identifier, + SyntaxKind.ExportKeyword, + SyntaxKind.DefaultKeyword, + SyntaxKind.ClassKeyword, + SyntaxKind.StaticKeyword, + SyntaxKind.PublicKeyword, + SyntaxKind.PrivateKeyword, + SyntaxKind.ProtectedKeyword, + SyntaxKind.GetKeyword, + SyntaxKind.SetKeyword, + SyntaxKind.OpenBracketToken, + SyntaxKind.AsteriskToken, + ], + [isEndOfDecoratorContextOnSameLine], + RuleAction.Space), + + rule("NoSpaceBeforeNonNullAssertionOperator", anyToken, SyntaxKind.ExclamationToken, [isNonJsxSameLineTokenContext, isNonNullAssertionContext], RuleAction.Delete), + rule("NoSpaceAfterNewKeywordOnConstructorSignature", SyntaxKind.NewKeyword, SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isConstructorSignatureContext], RuleAction.Delete), + ]; + + // These rules are applied after high priority + const userConfigurableRules = [ + // Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses + rule("SpaceAfterConstructor", SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], RuleAction.Space), + rule("NoSpaceAfterConstructor", SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], RuleAction.Delete), + + rule("SpaceAfterComma", SyntaxKind.CommaToken, anyToken, [isOptionEnabled("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementContext, isNextTokenNotCloseBracket], RuleAction.Space), + rule("NoSpaceAfterComma", SyntaxKind.CommaToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementContext], RuleAction.Delete), + + // Insert space after function keyword for anonymous functions + rule("SpaceAfterAnonymousFunctionKeyword", SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], RuleAction.Space), + rule("NoSpaceAfterAnonymousFunctionKeyword", SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], RuleAction.Delete), // Insert space after keywords in control flow statements - this.SpaceAfterKeywordInControl = new Rule(RuleDescriptor.create2(Shared.TokenRange.Keywords, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterKeywordsInControlFlowStatements"), Rules.IsControlDeclContext), RuleAction.Space)); - this.NoSpaceAfterKeywordInControl = new Rule(RuleDescriptor.create2(Shared.TokenRange.Keywords, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceAfterKeywordsInControlFlowStatements"), Rules.IsControlDeclContext), RuleAction.Delete)); + rule("SpaceAfterKeywordInControl", keywords, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], RuleAction.Space), + rule("NoSpaceAfterKeywordInControl", keywords, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], RuleAction.Delete), + + // Insert space after opening and before closing nonempty parenthesis + rule("SpaceAfterOpenParen", SyntaxKind.OpenParenToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.Space), + rule("SpaceBeforeCloseParen", anyToken, SyntaxKind.CloseParenToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.Space), + rule("SpaceBetweenOpenParens", SyntaxKind.OpenParenToken, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.Space), + rule("NoSpaceBetweenParens", SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, [isNonJsxSameLineTokenContext], RuleAction.Delete), + rule("NoSpaceAfterOpenParen", SyntaxKind.OpenParenToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.Delete), + rule("NoSpaceBeforeCloseParen", anyToken, SyntaxKind.CloseParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.Delete), + + // Insert space after opening and before closing nonempty brackets + rule("SpaceAfterOpenBracket", SyntaxKind.OpenBracketToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.Space), + rule("SpaceBeforeCloseBracket", anyToken, SyntaxKind.CloseBracketToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.Space), + rule("NoSpaceBetweenBrackets", SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken, [isNonJsxSameLineTokenContext], RuleAction.Delete), + rule("NoSpaceAfterOpenBracket", SyntaxKind.OpenBracketToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.Delete), + rule("NoSpaceBeforeCloseBracket", anyToken, SyntaxKind.CloseBracketToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.Delete), + + // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}. + rule("SpaceAfterOpenBrace", SyntaxKind.OpenBraceToken, anyToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], RuleAction.Space), + rule("SpaceBeforeCloseBrace", anyToken, SyntaxKind.CloseBraceToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], RuleAction.Space), + rule("NoSpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectContext], RuleAction.Delete), + rule("NoSpaceAfterOpenBrace", SyntaxKind.OpenBraceToken, anyToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], RuleAction.Delete), + rule("NoSpaceBeforeCloseBrace", anyToken, SyntaxKind.CloseBraceToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], RuleAction.Delete), + + // Insert space after opening and before closing template string braces + rule("SpaceAfterTemplateHeadAndMiddle", [SyntaxKind.TemplateHead, SyntaxKind.TemplateMiddle], anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], RuleAction.Space), + rule("SpaceBeforeTemplateMiddleAndTail", anyToken, [SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail], [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], RuleAction.Space), + rule("NoSpaceAfterTemplateHeadAndMiddle", [SyntaxKind.TemplateHead, SyntaxKind.TemplateMiddle], anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], RuleAction.Delete), + rule("NoSpaceBeforeTemplateMiddleAndTail", anyToken, [SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail], [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], RuleAction.Delete), + + // No space after { and before } in JSX expression + rule("SpaceAfterOpenBraceInJsxExpression", SyntaxKind.OpenBraceToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.Space), + rule("SpaceBeforeCloseBraceInJsxExpression", anyToken, SyntaxKind.CloseBraceToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.Space), + rule("NoSpaceAfterOpenBraceInJsxExpression", SyntaxKind.OpenBraceToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.Delete), + rule("NoSpaceBeforeCloseBraceInJsxExpression", anyToken, SyntaxKind.CloseBraceToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.Delete), + + // Insert space after semicolon in for statement + rule("SpaceAfterSemicolonInFor", SyntaxKind.SemicolonToken, anyToken, [isOptionEnabled("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], RuleAction.Space), + rule("NoSpaceAfterSemicolonInFor", SyntaxKind.SemicolonToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], RuleAction.Delete), + + // Insert space before and after binary operators + rule("SpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space), + rule("SpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Space), + rule("NoSpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Delete), + rule("NoSpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.Delete), + + rule("SpaceBeforeOpenParenInFuncDecl", anyToken, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], RuleAction.Space), + rule("NoSpaceBeforeOpenParenInFuncDecl", anyToken, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], RuleAction.Delete), + + // Open Brace braces after control block + rule("NewLineBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isBeforeMultilineBlockContext], RuleAction.NewLine, RuleFlags.CanDeleteNewLines), // Open Brace braces after function // TypeScript: Function can have return types, which can be made of tons of different token kinds - this.NewLineBeforeOpenBraceInFunction = new Rule(RuleDescriptor.create2(this.FunctionOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("placeOpenBraceOnNewLineForFunctions"), Rules.IsFunctionDeclContext, Rules.IsBeforeMultilineBlockContext), RuleAction.NewLine), RuleFlags.CanDeleteNewLines); - + rule("NewLineBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeMultilineBlockContext], RuleAction.NewLine, RuleFlags.CanDeleteNewLines), // Open Brace braces after TypeScript module/class/interface - this.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock = new Rule(RuleDescriptor.create2(this.TypeScriptOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("placeOpenBraceOnNewLineForFunctions"), Rules.IsTypeScriptDeclWithBlockContext, Rules.IsBeforeMultilineBlockContext), RuleAction.NewLine), RuleFlags.CanDeleteNewLines); + rule("NewLineBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isBeforeMultilineBlockContext], RuleAction.NewLine, RuleFlags.CanDeleteNewLines), - // Open Brace braces after control block - this.NewLineBeforeOpenBraceInControl = new Rule(RuleDescriptor.create2(this.ControlOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("placeOpenBraceOnNewLineForControlBlocks"), Rules.IsControlDeclContext, Rules.IsBeforeMultilineBlockContext), RuleAction.NewLine), RuleFlags.CanDeleteNewLines); + rule("SpaceAfterTypeAssertion", SyntaxKind.GreaterThanToken, anyToken, [isOptionEnabled("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], RuleAction.Space), + rule("NoSpaceAfterTypeAssertion", SyntaxKind.GreaterThanToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], RuleAction.Delete), + ]; - // Insert space after semicolon in for statement - this.SpaceAfterSemicolonInFor = new Rule(RuleDescriptor.create3(SyntaxKind.SemicolonToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterSemicolonInForStatements"), Rules.IsNonJsxSameLineTokenContext, Rules.IsForContext), RuleAction.Space)); - this.NoSpaceAfterSemicolonInFor = new Rule(RuleDescriptor.create3(SyntaxKind.SemicolonToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceAfterSemicolonInForStatements"), Rules.IsNonJsxSameLineTokenContext, Rules.IsForContext), RuleAction.Delete)); + // These rules are lower in priority than user-configurable + const lowPriorityCommonRules = [ + // Space after keyword but not before ; or : or ? + rule("NoSpaceBeforeSemicolon", anyToken, SyntaxKind.SemicolonToken, [isNonJsxSameLineTokenContext], RuleAction.Delete), - // Insert space after opening and before closing nonempty parenthesis - this.SpaceAfterOpenParen = new Rule(RuleDescriptor.create3(SyntaxKind.OpenParenToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - this.SpaceBeforeCloseParen = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - this.SpaceBetweenOpenParens = new Rule(RuleDescriptor.create1(SyntaxKind.OpenParenToken, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - this.NoSpaceBetweenParens = new Rule(RuleDescriptor.create1(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceAfterOpenParen = new Rule(RuleDescriptor.create3(SyntaxKind.OpenParenToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceBeforeCloseParen = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); + rule("SpaceBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], RuleAction.Space, RuleFlags.CanDeleteNewLines), + rule("SpaceBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], RuleAction.Space, RuleFlags.CanDeleteNewLines), + rule("SpaceBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], RuleAction.Space, RuleFlags.CanDeleteNewLines), - // Insert space after opening and before closing nonempty brackets - this.SpaceAfterOpenBracket = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - this.SpaceBeforeCloseBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - this.NoSpaceBetweenBrackets = new Rule(RuleDescriptor.create1(SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceAfterOpenBracket = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceBeforeCloseBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); + rule("NoSpaceBeforeComma", anyToken, SyntaxKind.CommaToken, [isNonJsxSameLineTokenContext], RuleAction.Delete), + // No space before and after indexer + rule("NoSpaceBeforeOpenBracket", anyTokenExcept(SyntaxKind.AsyncKeyword), SyntaxKind.OpenBracketToken, [isNonJsxSameLineTokenContext], RuleAction.Delete), + rule("NoSpaceAfterCloseBracket", SyntaxKind.CloseBracketToken, anyToken, [isNonJsxSameLineTokenContext, isNotBeforeBlockInFunctionDeclarationContext], RuleAction.Delete), + rule("SpaceAfterSemicolon", SyntaxKind.SemicolonToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.Space), - // Insert space after opening and before closing template string braces - this.NoSpaceAfterTemplateHeadAndMiddle = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.TemplateHead, SyntaxKind.TemplateMiddle]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.SpaceAfterTemplateHeadAndMiddle = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.TemplateHead, SyntaxKind.TemplateMiddle]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); - this.NoSpaceBeforeTemplateMiddleAndTail = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.FromTokens([SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail])), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Delete)); - this.SpaceBeforeTemplateMiddleAndTail = new Rule(RuleDescriptor.create4(Shared.TokenRange.Any, Shared.TokenRange.FromTokens([SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail])), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), Rules.IsNonJsxSameLineTokenContext), RuleAction.Space)); + // Add a space between statements. All keywords except (do,else,case) has open/close parens after them. + // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any] + rule( + "SpaceBetweenStatements", + [SyntaxKind.CloseParenToken, SyntaxKind.DoKeyword, SyntaxKind.ElseKeyword, SyntaxKind.CaseKeyword], + anyToken, + [isNonJsxSameLineTokenContext, isNonJsxElementContext, isNotForContext], + RuleAction.Space), + // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter. + rule("SpaceAfterTryFinally", [SyntaxKind.TryKeyword, SyntaxKind.FinallyKeyword], SyntaxKind.OpenBraceToken, [isNonJsxSameLineTokenContext], RuleAction.Space), + ]; - // No space after { and before } in JSX expression - this.NoSpaceAfterOpenBraceInJsxExpression = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBraceToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), RuleAction.Delete)); - this.SpaceAfterOpenBraceInJsxExpression = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBraceToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), RuleAction.Space)); - this.NoSpaceBeforeCloseBraceInJsxExpression = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), RuleAction.Delete)); - this.SpaceBeforeCloseBraceInJsxExpression = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), Rules.IsNonJsxSameLineTokenContext, Rules.IsJsxExpressionContext), RuleAction.Space)); + return [ + ...highPriorityCommonRules, + ...userConfigurableRules, + ...lowPriorityCommonRules, + ]; + } - // Insert space after function keyword for anonymous functions - this.SpaceAfterAnonymousFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), Rules.IsFunctionDeclContext), RuleAction.Space)); - this.NoSpaceAfterAnonymousFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), Rules.IsFunctionDeclContext), RuleAction.Delete)); + function rule( + debugName: string, + left: SyntaxKind | ReadonlyArray | TokenRange, + right: SyntaxKind | ReadonlyArray | TokenRange, + context: ReadonlyArray, + action: RuleAction, + flags: RuleFlags = RuleFlags.None, + ): RuleSpec { + return { leftTokenRange: toTokenRange(left), rightTokenRange: toTokenRange(right), rule: { debugName, context, action, flags } }; + } - // No space after type assertion - this.NoSpaceAfterTypeAssertion = new Rule(RuleDescriptor.create3(SyntaxKind.GreaterThanToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionDisabledOrUndefined("insertSpaceAfterTypeAssertion"), Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeAssertionContext), RuleAction.Delete)); - this.SpaceAfterTypeAssertion = new Rule(RuleDescriptor.create3(SyntaxKind.GreaterThanToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsOptionEnabled("insertSpaceAfterTypeAssertion"), Rules.IsNonJsxSameLineTokenContext, Rules.IsTypeAssertionContext), RuleAction.Space)); + function tokenRangeFrom(tokens: ReadonlyArray): TokenRange { + return { tokens, isSpecific: true }; + } - // These rules are higher in priority than user-configurable rules. - this.HighPriorityCommonRules = [ - this.IgnoreBeforeComment, this.IgnoreAfterLineComment, - this.NoSpaceBeforeColon, this.SpaceAfterColon, this.NoSpaceBeforeQuestionMark, this.SpaceAfterQuestionMarkInConditionalOperator, - this.NoSpaceAfterQuestionMark, - this.NoSpaceBeforeDot, this.NoSpaceAfterDot, - this.NoSpaceAfterUnaryPrefixOperator, - this.NoSpaceAfterUnaryPreincrementOperator, this.NoSpaceAfterUnaryPredecrementOperator, - this.NoSpaceBeforeUnaryPostincrementOperator, this.NoSpaceBeforeUnaryPostdecrementOperator, - this.SpaceAfterPostincrementWhenFollowedByAdd, - this.SpaceAfterAddWhenFollowedByUnaryPlus, this.SpaceAfterAddWhenFollowedByPreincrement, - this.SpaceAfterPostdecrementWhenFollowedBySubtract, - this.SpaceAfterSubtractWhenFollowedByUnaryMinus, this.SpaceAfterSubtractWhenFollowedByPredecrement, - this.NoSpaceAfterCloseBrace, - this.NewLineBeforeCloseBraceInBlockContext, - this.SpaceAfterCloseBrace, this.SpaceBetweenCloseBraceAndElse, this.SpaceBetweenCloseBraceAndWhile, this.NoSpaceBetweenEmptyBraceBrackets, - this.NoSpaceBetweenFunctionKeywordAndStar, this.SpaceAfterStarInGeneratorDeclaration, - this.SpaceAfterFunctionInFuncDecl, this.NewLineAfterOpenBraceInBlockContext, this.SpaceAfterGetSetInMember, - this.NoSpaceBetweenYieldKeywordAndStar, this.SpaceBetweenYieldOrYieldStarAndOperand, - this.NoSpaceBetweenReturnAndSemicolon, - this.SpaceAfterCertainKeywords, - this.SpaceAfterLetConstInVariableDeclaration, - this.NoSpaceBeforeOpenParenInFuncCall, - this.SpaceBeforeBinaryKeywordOperator, this.SpaceAfterBinaryKeywordOperator, - this.SpaceAfterVoidOperator, - this.SpaceBetweenAsyncAndOpenParen, this.SpaceBetweenAsyncAndFunctionKeyword, - this.NoSpaceBetweenTagAndTemplateString, - this.SpaceBeforeJsxAttribute, this.SpaceBeforeSlashInJsxOpeningElement, this.NoSpaceBeforeGreaterThanTokenInJsxOpeningElement, - this.NoSpaceBeforeEqualInJsxAttribute, this.NoSpaceAfterEqualInJsxAttribute, + function toTokenRange(arg: SyntaxKind | ReadonlyArray | TokenRange): TokenRange { + return typeof arg === "number" ? tokenRangeFrom([arg]) : isArray(arg) ? tokenRangeFrom(arg) : arg; + } - // TypeScript-specific rules - this.NoSpaceAfterModuleImport, - this.SpaceAfterCertainTypeScriptKeywords, this.SpaceBeforeCertainTypeScriptKeywords, - this.SpaceAfterModuleName, - this.SpaceBeforeArrow, this.SpaceAfterArrow, - this.NoSpaceAfterEllipsis, - this.NoSpaceAfterOptionalParameters, - this.NoSpaceBetweenEmptyInterfaceBraceBrackets, - this.NoSpaceBeforeOpenAngularBracket, - this.NoSpaceBetweenCloseParenAndAngularBracket, - this.NoSpaceAfterOpenAngularBracket, - this.NoSpaceBeforeCloseAngularBracket, - this.NoSpaceAfterCloseAngularBracket, - this.SpaceBeforeAt, - this.NoSpaceAfterAt, - this.SpaceAfterDecorator, - this.NoSpaceBeforeNonNullAssertionOperator, - this.NoSpaceAfterNewKeywordOnConstructorSignature - ]; - - // These rules are applied after high priority rules. - this.UserConfigurableRules = [ - this.SpaceAfterConstructor, this.NoSpaceAfterConstructor, - this.SpaceAfterComma, this.NoSpaceAfterComma, - this.SpaceAfterAnonymousFunctionKeyword, this.NoSpaceAfterAnonymousFunctionKeyword, - this.SpaceAfterKeywordInControl, this.NoSpaceAfterKeywordInControl, - this.SpaceAfterOpenParen, this.SpaceBeforeCloseParen, this.SpaceBetweenOpenParens, this.NoSpaceBetweenParens, this.NoSpaceAfterOpenParen, this.NoSpaceBeforeCloseParen, - this.SpaceAfterOpenBracket, this.SpaceBeforeCloseBracket, this.NoSpaceBetweenBrackets, this.NoSpaceAfterOpenBracket, this.NoSpaceBeforeCloseBracket, - this.SpaceAfterOpenBrace, this.SpaceBeforeCloseBrace, this.NoSpaceBetweenEmptyBraceBrackets, this.NoSpaceAfterOpenBrace, this.NoSpaceBeforeCloseBrace, - this.SpaceAfterTemplateHeadAndMiddle, this.SpaceBeforeTemplateMiddleAndTail, this.NoSpaceAfterTemplateHeadAndMiddle, this.NoSpaceBeforeTemplateMiddleAndTail, - this.SpaceAfterOpenBraceInJsxExpression, this.SpaceBeforeCloseBraceInJsxExpression, this.NoSpaceAfterOpenBraceInJsxExpression, this.NoSpaceBeforeCloseBraceInJsxExpression, - this.SpaceAfterSemicolonInFor, this.NoSpaceAfterSemicolonInFor, - this.SpaceBeforeBinaryOperator, this.SpaceAfterBinaryOperator, this.NoSpaceBeforeBinaryOperator, this.NoSpaceAfterBinaryOperator, - this.SpaceBeforeOpenParenInFuncDecl, this.NoSpaceBeforeOpenParenInFuncDecl, - this.NewLineBeforeOpenBraceInControl, - this.NewLineBeforeOpenBraceInFunction, this.NewLineBeforeOpenBraceInTypeScriptDeclWithBlock, - this.SpaceAfterTypeAssertion, this.NoSpaceAfterTypeAssertion - ]; - - // These rules are lower in priority than user-configurable rules. - this.LowPriorityCommonRules = [ - this.NoSpaceBeforeSemicolon, - this.SpaceBeforeOpenBraceInControl, this.SpaceBeforeOpenBraceInFunction, this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock, - this.NoSpaceBeforeComma, - this.NoSpaceBeforeOpenBracket, - this.NoSpaceAfterCloseBracket, - this.SpaceAfterSemicolon, - this.SpaceBetweenStatements, this.SpaceAfterTryFinally - ]; - - if (Debug.isDebugging) { - const o: ts.MapLike = this; - for (const name in o) { - const rule = o[name]; - if (rule instanceof Rule) { - rule.debugName = name; - } - } + function tokenRangeFromRange(from: SyntaxKind, to: SyntaxKind, except: ReadonlyArray = []): TokenRange { + const tokens: SyntaxKind[] = []; + for (let token = from; token <= to; token++) { + if (!contains(except, token)) { + tokens.push(token); } } + return tokenRangeFrom(tokens); + } - /// - /// Contexts - /// + /// + /// Contexts + /// - static IsOptionEnabled(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { - return (context) => context.options && context.options.hasOwnProperty(optionName) && !!context.options[optionName]; - } + function isOptionEnabled(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { + return (context) => context.options && context.options.hasOwnProperty(optionName) && !!context.options[optionName]; + } - static IsOptionDisabled(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { - return (context) => context.options && context.options.hasOwnProperty(optionName) && !context.options[optionName]; - } + function isOptionDisabled(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { + return (context) => context.options && context.options.hasOwnProperty(optionName) && !context.options[optionName]; + } - static IsOptionDisabledOrUndefined(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { - return (context) => !context.options || !context.options.hasOwnProperty(optionName) || !context.options[optionName]; - } + function isOptionDisabledOrUndefined(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { + return (context) => !context.options || !context.options.hasOwnProperty(optionName) || !context.options[optionName]; + } - static isOptionDisabledOrUndefinedOrTokensOnSameLine(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { - return (context) => !context.options || !context.options.hasOwnProperty(optionName) || !context.options[optionName] || context.TokensAreOnSameLine(); - } + function isOptionDisabledOrUndefinedOrTokensOnSameLine(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { + return (context) => !context.options || !context.options.hasOwnProperty(optionName) || !context.options[optionName] || context.TokensAreOnSameLine(); + } - static IsOptionEnabledOrUndefined(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { - return (context) => !context.options || !context.options.hasOwnProperty(optionName) || !!context.options[optionName]; - } + function isOptionEnabledOrUndefined(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { + return (context) => !context.options || !context.options.hasOwnProperty(optionName) || !!context.options[optionName]; + } - static IsForContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.ForStatement; - } + function isForContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ForStatement; + } - static IsNotForContext(context: FormattingContext): boolean { - return !Rules.IsForContext(context); - } + function isNotForContext(context: FormattingContext): boolean { + return !isForContext(context); + } - static IsBinaryOpContext(context: FormattingContext): boolean { + function isBinaryOpContext(context: FormattingContext): boolean { - switch (context.contextNode.kind) { - case SyntaxKind.BinaryExpression: - case SyntaxKind.ConditionalExpression: - case SyntaxKind.AsExpression: - case SyntaxKind.ExportSpecifier: - case SyntaxKind.ImportSpecifier: - case SyntaxKind.TypePredicate: - case SyntaxKind.UnionType: - case SyntaxKind.IntersectionType: - return true; - - // equals in binding elements: function foo([[x, y] = [1, 2]]) - case SyntaxKind.BindingElement: - // equals in type X = ... - case SyntaxKind.TypeAliasDeclaration: - // equal in import a = module('a'); - case SyntaxKind.ImportEqualsDeclaration: - // equal in let a = 0; - case SyntaxKind.VariableDeclaration: - // equal in p = 0; - case SyntaxKind.Parameter: - case SyntaxKind.EnumMember: - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.PropertySignature: - return context.currentTokenSpan.kind === SyntaxKind.EqualsToken || context.nextTokenSpan.kind === SyntaxKind.EqualsToken; - // "in" keyword in for (let x in []) { } - case SyntaxKind.ForInStatement: - // "in" keyword in [P in keyof T]: T[P] - case SyntaxKind.TypeParameter: - return context.currentTokenSpan.kind === SyntaxKind.InKeyword || context.nextTokenSpan.kind === SyntaxKind.InKeyword; - // Technically, "of" is not a binary operator, but format it the same way as "in" - case SyntaxKind.ForOfStatement: - return context.currentTokenSpan.kind === SyntaxKind.OfKeyword || context.nextTokenSpan.kind === SyntaxKind.OfKeyword; - } - return false; - } - - static IsNotBinaryOpContext(context: FormattingContext): boolean { - return !Rules.IsBinaryOpContext(context); - } - - static IsConditionalOperatorContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.ConditionalExpression; - } - - static IsSameLineTokenOrBeforeBlockContext(context: FormattingContext): boolean { - return context.TokensAreOnSameLine() || Rules.IsBeforeBlockContext(context); - } - - static IsBraceWrappedContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.ObjectBindingPattern || Rules.IsSingleLineBlockContext(context); - } - - // This check is done before an open brace in a control construct, a function, or a typescript block declaration - static IsBeforeMultilineBlockContext(context: FormattingContext): boolean { - return Rules.IsBeforeBlockContext(context) && !(context.NextNodeAllOnSameLine() || context.NextNodeBlockIsOnOneLine()); - } - - static IsMultilineBlockContext(context: FormattingContext): boolean { - return Rules.IsBlockContext(context) && !(context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine()); - } - - static IsSingleLineBlockContext(context: FormattingContext): boolean { - return Rules.IsBlockContext(context) && (context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine()); - } - - static IsBlockContext(context: FormattingContext): boolean { - return Rules.NodeIsBlockContext(context.contextNode); - } - - static IsBeforeBlockContext(context: FormattingContext): boolean { - return Rules.NodeIsBlockContext(context.nextTokenParent); - } - - // IMPORTANT!!! This method must return true ONLY for nodes with open and close braces as immediate children - static NodeIsBlockContext(node: Node): boolean { - if (Rules.NodeIsTypeScriptDeclWithBlockContext(node)) { - // This means we are in a context that looks like a block to the user, but in the grammar is actually not a node (it's a class, module, enum, object type literal, etc). + switch (context.contextNode.kind) { + case SyntaxKind.BinaryExpression: + case SyntaxKind.ConditionalExpression: + case SyntaxKind.AsExpression: + case SyntaxKind.ExportSpecifier: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.TypePredicate: + case SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: return true; - } - switch (node.kind) { - case SyntaxKind.Block: - case SyntaxKind.CaseBlock: - case SyntaxKind.ObjectLiteralExpression: - case SyntaxKind.ModuleBlock: + // equals in binding elements: function foo([[x, y] = [1, 2]]) + case SyntaxKind.BindingElement: + // equals in type X = ... + case SyntaxKind.TypeAliasDeclaration: + // equal in import a = module('a'); + case SyntaxKind.ImportEqualsDeclaration: + // equal in let a = 0; + case SyntaxKind.VariableDeclaration: + // equal in p = 0; + case SyntaxKind.Parameter: + case SyntaxKind.EnumMember: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + return context.currentTokenSpan.kind === SyntaxKind.EqualsToken || context.nextTokenSpan.kind === SyntaxKind.EqualsToken; + // "in" keyword in for (let x in []) { } + case SyntaxKind.ForInStatement: + // "in" keyword in [P in keyof T]: T[P] + case SyntaxKind.TypeParameter: + return context.currentTokenSpan.kind === SyntaxKind.InKeyword || context.nextTokenSpan.kind === SyntaxKind.InKeyword; + // Technically, "of" is not a binary operator, but format it the same way as "in" + case SyntaxKind.ForOfStatement: + return context.currentTokenSpan.kind === SyntaxKind.OfKeyword || context.nextTokenSpan.kind === SyntaxKind.OfKeyword; + } + return false; + } + + function isNotBinaryOpContext(context: FormattingContext): boolean { + return !isBinaryOpContext(context); + } + + function isConditionalOperatorContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ConditionalExpression; + } + + function isSameLineTokenOrBeforeBlockContext(context: FormattingContext): boolean { + return context.TokensAreOnSameLine() || isBeforeBlockContext(context); + } + + function isBraceWrappedContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ObjectBindingPattern || isSingleLineBlockContext(context); + } + + // This check is done before an open brace in a control construct, a function, or a typescript block declaration + function isBeforeMultilineBlockContext(context: FormattingContext): boolean { + return isBeforeBlockContext(context) && !(context.NextNodeAllOnSameLine() || context.NextNodeBlockIsOnOneLine()); + } + + function isMultilineBlockContext(context: FormattingContext): boolean { + return isBlockContext(context) && !(context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine()); + } + + function isSingleLineBlockContext(context: FormattingContext): boolean { + return isBlockContext(context) && (context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine()); + } + + function isBlockContext(context: FormattingContext): boolean { + return nodeIsBlockContext(context.contextNode); + } + + function isBeforeBlockContext(context: FormattingContext): boolean { + return nodeIsBlockContext(context.nextTokenParent); + } + + // IMPORTANT!!! This method must return true ONLY for nodes with open and close braces as immediate children + function nodeIsBlockContext(node: Node): boolean { + if (nodeIsTypeScriptDeclWithBlockContext(node)) { + // This means we are in a context that looks like a block to the user, but in the grammar is actually not a node (it's a class, module, enum, object type literal, etc). + return true; + } + + switch (node.kind) { + case SyntaxKind.Block: + case SyntaxKind.CaseBlock: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ModuleBlock: + return true; + } + + return false; + } + + function isFunctionDeclContext(context: FormattingContext): boolean { + switch (context.contextNode.kind) { + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + // case SyntaxKind.MemberFunctionDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + // case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.FunctionExpression: + case SyntaxKind.Constructor: + case SyntaxKind.ArrowFunction: + // case SyntaxKind.ConstructorDeclaration: + // case SyntaxKind.SimpleArrowFunctionExpression: + // case SyntaxKind.ParenthesizedArrowFunctionExpression: + case SyntaxKind.InterfaceDeclaration: // This one is not truly a function, but for formatting purposes, it acts just like one + return true; + } + + return false; + } + + function isFunctionDeclarationOrFunctionExpressionContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.FunctionDeclaration || context.contextNode.kind === SyntaxKind.FunctionExpression; + } + + function isTypeScriptDeclWithBlockContext(context: FormattingContext): boolean { + return nodeIsTypeScriptDeclWithBlockContext(context.contextNode); + } + + function nodeIsTypeScriptDeclWithBlockContext(node: Node): boolean { + switch (node.kind) { + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.TypeLiteral: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.ExportDeclaration: + case SyntaxKind.NamedExports: + case SyntaxKind.ImportDeclaration: + case SyntaxKind.NamedImports: + return true; + } + + return false; + } + + function isAfterCodeBlockContext(context: FormattingContext): boolean { + switch (context.currentTokenParent.kind) { + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.CatchClause: + case SyntaxKind.ModuleBlock: + case SyntaxKind.SwitchStatement: + return true; + case SyntaxKind.Block: { + const blockParent = context.currentTokenParent.parent; + // In a codefix scenario, we can't rely on parents being set. So just always return true. + if (!blockParent || blockParent.kind !== SyntaxKind.ArrowFunction && blockParent.kind !== SyntaxKind.FunctionExpression) { return true; - } - - return false; - } - - static IsFunctionDeclContext(context: FormattingContext): boolean { - switch (context.contextNode.kind) { - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - // case SyntaxKind.MemberFunctionDeclaration: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - // case SyntaxKind.MethodSignature: - case SyntaxKind.CallSignature: - case SyntaxKind.FunctionExpression: - case SyntaxKind.Constructor: - case SyntaxKind.ArrowFunction: - // case SyntaxKind.ConstructorDeclaration: - // case SyntaxKind.SimpleArrowFunctionExpression: - // case SyntaxKind.ParenthesizedArrowFunctionExpression: - case SyntaxKind.InterfaceDeclaration: // This one is not truly a function, but for formatting purposes, it acts just like one - return true; - } - - return false; - } - - static IsFunctionDeclarationOrFunctionExpressionContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.FunctionDeclaration || context.contextNode.kind === SyntaxKind.FunctionExpression; - } - - static IsTypeScriptDeclWithBlockContext(context: FormattingContext): boolean { - return Rules.NodeIsTypeScriptDeclWithBlockContext(context.contextNode); - } - - static NodeIsTypeScriptDeclWithBlockContext(node: Node): boolean { - switch (node.kind) { - case SyntaxKind.ClassDeclaration: - case SyntaxKind.ClassExpression: - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.EnumDeclaration: - case SyntaxKind.TypeLiteral: - case SyntaxKind.ModuleDeclaration: - case SyntaxKind.ExportDeclaration: - case SyntaxKind.NamedExports: - case SyntaxKind.ImportDeclaration: - case SyntaxKind.NamedImports: - return true; - } - - return false; - } - - static IsAfterCodeBlockContext(context: FormattingContext): boolean { - switch (context.currentTokenParent.kind) { - case SyntaxKind.ClassDeclaration: - case SyntaxKind.ModuleDeclaration: - case SyntaxKind.EnumDeclaration: - case SyntaxKind.CatchClause: - case SyntaxKind.ModuleBlock: - case SyntaxKind.SwitchStatement: - return true; - case SyntaxKind.Block: { - const blockParent = context.currentTokenParent.parent; - // In a codefix scenario, we can't rely on parents being set. So just always return true. - if (!blockParent || blockParent.kind !== SyntaxKind.ArrowFunction && blockParent.kind !== SyntaxKind.FunctionExpression) { - return true; - } } } - return false; } + return false; + } - static IsControlDeclContext(context: FormattingContext): boolean { - switch (context.contextNode.kind) { - case SyntaxKind.IfStatement: - case SyntaxKind.SwitchStatement: - case SyntaxKind.ForStatement: - case SyntaxKind.ForInStatement: - case SyntaxKind.ForOfStatement: - case SyntaxKind.WhileStatement: - case SyntaxKind.TryStatement: - case SyntaxKind.DoStatement: - case SyntaxKind.WithStatement: - // TODO - // case SyntaxKind.ElseClause: - case SyntaxKind.CatchClause: - return true; + function isControlDeclContext(context: FormattingContext): boolean { + switch (context.contextNode.kind) { + case SyntaxKind.IfStatement: + case SyntaxKind.SwitchStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.TryStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.WithStatement: + // TODO + // case SyntaxKind.ElseClause: + case SyntaxKind.CatchClause: + return true; - default: - return false; - } - } - - static IsObjectContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.ObjectLiteralExpression; - } - - static IsFunctionCallContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.CallExpression; - } - - static IsNewContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.NewExpression; - } - - static IsFunctionCallOrNewContext(context: FormattingContext): boolean { - return Rules.IsFunctionCallContext(context) || Rules.IsNewContext(context); - } - - static IsPreviousTokenNotComma(context: FormattingContext): boolean { - return context.currentTokenSpan.kind !== SyntaxKind.CommaToken; - } - - static IsNextTokenNotCloseBracket(context: FormattingContext): boolean { - return context.nextTokenSpan.kind !== SyntaxKind.CloseBracketToken; - } - - static IsArrowFunctionContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.ArrowFunction; - } - - static IsNonJsxSameLineTokenContext(context: FormattingContext): boolean { - return context.TokensAreOnSameLine() && context.contextNode.kind !== SyntaxKind.JsxText; - } - - static IsNonJsxElementContext(context: FormattingContext): boolean { - return context.contextNode.kind !== SyntaxKind.JsxElement; - } - - static IsJsxExpressionContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.JsxExpression; - } - - static IsNextTokenParentJsxAttribute(context: FormattingContext): boolean { - return context.nextTokenParent.kind === SyntaxKind.JsxAttribute; - } - - static IsJsxAttributeContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.JsxAttribute; - } - - static IsJsxSelfClosingElementContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.JsxSelfClosingElement; - } - - static IsNotBeforeBlockInFunctionDeclarationContext(context: FormattingContext): boolean { - return !Rules.IsFunctionDeclContext(context) && !Rules.IsBeforeBlockContext(context); - } - - static IsEndOfDecoratorContextOnSameLine(context: FormattingContext): boolean { - return context.TokensAreOnSameLine() && - context.contextNode.decorators && - Rules.NodeIsInDecoratorContext(context.currentTokenParent) && - !Rules.NodeIsInDecoratorContext(context.nextTokenParent); - } - - static NodeIsInDecoratorContext(node: Node): boolean { - while (isExpressionNode(node)) { - node = node.parent; - } - return node.kind === SyntaxKind.Decorator; - } - - static IsStartOfVariableDeclarationList(context: FormattingContext): boolean { - return context.currentTokenParent.kind === SyntaxKind.VariableDeclarationList && - context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos; - } - - static IsNotFormatOnEnter(context: FormattingContext): boolean { - return context.formattingRequestKind !== FormattingRequestKind.FormatOnEnter; - } - - static IsModuleDeclContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.ModuleDeclaration; - } - - static IsObjectTypeContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.TypeLiteral; // && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration; - } - - static IsConstructorSignatureContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.ConstructSignature; - } - - static IsTypeArgumentOrParameterOrAssertion(token: TextRangeWithKind, parent: Node): boolean { - if (token.kind !== SyntaxKind.LessThanToken && token.kind !== SyntaxKind.GreaterThanToken) { + default: return false; - } - switch (parent.kind) { - case SyntaxKind.TypeReference: - case SyntaxKind.TypeAssertionExpression: - case SyntaxKind.TypeAliasDeclaration: - case SyntaxKind.ClassDeclaration: - case SyntaxKind.ClassExpression: - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.FunctionExpression: - case SyntaxKind.ArrowFunction: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - case SyntaxKind.CallSignature: - case SyntaxKind.ConstructSignature: - case SyntaxKind.CallExpression: - case SyntaxKind.NewExpression: - case SyntaxKind.ExpressionWithTypeArguments: - return true; - default: - return false; - - } - } - - static IsTypeArgumentOrParameterOrAssertionContext(context: FormattingContext): boolean { - return Rules.IsTypeArgumentOrParameterOrAssertion(context.currentTokenSpan, context.currentTokenParent) || - Rules.IsTypeArgumentOrParameterOrAssertion(context.nextTokenSpan, context.nextTokenParent); - } - - static IsTypeAssertionContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.TypeAssertionExpression; - } - - static IsVoidOpContext(context: FormattingContext): boolean { - return context.currentTokenSpan.kind === SyntaxKind.VoidKeyword && context.currentTokenParent.kind === SyntaxKind.VoidExpression; - } - - static IsYieldOrYieldStarWithOperand(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.YieldExpression && (context.contextNode).expression !== undefined; - } - - static IsNonNullAssertionContext(context: FormattingContext): boolean { - return context.contextNode.kind === SyntaxKind.NonNullExpression; } } -} \ No newline at end of file + + function isObjectContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ObjectLiteralExpression; + } + + function isFunctionCallContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.CallExpression; + } + + function isNewContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.NewExpression; + } + + function isFunctionCallOrNewContext(context: FormattingContext): boolean { + return isFunctionCallContext(context) || isNewContext(context); + } + + function isPreviousTokenNotComma(context: FormattingContext): boolean { + return context.currentTokenSpan.kind !== SyntaxKind.CommaToken; + } + + function isNextTokenNotCloseBracket(context: FormattingContext): boolean { + return context.nextTokenSpan.kind !== SyntaxKind.CloseBracketToken; + } + + function isArrowFunctionContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ArrowFunction; + } + + function isNonJsxSameLineTokenContext(context: FormattingContext): boolean { + return context.TokensAreOnSameLine() && context.contextNode.kind !== SyntaxKind.JsxText; + } + + function isNonJsxElementContext(context: FormattingContext): boolean { + return context.contextNode.kind !== SyntaxKind.JsxElement; + } + + function isJsxExpressionContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.JsxExpression; + } + + function isNextTokenParentJsxAttribute(context: FormattingContext): boolean { + return context.nextTokenParent.kind === SyntaxKind.JsxAttribute; + } + + function isJsxAttributeContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.JsxAttribute; + } + + function isJsxSelfClosingElementContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.JsxSelfClosingElement; + } + + function isNotBeforeBlockInFunctionDeclarationContext(context: FormattingContext): boolean { + return !isFunctionDeclContext(context) && !isBeforeBlockContext(context); + } + + function isEndOfDecoratorContextOnSameLine(context: FormattingContext): boolean { + return context.TokensAreOnSameLine() && + context.contextNode.decorators && + nodeIsInDecoratorContext(context.currentTokenParent) && + !nodeIsInDecoratorContext(context.nextTokenParent); + } + + function nodeIsInDecoratorContext(node: Node): boolean { + while (isExpressionNode(node)) { + node = node.parent; + } + return node.kind === SyntaxKind.Decorator; + } + + function isStartOfVariableDeclarationList(context: FormattingContext): boolean { + return context.currentTokenParent.kind === SyntaxKind.VariableDeclarationList && + context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos; + } + + function isNotFormatOnEnter(context: FormattingContext): boolean { + return context.formattingRequestKind !== FormattingRequestKind.FormatOnEnter; + } + + function isModuleDeclContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ModuleDeclaration; + } + + function isObjectTypeContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.TypeLiteral; // && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration; + } + + function isConstructorSignatureContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ConstructSignature; + } + + function isTypeArgumentOrParameterOrAssertion(token: TextRangeWithKind, parent: Node): boolean { + if (token.kind !== SyntaxKind.LessThanToken && token.kind !== SyntaxKind.GreaterThanToken) { + return false; + } + switch (parent.kind) { + case SyntaxKind.TypeReference: + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.ExpressionWithTypeArguments: + return true; + default: + return false; + + } + } + + function isTypeArgumentOrParameterOrAssertionContext(context: FormattingContext): boolean { + return isTypeArgumentOrParameterOrAssertion(context.currentTokenSpan, context.currentTokenParent) || + isTypeArgumentOrParameterOrAssertion(context.nextTokenSpan, context.nextTokenParent); + } + + function isTypeAssertionContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.TypeAssertionExpression; + } + + function isVoidOpContext(context: FormattingContext): boolean { + return context.currentTokenSpan.kind === SyntaxKind.VoidKeyword && context.currentTokenParent.kind === SyntaxKind.VoidExpression; + } + + function isYieldOrYieldStarWithOperand(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.YieldExpression && (context.contextNode).expression !== undefined; + } + + function isNonNullAssertionContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.NonNullExpression; + } +} diff --git a/src/services/formatting/rulesMap.ts b/src/services/formatting/rulesMap.ts index 3b04308ebe8..d44e47a763a 100644 --- a/src/services/formatting/rulesMap.ts +++ b/src/services/formatting/rulesMap.ts @@ -1,60 +1,59 @@ -/// +/// /* @internal */ namespace ts.formatting { - export class RulesMap { - public map: RulesBucket[]; - public mapRowLength: number; + export function getFormatContext(options: FormatCodeSettings): formatting.FormatContext { + return { options, getRule: getRulesMap() }; + } - constructor(rules: ReadonlyArray) { - this.mapRowLength = SyntaxKind.LastToken + 1; - this.map = new Array(this.mapRowLength * this.mapRowLength); + let rulesMapCache: RulesMap | undefined; - // This array is used only during construction of the rulesbucket in the map - const rulesBucketConstructionStateList: RulesBucketConstructionState[] = new Array(this.map.length); - for (const rule of rules) { - this.FillRule(rule, rulesBucketConstructionStateList); - } + function getRulesMap(): RulesMap { + if (rulesMapCache === undefined) { + rulesMapCache = createRulesMap(getAllRules()); } + return rulesMapCache; + } - private GetRuleBucketIndex(row: number, column: number): number { - Debug.assert(row <= SyntaxKind.LastKeyword && column <= SyntaxKind.LastKeyword, "Must compute formatting context from tokens"); - return (row * this.mapRowLength) + column; - } + export type RulesMap = (context: FormattingContext) => Rule | undefined; + function createRulesMap(rules: ReadonlyArray): RulesMap { + const map = buildMap(rules); + return context => { + const bucket = map[getRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind)]; + return bucket && find(bucket, rule => every(rule.context, c => c(context))); + }; + } - private FillRule(rule: Rule, rulesBucketConstructionStateList: RulesBucketConstructionState[]): void { - const specificRule = rule.descriptor.leftTokenRange.isSpecific() && rule.descriptor.rightTokenRange.isSpecific(); + function buildMap(rules: ReadonlyArray): ReadonlyArray> { + // Map from bucket index to array of rules + const map: Rule[][] = new Array(mapRowLength * mapRowLength); + // This array is used only during construction of the rulesbucket in the map + const rulesBucketConstructionStateList = new Array(map.length); + for (const rule of rules) { + const specificRule = rule.leftTokenRange.isSpecific && rule.rightTokenRange.isSpecific; - rule.descriptor.leftTokenRange.GetTokens().forEach((left) => { - rule.descriptor.rightTokenRange.GetTokens().forEach((right) => { - const rulesBucketIndex = this.GetRuleBucketIndex(left, right); - - let rulesBucket = this.map[rulesBucketIndex]; + for (const left of rule.leftTokenRange.tokens) { + for (const right of rule.rightTokenRange.tokens) { + const index = getRuleBucketIndex(left, right); + let rulesBucket = map[index]; if (rulesBucket === undefined) { - rulesBucket = this.map[rulesBucketIndex] = new RulesBucket(); - } - - rulesBucket.AddRule(rule, specificRule, rulesBucketConstructionStateList, rulesBucketIndex); - }); - }); - } - - public GetRule(context: FormattingContext): Rule | undefined { - const bucketIndex = this.GetRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind); - const bucket = this.map[bucketIndex]; - if (bucket) { - for (const rule of bucket.Rules()) { - if (rule.operation.context.InContext(context)) { - return rule; + rulesBucket = map[index] = []; } + addRule(rulesBucket, rule.rule, specificRule, rulesBucketConstructionStateList, index); } } - return undefined; } + return map; + } + + function getRuleBucketIndex(row: number, column: number): number { + Debug.assert(row <= SyntaxKind.LastKeyword && column <= SyntaxKind.LastKeyword, "Must compute formatting context from tokens"); + return (row * mapRowLength) + column; } const maskBitSize = 5; - const mask = 0x1f; + const mask = 0b11111; // MaskBitSize bits + const mapRowLength = SyntaxKind.LastToken + 1; enum RulesPosition { IgnoreRulesSpecific = 0, @@ -65,92 +64,44 @@ namespace ts.formatting { NoContextRulesAny = maskBitSize * 5 } - export class RulesBucketConstructionState { - private rulesInsertionIndexBitmap: number; - - constructor() { - //// The Rules list contains all the inserted rules into a rulebucket in the following order: - //// 1- Ignore rules with specific token combination - //// 2- Ignore rules with any token combination - //// 3- Context rules with specific token combination - //// 4- Context rules with any token combination - //// 5- Non-context rules with specific token combination - //// 6- Non-context rules with any token combination - //// - //// The member rulesInsertionIndexBitmap is used to describe the number of rules - //// in each sub-bucket (above) hence can be used to know the index of where to insert - //// the next rule. It's a bitmap which contains 6 different sections each is given 5 bits. - //// - //// Example: - //// In order to insert a rule to the end of sub-bucket (3), we get the index by adding - //// the values in the bitmap segments 3rd, 2nd, and 1st. - this.rulesInsertionIndexBitmap = 0; - } - - public GetInsertionIndex(maskPosition: RulesPosition): number { - let index = 0; - - let pos = 0; - let indexBitmap = this.rulesInsertionIndexBitmap; - - while (pos <= maskPosition) { - index += (indexBitmap & mask); - indexBitmap >>= maskBitSize; - pos += maskBitSize; - } - - return index; - } - - public IncreaseInsertionIndex(maskPosition: RulesPosition): void { - let value = (this.rulesInsertionIndexBitmap >> maskPosition) & mask; - value++; - Debug.assert((value & mask) === value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules."); - - let temp = this.rulesInsertionIndexBitmap & ~(mask << maskPosition); - temp |= value << maskPosition; - - this.rulesInsertionIndexBitmap = temp; - } + // The Rules list contains all the inserted rules into a rulebucket in the following order: + // 1- Ignore rules with specific token combination + // 2- Ignore rules with any token combination + // 3- Context rules with specific token combination + // 4- Context rules with any token combination + // 5- Non-context rules with specific token combination + // 6- Non-context rules with any token combination + // + // The member rulesInsertionIndexBitmap is used to describe the number of rules + // in each sub-bucket (above) hence can be used to know the index of where to insert + // the next rule. It's a bitmap which contains 6 different sections each is given 5 bits. + // + // Example: + // In order to insert a rule to the end of sub-bucket (3), we get the index by adding + // the values in the bitmap segments 3rd, 2nd, and 1st. + function addRule(rules: Rule[], rule: Rule, specificTokens: boolean, constructionState: number[], rulesBucketIndex: number): void { + const position = rule.action === RuleAction.Ignore + ? specificTokens ? RulesPosition.IgnoreRulesSpecific : RulesPosition.IgnoreRulesAny + : rule.context !== anyContext + ? specificTokens ? RulesPosition.ContextRulesSpecific : RulesPosition.ContextRulesAny + : specificTokens ? RulesPosition.NoContextRulesSpecific : RulesPosition.NoContextRulesAny; + const state = constructionState[rulesBucketIndex] || 0; + rules.splice(getInsertionIndex(state, position), 0, rule); + constructionState[rulesBucketIndex] = increaseInsertionIndex(state, position); } - export class RulesBucket { - private rules: Rule[]; - - constructor() { - this.rules = []; + function getInsertionIndex(indexBitmap: number, maskPosition: RulesPosition) { + let index = 0; + for (let pos = 0; pos <= maskPosition; pos += maskBitSize) { + index += indexBitmap & mask; + indexBitmap >>= maskBitSize; } + return index; + } - public Rules(): Rule[] { - return this.rules; - } - - public AddRule(rule: Rule, specificTokens: boolean, constructionState: RulesBucketConstructionState[], rulesBucketIndex: number): void { - let position: RulesPosition; - - if (rule.operation.action === RuleAction.Ignore) { - position = specificTokens ? - RulesPosition.IgnoreRulesSpecific : - RulesPosition.IgnoreRulesAny; - } - else if (!rule.operation.context.IsAny()) { - position = specificTokens ? - RulesPosition.ContextRulesSpecific : - RulesPosition.ContextRulesAny; - } - else { - position = specificTokens ? - RulesPosition.NoContextRulesSpecific : - RulesPosition.NoContextRulesAny; - } - - let state = constructionState[rulesBucketIndex]; - if (state === undefined) { - state = constructionState[rulesBucketIndex] = new RulesBucketConstructionState(); - } - const index = state.GetInsertionIndex(position); - this.rules.splice(index, 0, rule); - state.IncreaseInsertionIndex(position); - } + function increaseInsertionIndex(indexBitmap: number, maskPosition: RulesPosition): number { + const value = ((indexBitmap >> maskPosition) & mask) + 1; + Debug.assert((value & mask) === value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules."); + return (indexBitmap & ~(mask << maskPosition)) | (value << maskPosition); } } \ No newline at end of file diff --git a/src/services/formatting/rulesProvider.ts b/src/services/formatting/rulesProvider.ts deleted file mode 100644 index fcf08541890..00000000000 --- a/src/services/formatting/rulesProvider.ts +++ /dev/null @@ -1,30 +0,0 @@ -/// - -/* @internal */ -namespace ts.formatting { - export class RulesProvider { - private globalRules: Rules; - private options: ts.FormatCodeSettings; - private rulesMap: RulesMap; - - constructor() { - this.globalRules = new Rules(); - const activeRules = this.globalRules.HighPriorityCommonRules.concat(this.globalRules.UserConfigurableRules).concat(this.globalRules.LowPriorityCommonRules); - this.rulesMap = new RulesMap(activeRules); - } - - public getRulesMap() { - return this.rulesMap; - } - - public getFormatOptions(): Readonly { - return this.options; - } - - public ensureUpToDate(options: ts.FormatCodeSettings) { - if (!this.options || !ts.compareDataObjects(this.options, options)) { - this.options = ts.clone(options); - } - } - } -} \ No newline at end of file diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 7701cff182c..5afe4cb1d31 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -1,5 +1,3 @@ -/// - /* @internal */ namespace ts.formatting { export namespace SmartIndenter { diff --git a/src/services/formatting/tokenRange.ts b/src/services/formatting/tokenRange.ts deleted file mode 100644 index 31e15bc738d..00000000000 --- a/src/services/formatting/tokenRange.ts +++ /dev/null @@ -1,124 +0,0 @@ -/// - -/* @internal */ -namespace ts.formatting { - export namespace Shared { - const allTokens: SyntaxKind[] = []; - for (let token = SyntaxKind.FirstToken; token <= SyntaxKind.LastToken; token++) { - allTokens.push(token); - } - - class TokenValuesAccess implements TokenRange { - constructor(private readonly tokens: SyntaxKind[] = []) { } - - public GetTokens(): SyntaxKind[] { - return this.tokens; - } - - public Contains(token: SyntaxKind): boolean { - return this.tokens.indexOf(token) >= 0; - } - - public isSpecific() { return true; } - } - - class TokenSingleValueAccess implements TokenRange { - constructor(private readonly token: SyntaxKind) {} - - public GetTokens(): SyntaxKind[] { - return [this.token]; - } - - public Contains(tokenValue: SyntaxKind): boolean { - return tokenValue === this.token; - } - - public isSpecific() { return true; } - } - - class TokenAllAccess implements TokenRange { - public GetTokens(): SyntaxKind[] { - return allTokens; - } - - public Contains(): boolean { - return true; - } - - public toString(): string { - return "[allTokens]"; - } - - public isSpecific() { return false; } - } - - class TokenAllExceptAccess implements TokenRange { - constructor(private readonly except: SyntaxKind) {} - - public GetTokens(): SyntaxKind[] { - return allTokens.filter(t => t !== this.except); - } - - public Contains(token: SyntaxKind): boolean { - return token !== this.except; - } - - public isSpecific() { return false; } - } - - export interface TokenRange { - GetTokens(): SyntaxKind[]; - Contains(token: SyntaxKind): boolean; - isSpecific(): boolean; - } - - export namespace TokenRange { - export function FromToken(token: SyntaxKind): TokenRange { - return new TokenSingleValueAccess(token); - } - - export function FromTokens(tokens: SyntaxKind[]): TokenRange { - return new TokenValuesAccess(tokens); - } - - export function FromRange(from: SyntaxKind, to: SyntaxKind, except: SyntaxKind[] = []): TokenRange { - const tokens: SyntaxKind[] = []; - for (let token = from; token <= to; token++) { - if (ts.indexOf(except, token) < 0) { - tokens.push(token); - } - } - return new TokenValuesAccess(tokens); - } - - export function AnyExcept(token: SyntaxKind): TokenRange { - return new TokenAllExceptAccess(token); - } - - // tslint:disable variable-name (TODO) - export const Any: TokenRange = new TokenAllAccess(); - export const AnyIncludingMultilineComments = TokenRange.FromTokens([...allTokens, SyntaxKind.MultiLineCommentTrivia]); - export const Keywords = TokenRange.FromRange(SyntaxKind.FirstKeyword, SyntaxKind.LastKeyword); - export const BinaryOperators = TokenRange.FromRange(SyntaxKind.FirstBinaryOperator, SyntaxKind.LastBinaryOperator); - export const BinaryKeywordOperators = TokenRange.FromTokens([ - SyntaxKind.InKeyword, SyntaxKind.InstanceOfKeyword, SyntaxKind.OfKeyword, SyntaxKind.AsKeyword, SyntaxKind.IsKeyword]); - export const UnaryPrefixOperators = TokenRange.FromTokens([ - SyntaxKind.PlusPlusToken, SyntaxKind.MinusMinusToken, SyntaxKind.TildeToken, SyntaxKind.ExclamationToken]); - export const UnaryPrefixExpressions = TokenRange.FromTokens([ - SyntaxKind.NumericLiteral, SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, - SyntaxKind.OpenBraceToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]); - export const UnaryPreincrementExpressions = TokenRange.FromTokens([ - SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]); - export const UnaryPostincrementExpressions = TokenRange.FromTokens([ - SyntaxKind.Identifier, SyntaxKind.CloseParenToken, SyntaxKind.CloseBracketToken, SyntaxKind.NewKeyword]); - export const UnaryPredecrementExpressions = TokenRange.FromTokens([ - SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]); - export const UnaryPostdecrementExpressions = TokenRange.FromTokens([ - SyntaxKind.Identifier, SyntaxKind.CloseParenToken, SyntaxKind.CloseBracketToken, SyntaxKind.NewKeyword]); - export const Comments = TokenRange.FromTokens([SyntaxKind.SingleLineCommentTrivia, SyntaxKind.MultiLineCommentTrivia]); - export const TypeNames = TokenRange.FromTokens([ - SyntaxKind.Identifier, SyntaxKind.NumberKeyword, SyntaxKind.StringKeyword, SyntaxKind.BooleanKeyword, - SyntaxKind.SymbolKeyword, SyntaxKind.VoidKeyword, SyntaxKind.AnyKeyword]); - } - } -} diff --git a/src/services/refactors/convertFunctionToEs6Class.ts b/src/services/refactors/convertFunctionToEs6Class.ts index f5951bd26e4..b66d14ee449 100644 --- a/src/services/refactors/convertFunctionToEs6Class.ts +++ b/src/services/refactors/convertFunctionToEs6Class.ts @@ -50,7 +50,7 @@ namespace ts.refactor.convertFunctionToES6Class { const { file: sourceFile } = context; const ctorSymbol = getConstructorSymbol(context); - const newLine = context.rulesProvider.getFormatOptions().newLineCharacter; + const newLine = context.formatContext.options.newLineCharacter; const deletedNodes: Node[] = []; const deletes: (() => any)[] = []; diff --git a/src/services/services.ts b/src/services/services.ts index 04a8e148b73..37298c8eba8 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -33,9 +33,6 @@ namespace ts { /** The version of the language service API */ export const servicesVersion = "0.7"; - /* @internal */ - let ruleProvider: formatting.RulesProvider; - function createNode(kind: TKind, pos: number, end: number, parent?: Node): NodeObject | TokenObject | IdentifierObject { const node = isNodeKind(kind) ? new NodeObject(kind, pos, end) : kind === SyntaxKind.Identifier ? new IdentifierObject(SyntaxKind.Identifier, pos, end) : @@ -1157,7 +1154,6 @@ namespace ts { documentRegistry: DocumentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory())): LanguageService { const syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host); - ruleProvider = ruleProvider || new formatting.RulesProvider(); let program: Program; let lastProjectVersion: string; let lastTypesRootVersion = 0; @@ -1187,11 +1183,6 @@ namespace ts { return sourceFile; } - function getRuleProvider(options: FormatCodeSettings) { - ruleProvider.ensureUpToDate(options); - return ruleProvider; - } - function synchronizeHostData(): void { // perform fast check if host supports it if (host.getProjectVersion) { @@ -1429,7 +1420,6 @@ namespace ts { function getCompletionEntryDetails(fileName: string, position: number, name: string, formattingOptions?: FormatCodeSettings, source?: string): CompletionEntryDetails { synchronizeHostData(); - const ruleProvider = formattingOptions ? getRuleProvider(formattingOptions) : undefined; return Completions.getCompletionEntryDetails( program.getTypeChecker(), log, @@ -1439,7 +1429,7 @@ namespace ts { { name, source }, program.getSourceFiles(), host, - ruleProvider); + formattingOptions && formatting.getFormatContext(formattingOptions)); } function getCompletionEntrySymbol(fileName: string, position: number, name: string, source?: string): Symbol { @@ -1838,32 +1828,27 @@ namespace ts { function getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[] { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - const settings = toEditorSettings(options); - return formatting.formatSelection(start, end, sourceFile, getRuleProvider(settings), settings); + return formatting.formatSelection(start, end, sourceFile, formatting.getFormatContext(toEditorSettings(options))); } function getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[] { - const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - const settings = toEditorSettings(options); - return formatting.formatDocument(sourceFile, getRuleProvider(settings), settings); + return formatting.formatDocument(syntaxTreeCache.getCurrentSourceFile(fileName), formatting.getFormatContext(toEditorSettings(options))); } function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[] { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - const settings = toEditorSettings(options); + const formatContext = formatting.getFormatContext(toEditorSettings(options)); if (!isInComment(sourceFile, position)) { - if (key === "{") { - return formatting.formatOnOpeningCurly(position, sourceFile, getRuleProvider(settings), settings); - } - else if (key === "}") { - return formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(settings), settings); - } - else if (key === ";") { - return formatting.formatOnSemicolon(position, sourceFile, getRuleProvider(settings), settings); - } - else if (key === "\n") { - return formatting.formatOnEnter(position, sourceFile, getRuleProvider(settings), settings); + switch (key) { + case "{": + return formatting.formatOnOpeningCurly(position, sourceFile, formatContext); + case "}": + return formatting.formatOnClosingCurly(position, sourceFile, formatContext); + case ";": + return formatting.formatOnSemicolon(position, sourceFile, formatContext); + case "\n": + return formatting.formatOnEnter(position, sourceFile, formatContext); } } @@ -1875,11 +1860,11 @@ namespace ts { const sourceFile = getValidSourceFile(fileName); const span = createTextSpanFromBounds(start, end); const newLineCharacter = getNewLineOrDefaultFromHost(host); - const rulesProvider = getRuleProvider(formatOptions); + const formatContext = formatting.getFormatContext(formatOptions); return flatMap(deduplicate(errorCodes, equateValues, compareValues), errorCode => { cancellationToken.throwIfCancellationRequested(); - return codefix.getFixes({ errorCode, sourceFile, span, program, newLineCharacter, host, cancellationToken, rulesProvider }); + return codefix.getFixes({ errorCode, sourceFile, span, program, newLineCharacter, host, cancellationToken, formatContext }); }); } @@ -2104,7 +2089,7 @@ namespace ts { program: getProgram(), newLineCharacter: formatOptions ? formatOptions.newLineCharacter : host.getNewLine(), host, - rulesProvider: getRuleProvider(formatOptions), + formatContext: formatting.getFormatContext(formatOptions), cancellationToken, }; } diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index bc3a8e27ef0..7c4e25537ef 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -188,7 +188,7 @@ namespace ts.textChanges { export interface TextChangesContext { newLineCharacter: string; - rulesProvider: formatting.RulesProvider; + formatContext: ts.formatting.FormatContext; } export class ChangeTracker { @@ -196,7 +196,7 @@ namespace ts.textChanges { private readonly newLineCharacter: string; public static fromContext(context: TextChangesContext): ChangeTracker { - return new ChangeTracker(context.newLineCharacter === "\n" ? NewLineKind.LineFeed : NewLineKind.CarriageReturnLineFeed, context.rulesProvider); + return new ChangeTracker(context.newLineCharacter === "\n" ? NewLineKind.LineFeed : NewLineKind.CarriageReturnLineFeed, context.formatContext); } public static with(context: TextChangesContext, cb: (tracker: ChangeTracker) => void): FileTextChanges[] { @@ -207,7 +207,7 @@ namespace ts.textChanges { constructor( private readonly newLine: NewLineKind, - private readonly rulesProvider: formatting.RulesProvider, + private readonly formatContext: ts.formatting.FormatContext, private readonly validator?: (text: NonFormattedText) => void) { this.newLineCharacter = getNewLineCharacter({ newLine }); } @@ -475,7 +475,7 @@ namespace ts.textChanges { options: {} }); // use the same indentation as 'after' item - const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(afterStartLinePosition, afterStart, sourceFile, this.rulesProvider.getFormatOptions()); + const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(afterStartLinePosition, afterStart, sourceFile, this.formatContext.options); // insert element before the line break on the line that contains 'after' element let insertPos = skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ false); if (insertPos !== end && isLineBreak(sourceFile.text.charCodeAt(insertPos - 1))) { @@ -562,7 +562,7 @@ namespace ts.textChanges { this.validator(nonformattedText); } - const formatOptions = this.rulesProvider.getFormatOptions(); + const { options: formatOptions } = this.formatContext; const posStartsLine = getLineStartPositionForPosition(pos, sourceFile) === pos; const initialIndentation = @@ -578,7 +578,7 @@ namespace ts.textChanges { ? (formatOptions.indentSize || 0) : 0; - return applyFormatting(nonformattedText, sourceFile, initialIndentation, delta, this.rulesProvider); + return applyFormatting(nonformattedText, sourceFile, initialIndentation, delta, this.formatContext); } private static normalize(changes: Change[]): Change[] { @@ -605,14 +605,14 @@ namespace ts.textChanges { return { text: writer.getText(), node: assignPositionsToNode(node) }; } - function applyFormatting(nonFormattedText: NonFormattedText, sourceFile: SourceFile, initialIndentation: number, delta: number, rulesProvider: formatting.RulesProvider) { + function applyFormatting(nonFormattedText: NonFormattedText, sourceFile: SourceFile, initialIndentation: number, delta: number, formatContext: ts.formatting.FormatContext) { const lineMap = computeLineStarts(nonFormattedText.text); const file: SourceFileLike = { text: nonFormattedText.text, lineMap, getLineAndCharacterOfPosition: pos => computeLineAndCharacterOfPosition(lineMap, pos) }; - const changes = formatting.formatNodeGivenIndentation(nonFormattedText.node, file, sourceFile.languageVariant, initialIndentation, delta, rulesProvider); + const changes = formatting.formatNodeGivenIndentation(nonFormattedText.node, file, sourceFile.languageVariant, initialIndentation, delta, formatContext); return applyChanges(nonFormattedText.text, changes); } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index f59f6e56e91..1ed44d29f95 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1068,20 +1068,19 @@ namespace ts { return createTextSpanFromBounds(range.pos, range.end); } + export const typeKeywords: ReadonlyArray = [ + SyntaxKind.AnyKeyword, + SyntaxKind.BooleanKeyword, + SyntaxKind.NeverKeyword, + SyntaxKind.NumberKeyword, + SyntaxKind.ObjectKeyword, + SyntaxKind.StringKeyword, + SyntaxKind.SymbolKeyword, + SyntaxKind.VoidKeyword, + ]; + export function isTypeKeyword(kind: SyntaxKind): boolean { - switch (kind) { - case SyntaxKind.AnyKeyword: - case SyntaxKind.BooleanKeyword: - case SyntaxKind.NeverKeyword: - case SyntaxKind.NumberKeyword: - case SyntaxKind.ObjectKeyword: - case SyntaxKind.StringKeyword: - case SyntaxKind.SymbolKeyword: - case SyntaxKind.VoidKeyword: - return true; - default: - return false; - } + return contains(typeKeywords, kind); } /** True if the symbol is for an external module, as opposed to a namespace. */ From 6b08f3b99dc1fa72b66216b2a072eaf8382df3ee Mon Sep 17 00:00:00 2001 From: csigs Date: Wed, 8 Nov 2017 23:10:37 +0000 Subject: [PATCH 37/73] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl index 17236daf66b..bd78324f196 100644 --- a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2240,6 +2240,15 @@ + + + + + + + + + @@ -2969,6 +2978,15 @@ + + + + + + + + + @@ -3707,6 +3725,18 @@ + + + + + + + + + + + + @@ -3938,6 +3968,12 @@ + + + + + + @@ -4211,6 +4247,24 @@ + + + + + + + + + + + + + + + + + + From c1c79267352619c671d65d20878f1cbc6d325ccb Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 8 Nov 2017 15:18:35 -0800 Subject: [PATCH 38/73] Revert "Add TupleBase with unusable mutating Array methods" This reverts commits 4385444c4488f7d0fe802e58b7de303e088e0a01, 2399d58, es55de3, 888da3c --- src/compiler/checker.ts | 11 +++--- src/lib/es5.d.ts | 17 --------- .../arityAndOrderCompatibility01.errors.txt | 2 +- .../reference/arityAndOrderCompatibility01.js | 2 +- .../arityAndOrderCompatibility01.symbols | 4 +-- .../arityAndOrderCompatibility01.types | 4 +-- ...nmentCompatBetweenTupleAndArray.errors.txt | 18 +++++----- .../baselines/reference/tupleTypes.errors.txt | 36 +++++++++---------- .../typeInferenceWithTupleType.errors.txt | 31 ---------------- .../typeInferenceWithTupleType.symbols | 4 +-- .../typeInferenceWithTupleType.types | 8 ++--- .../tuple/arityAndOrderCompatibility01.ts | 2 +- 12 files changed, 41 insertions(+), 98 deletions(-) delete mode 100644 tests/baselines/reference/typeInferenceWithTupleType.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 264b5dad105..5aed0596ae2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -330,7 +330,6 @@ namespace ts { let globalFunctionType: ObjectType; let globalArrayType: GenericType; let globalReadonlyArrayType: GenericType; - let globalTupleBaseType: GenericType; let globalStringType: ObjectType; let globalNumberType: ObjectType; let globalBooleanType: ObjectType; @@ -773,7 +772,7 @@ namespace ts { * @param parameterName a name of the parameter to get the symbols for. * @return a tuple of two symbols */ - function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: __String): Symbol[] { + function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: __String): [Symbol, Symbol] { const constructorDeclaration = parameter.parent; const classDeclaration = parameter.parent.parent; @@ -4993,7 +4992,7 @@ namespace ts { function getBaseTypes(type: InterfaceType): BaseType[] { if (!type.resolvedBaseTypes) { if (type.objectFlags & ObjectFlags.Tuple) { - type.resolvedBaseTypes = [createTypeFromGenericGlobalType(globalTupleBaseType, [getUnionType(type.typeParameters)])]; + type.resolvedBaseTypes = [createArrayType(getUnionType(type.typeParameters))]; } else if (type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { if (type.symbol.flags & SymbolFlags.Class) { @@ -10018,7 +10017,7 @@ namespace ts { const typeParameters = type.typeParameters || emptyArray; let variances = type.variances; if (!variances) { - if (type === globalArrayType || type === globalReadonlyArrayType || type === globalTupleBaseType) { + if (type === globalArrayType || type === globalReadonlyArrayType) { // Arrays are known to be covariant, no need to spend time computing this variances = [Variance.Covariant]; } @@ -10347,7 +10346,7 @@ namespace ts { function isArrayLikeType(type: Type): boolean { // A type is array-like if it is a reference to the global Array or global ReadonlyArray type, // or if it is not the undefined or null type and if it is assignable to ReadonlyArray - return getObjectFlags(type) & ObjectFlags.Reference && ((type).target === globalArrayType || (type).target === globalReadonlyArrayType || (type as TypeReference).target === globalTupleBaseType) || + return getObjectFlags(type) & ObjectFlags.Reference && ((type).target === globalArrayType || (type).target === globalReadonlyArrayType) || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType); } @@ -24524,9 +24523,7 @@ namespace ts { anyArrayType = createArrayType(anyType); autoArrayType = createArrayType(autoType); - // TODO: ReadonlyArray and TupleBase should always be available, but haven't been required previously globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray" as __String, /*arity*/ 1); - globalTupleBaseType = getGlobalTypeOrUndefined("TupleBase" as __String, /*arity*/ 1) || globalArrayType; anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; globalThisType = getGlobalTypeOrUndefined("ThisType" as __String, /*arity*/ 1); } diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index d3760e3a310..fd2ae5b3fdf 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1240,23 +1240,6 @@ interface ArrayConstructor { declare const Array: ArrayConstructor; -interface TupleBase extends Array { - /** Mutation is not allowed on tuples. Do not use this method. */ - push: never; - /** Mutation is not allowed on tuples. Do not use this method. */ - pop: never; - /** Mutation is not allowed on tuples. Do not use this method. */ - reverse: never; - /** Mutation is not allowed on tuples. Do not use this method. */ - sort: never; - /** Mutation is not allowed on tuples. Do not use this method. */ - shift: never; - /** Mutation is not allowed on tuples. Do not use this method. */ - unshift: never; - /** Mutation is not allowed on tuples. Do not use this method. */ - splice: never; -} - interface TypedPropertyDescriptor { enumerable?: boolean; configurable?: boolean; diff --git a/tests/baselines/reference/arityAndOrderCompatibility01.errors.txt b/tests/baselines/reference/arityAndOrderCompatibility01.errors.txt index 273d1f3b318..4d6fbd063ae 100644 --- a/tests/baselines/reference/arityAndOrderCompatibility01.errors.txt +++ b/tests/baselines/reference/arityAndOrderCompatibility01.errors.txt @@ -40,7 +40,7 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(32,5): error ==== tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts (19 errors) ==== - interface StrNum extends TupleBase { + interface StrNum extends Array { 0: string; 1: number; length: 2; diff --git a/tests/baselines/reference/arityAndOrderCompatibility01.js b/tests/baselines/reference/arityAndOrderCompatibility01.js index e097b72594e..bf7736a80c9 100644 --- a/tests/baselines/reference/arityAndOrderCompatibility01.js +++ b/tests/baselines/reference/arityAndOrderCompatibility01.js @@ -1,5 +1,5 @@ //// [arityAndOrderCompatibility01.ts] -interface StrNum extends TupleBase { +interface StrNum extends Array { 0: string; 1: number; length: 2; diff --git a/tests/baselines/reference/arityAndOrderCompatibility01.symbols b/tests/baselines/reference/arityAndOrderCompatibility01.symbols index 8305819f593..3a5d55dc1e6 100644 --- a/tests/baselines/reference/arityAndOrderCompatibility01.symbols +++ b/tests/baselines/reference/arityAndOrderCompatibility01.symbols @@ -1,7 +1,7 @@ === tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts === -interface StrNum extends TupleBase { +interface StrNum extends Array { >StrNum : Symbol(StrNum, Decl(arityAndOrderCompatibility01.ts, 0, 0)) ->TupleBase : Symbol(TupleBase, Decl(lib.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) 0: string; 1: number; diff --git a/tests/baselines/reference/arityAndOrderCompatibility01.types b/tests/baselines/reference/arityAndOrderCompatibility01.types index 67a02599c40..80e91fbd2e7 100644 --- a/tests/baselines/reference/arityAndOrderCompatibility01.types +++ b/tests/baselines/reference/arityAndOrderCompatibility01.types @@ -1,7 +1,7 @@ === tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts === -interface StrNum extends TupleBase { +interface StrNum extends Array { >StrNum : StrNum ->TupleBase : TupleBase +>Array : T[] 0: string; 1: number; diff --git a/tests/baselines/reference/assignmentCompatBetweenTupleAndArray.errors.txt b/tests/baselines/reference/assignmentCompatBetweenTupleAndArray.errors.txt index 53073a5300a..03dcee9baf3 100644 --- a/tests/baselines/reference/assignmentCompatBetweenTupleAndArray.errors.txt +++ b/tests/baselines/reference/assignmentCompatBetweenTupleAndArray.errors.txt @@ -1,9 +1,8 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatBetweenTupleAndArray.ts(17,1): error TS2322: Type '[number, string]' is not assignable to type 'number[]'. - Types of property 'concat' are incompatible. - Type '{ (...items: ReadonlyArray[]): (string | number)[]; (...items: (string | number | ReadonlyArray)[]): (string | number)[]; }' is not assignable to type '{ (...items: ReadonlyArray[]): number[]; (...items: (number | ReadonlyArray)[]): number[]; }'. - Type '(string | number)[]' is not assignable to type 'number[]'. - Type 'string | number' is not assignable to type 'number'. - Type 'string' is not assignable to type 'number'. + Types of property 'pop' are incompatible. + Type '() => string | number' is not assignable to type '() => number'. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignmentCompatBetweenTupleAndArray.ts(18,1): error TS2322: Type '{}[]' is not assignable to type '[{}]'. Property '0' is missing in type '{}[]'. @@ -28,11 +27,10 @@ tests/cases/conformance/types/typeRelationships/assignmentCompatibility/assignme numArray = numStrTuple; ~~~~~~~~ !!! error TS2322: Type '[number, string]' is not assignable to type 'number[]'. -!!! error TS2322: Types of property 'concat' are incompatible. -!!! error TS2322: Type '{ (...items: ReadonlyArray[]): (string | number)[]; (...items: (string | number | ReadonlyArray)[]): (string | number)[]; }' is not assignable to type '{ (...items: ReadonlyArray[]): number[]; (...items: (number | ReadonlyArray)[]): number[]; }'. -!!! error TS2322: Type '(string | number)[]' is not assignable to type 'number[]'. -!!! error TS2322: Type 'string | number' is not assignable to type 'number'. -!!! error TS2322: Type 'string' is not assignable to type 'number'. +!!! error TS2322: Types of property 'pop' are incompatible. +!!! error TS2322: Type '() => string | number' is not assignable to type '() => number'. +!!! error TS2322: Type 'string | number' is not assignable to type 'number'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. emptyObjTuple = emptyObjArray; ~~~~~~~~~~~~~ !!! error TS2322: Type '{}[]' is not assignable to type '[{}]'. diff --git a/tests/baselines/reference/tupleTypes.errors.txt b/tests/baselines/reference/tupleTypes.errors.txt index 750df3f5092..16a8f66ba79 100644 --- a/tests/baselines/reference/tupleTypes.errors.txt +++ b/tests/baselines/reference/tupleTypes.errors.txt @@ -10,17 +10,15 @@ tests/cases/compiler/tupleTypes.ts(18,1): error TS2322: Type '[number, string, n Type '3' is not assignable to type '2'. tests/cases/compiler/tupleTypes.ts(41,1): error TS2322: Type 'undefined[]' is not assignable to type '[number, string]'. tests/cases/compiler/tupleTypes.ts(47,1): error TS2322: Type '[number, string]' is not assignable to type 'number[]'. - Types of property 'concat' are incompatible. - Type '{ (...items: ReadonlyArray[]): (string | number)[]; (...items: (string | number | ReadonlyArray)[]): (string | number)[]; }' is not assignable to type '{ (...items: ReadonlyArray[]): number[]; (...items: (number | ReadonlyArray)[]): number[]; }'. - Type '(string | number)[]' is not assignable to type 'number[]'. - Type 'string | number' is not assignable to type 'number'. - Type 'string' is not assignable to type 'number'. + Types of property 'pop' are incompatible. + Type '() => string | number' is not assignable to type '() => number'. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. tests/cases/compiler/tupleTypes.ts(49,1): error TS2322: Type '[number, {}]' is not assignable to type 'number[]'. - Types of property 'concat' are incompatible. - Type '{ (...items: ReadonlyArray[]): (number | {})[]; (...items: (number | {} | ReadonlyArray)[]): (number | {})[]; }' is not assignable to type '{ (...items: ReadonlyArray[]): number[]; (...items: (number | ReadonlyArray)[]): number[]; }'. - Type '(number | {})[]' is not assignable to type 'number[]'. - Type 'number | {}' is not assignable to type 'number'. - Type '{}' is not assignable to type 'number'. + Types of property 'pop' are incompatible. + Type '() => number | {}' is not assignable to type '() => number'. + Type 'number | {}' is not assignable to type 'number'. + Type '{}' is not assignable to type 'number'. tests/cases/compiler/tupleTypes.ts(50,1): error TS2322: Type '[number, number]' is not assignable to type '[number, string]'. Type 'number' is not assignable to type 'string'. tests/cases/compiler/tupleTypes.ts(51,1): error TS2322: Type '[number, {}]' is not assignable to type '[number, string]'. @@ -94,20 +92,18 @@ tests/cases/compiler/tupleTypes.ts(51,1): error TS2322: Type '[number, {}]' is n a = a1; // Error ~ !!! error TS2322: Type '[number, string]' is not assignable to type 'number[]'. -!!! error TS2322: Types of property 'concat' are incompatible. -!!! error TS2322: Type '{ (...items: ReadonlyArray[]): (string | number)[]; (...items: (string | number | ReadonlyArray)[]): (string | number)[]; }' is not assignable to type '{ (...items: ReadonlyArray[]): number[]; (...items: (number | ReadonlyArray)[]): number[]; }'. -!!! error TS2322: Type '(string | number)[]' is not assignable to type 'number[]'. -!!! error TS2322: Type 'string | number' is not assignable to type 'number'. -!!! error TS2322: Type 'string' is not assignable to type 'number'. +!!! error TS2322: Types of property 'pop' are incompatible. +!!! error TS2322: Type '() => string | number' is not assignable to type '() => number'. +!!! error TS2322: Type 'string | number' is not assignable to type 'number'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. a = a2; a = a3; // Error ~ !!! error TS2322: Type '[number, {}]' is not assignable to type 'number[]'. -!!! error TS2322: Types of property 'concat' are incompatible. -!!! error TS2322: Type '{ (...items: ReadonlyArray[]): (number | {})[]; (...items: (number | {} | ReadonlyArray)[]): (number | {})[]; }' is not assignable to type '{ (...items: ReadonlyArray[]): number[]; (...items: (number | ReadonlyArray)[]): number[]; }'. -!!! error TS2322: Type '(number | {})[]' is not assignable to type 'number[]'. -!!! error TS2322: Type 'number | {}' is not assignable to type 'number'. -!!! error TS2322: Type '{}' is not assignable to type 'number'. +!!! error TS2322: Types of property 'pop' are incompatible. +!!! error TS2322: Type '() => number | {}' is not assignable to type '() => number'. +!!! error TS2322: Type 'number | {}' is not assignable to type 'number'. +!!! error TS2322: Type '{}' is not assignable to type 'number'. a1 = a2; // Error ~~ !!! error TS2322: Type '[number, number]' is not assignable to type '[number, string]'. diff --git a/tests/baselines/reference/typeInferenceWithTupleType.errors.txt b/tests/baselines/reference/typeInferenceWithTupleType.errors.txt deleted file mode 100644 index 9fba99de278..00000000000 --- a/tests/baselines/reference/typeInferenceWithTupleType.errors.txt +++ /dev/null @@ -1,31 +0,0 @@ -tests/cases/conformance/types/tuple/typeInferenceWithTupleType.ts(16,9): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'never' has no compatible call signatures. - - -==== tests/cases/conformance/types/tuple/typeInferenceWithTupleType.ts (1 errors) ==== - function combine(x: T, y: U): [T, U] { - return [x, y]; - } - - var combineResult = combine("string", 10); - var combineEle1 = combineResult[0]; // string - var combineEle2 = combineResult[1]; // number - - function zip(array1: T[], array2: U[]): [[T, U]] { - if (array1.length != array2.length) { - return [[undefined, undefined]]; - } - var length = array1.length; - var zipResult: [[T, U]]; - for (var i = 0; i < length; ++i) { - zipResult.push([array1[i], array2[i]]); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'never' has no compatible call signatures. - } - return zipResult; - } - - var zipResult = zip(["foo", "bar"], [5, 6]); - var zipResultEle = zipResult[0]; // [string, number] - var zipResultEleEle = zipResult[0][0]; // string - - \ No newline at end of file diff --git a/tests/baselines/reference/typeInferenceWithTupleType.symbols b/tests/baselines/reference/typeInferenceWithTupleType.symbols index e28ea2571dd..6f3279db8c2 100644 --- a/tests/baselines/reference/typeInferenceWithTupleType.symbols +++ b/tests/baselines/reference/typeInferenceWithTupleType.symbols @@ -70,9 +70,9 @@ function zip(array1: T[], array2: U[]): [[T, U]] { >i : Symbol(i, Decl(typeInferenceWithTupleType.ts, 14, 12)) zipResult.push([array1[i], array2[i]]); ->zipResult.push : Symbol(TupleBase.push, Decl(lib.d.ts, --, --)) +>zipResult.push : Symbol(Array.push, Decl(lib.d.ts, --, --)) >zipResult : Symbol(zipResult, Decl(typeInferenceWithTupleType.ts, 13, 7)) ->push : Symbol(TupleBase.push, Decl(lib.d.ts, --, --)) +>push : Symbol(Array.push, Decl(lib.d.ts, --, --)) >array1 : Symbol(array1, Decl(typeInferenceWithTupleType.ts, 8, 19)) >i : Symbol(i, Decl(typeInferenceWithTupleType.ts, 14, 12)) >array2 : Symbol(array2, Decl(typeInferenceWithTupleType.ts, 8, 31)) diff --git a/tests/baselines/reference/typeInferenceWithTupleType.types b/tests/baselines/reference/typeInferenceWithTupleType.types index e546a127758..a7f8bff6798 100644 --- a/tests/baselines/reference/typeInferenceWithTupleType.types +++ b/tests/baselines/reference/typeInferenceWithTupleType.types @@ -82,11 +82,11 @@ function zip(array1: T[], array2: U[]): [[T, U]] { >i : number zipResult.push([array1[i], array2[i]]); ->zipResult.push([array1[i], array2[i]]) : any ->zipResult.push : never +>zipResult.push([array1[i], array2[i]]) : number +>zipResult.push : (...items: [T, U][]) => number >zipResult : [[T, U]] ->push : never ->[array1[i], array2[i]] : (T | U)[] +>push : (...items: [T, U][]) => number +>[array1[i], array2[i]] : [T, U] >array1[i] : T >array1 : T[] >i : number diff --git a/tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts b/tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts index ebd7738125e..85a035d472b 100644 --- a/tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts +++ b/tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts @@ -1,4 +1,4 @@ -interface StrNum extends TupleBase { +interface StrNum extends Array { 0: string; 1: number; length: 2; From bb79308a2446266a3bff299d569620613cbabec7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 8 Nov 2017 15:26:05 -0800 Subject: [PATCH 39/73] Use CRLF and emit test output for stdout/stderr I've got git problems and I'm not even on Windows! --- src/harness/externalCompileRunner.ts | 134 +++++++++++++-------------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/src/harness/externalCompileRunner.ts b/src/harness/externalCompileRunner.ts index 8ca0be807bf..9b8fc8c4fc5 100644 --- a/src/harness/externalCompileRunner.ts +++ b/src/harness/externalCompileRunner.ts @@ -1,67 +1,67 @@ -/// -/// -abstract class ExternalCompileRunnerBase extends RunnerBase { - abstract testDir: string; - public enumerateTestFiles() { - return Harness.IO.getDirectories(this.testDir); - } - /** Setup the runner's tests so that they are ready to be executed by the harness - * The first test should be a describe/it block that sets up the harness's compiler instance appropriately - */ - public initializeTests(): void { - // Read in and evaluate the test list - const testList = this.tests && this.tests.length ? this.tests : this.enumerateTestFiles(); - - describe(`${this.kind()} code samples`, () => { - for (const test of testList) { - this.runTest(test); - } - }); - } - private runTest(directoryName: string) { - describe(directoryName, () => { - const cp = require("child_process"); - const path = require("path"); - const fs = require("fs"); - - it("should build successfully", () => { - const cwd = path.join(__dirname, "../../", this.testDir, directoryName); - const timeout = 600000; // 600s = 10 minutes - if (fs.existsSync(path.join(cwd, "package.json"))) { - if (fs.existsSync(path.join(cwd, "package-lock.json"))) { - fs.unlinkSync(path.join(cwd, "package-lock.json")); - } - const stdio = isWorker ? "pipe" : "inherit"; - const install = cp.spawnSync(`npm`, ["i"], { cwd, timeout, shell: true, stdio }); - if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed!`); - } - Harness.Baseline.runBaseline(`${this.kind()}/${directoryName}.log`, () => { - const result = cp.spawnSync(`node`, [path.join(__dirname, "tsc.js")], { cwd, timeout, shell: true }); - // tslint:disable-next-line:no-null-keyword - return result.status === 0 ? null : `Exit Code: ${result.status} -Standard output: -${result.stdout.toString().replace(/\r\n/g, "\n")} - - -Standard error: -${result.stderr.toString().replace(/\r\n/g, "\n")}`; - }); - }); - }); - } -} - -class UserCodeRunner extends ExternalCompileRunnerBase { - public readonly testDir = "tests/cases/user/"; - public kind(): TestRunnerKind { - return "user"; - } -} - -class DefinitelyTypedRunner extends ExternalCompileRunnerBase { - public readonly testDir = "../DefinitelyTyped/types/"; - public workingDirectory = this.testDir; - public kind(): TestRunnerKind { - return "dt"; - } -} +/// +/// +abstract class ExternalCompileRunnerBase extends RunnerBase { + abstract testDir: string; + public enumerateTestFiles() { + return Harness.IO.getDirectories(this.testDir); + } + /** Setup the runner's tests so that they are ready to be executed by the harness + * The first test should be a describe/it block that sets up the harness's compiler instance appropriately + */ + public initializeTests(): void { + // Read in and evaluate the test list + const testList = this.tests && this.tests.length ? this.tests : this.enumerateTestFiles(); + + describe(`${this.kind()} code samples`, () => { + for (const test of testList) { + this.runTest(test); + } + }); + } + private runTest(directoryName: string) { + describe(directoryName, () => { + const cp = require("child_process"); + const path = require("path"); + const fs = require("fs"); + + it("should build successfully", () => { + const cwd = path.join(__dirname, "../../", this.testDir, directoryName); + const timeout = 600000; // 600s = 10 minutes + if (fs.existsSync(path.join(cwd, "package.json"))) { + if (fs.existsSync(path.join(cwd, "package-lock.json"))) { + fs.unlinkSync(path.join(cwd, "package-lock.json")); + } + const stdio = isWorker ? "pipe" : "inherit"; + const install = cp.spawnSync(`npm`, ["i"], { cwd, timeout, shell: true, stdio }); + if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed!`); + } + Harness.Baseline.runBaseline(`${this.kind()}/${directoryName}.log`, () => { + const result = cp.spawnSync(`node`, [path.join(__dirname, "tsc.js")], { cwd, timeout, shell: true }); + // tslint:disable-next-line:no-null-keyword + return result.status === 0 && !result.stdout.length && !result.stderr.length ? null : `Exit Code: ${result.status} +Standard output: +${result.stdout.toString().replace(/\r\n/g, "\n")} + + +Standard error: +${result.stderr.toString().replace(/\r\n/g, "\n")}`; + }); + }); + }); + } +} + +class UserCodeRunner extends ExternalCompileRunnerBase { + public readonly testDir = "tests/cases/user/"; + public kind(): TestRunnerKind { + return "user"; + } +} + +class DefinitelyTypedRunner extends ExternalCompileRunnerBase { + public readonly testDir = "../DefinitelyTyped/types/"; + public workingDirectory = this.testDir; + public kind(): TestRunnerKind { + return "dt"; + } +} From 1408a4d2b7604931687273169374f6a9d2c80c12 Mon Sep 17 00:00:00 2001 From: Adrian Leonhard Date: Thu, 9 Nov 2017 02:27:02 +0100 Subject: [PATCH 40/73] Add Symbol.species to ArrayConstructor, MapConstructor, SetConstructor, ArrayBufferConstructor. (#18652) Fix Symbol.species in RegExpConstructor and PromiseConstructor. See https://github.com/Microsoft/TypeScript/issues/2881 . --- src/lib/es2015.symbol.wellknown.d.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/lib/es2015.symbol.wellknown.d.ts b/src/lib/es2015.symbol.wellknown.d.ts index 268570ff232..23d836c6515 100644 --- a/src/lib/es2015.symbol.wellknown.d.ts +++ b/src/lib/es2015.symbol.wellknown.d.ts @@ -150,7 +150,7 @@ interface Promise { } interface PromiseConstructor { - readonly [Symbol.species]: Function; + readonly [Symbol.species]: PromiseConstructor; } interface RegExp { @@ -202,7 +202,7 @@ interface RegExp { } interface RegExpConstructor { - [Symbol.species](): RegExpConstructor; + readonly [Symbol.species]: RegExpConstructor; } interface String { @@ -283,3 +283,16 @@ interface Float32Array { interface Float64Array { readonly [Symbol.toStringTag]: "Float64Array"; } + +interface ArrayConstructor { + readonly [Symbol.species]: ArrayConstructor; +} +interface MapConstructor { + readonly [Symbol.species]: MapConstructor; +} +interface SetConstructor { + readonly [Symbol.species]: SetConstructor; +} +interface ArrayBufferConstructor { + readonly [Symbol.species]: ArrayBufferConstructor; +} \ No newline at end of file From e9841f3899ddba2052e5e68e68adfc9268afd891 Mon Sep 17 00:00:00 2001 From: "wenlu.wang" <805037171@163.com> Date: Wed, 8 Nov 2017 19:44:12 -0600 Subject: [PATCH 41/73] fix completions protected members in recursive generic types (#19192) (#19242) --- src/compiler/checker.ts | 7 +++---- ...ompletionsForRecursiveGenericTypesMember.ts | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 tests/cases/fourslash/completionsForRecursiveGenericTypesMember.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 38bc617c650..6f75bfa0d46 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15162,12 +15162,11 @@ namespace ts { if (flags & ModifierFlags.Static) { return true; } - // An instance property must be accessed through an instance of the enclosing class - if (type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType) { + if (type.flags & TypeFlags.TypeParameter) { // get the original type -- represented as the type constraint of the 'this' type - type = getConstraintOfTypeParameter(type); + type = (type as TypeParameter).isThisType ? getConstraintOfTypeParameter(type) : getBaseConstraintOfType(type); } - if (!(getObjectFlags(getTargetType(type)) & ObjectFlags.ClassOrInterface && hasBaseType(type, enclosingClass))) { + if (!type || !hasBaseType(type, enclosingClass)) { error(errorNode, Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass)); return false; } diff --git a/tests/cases/fourslash/completionsForRecursiveGenericTypesMember.ts b/tests/cases/fourslash/completionsForRecursiveGenericTypesMember.ts new file mode 100644 index 00000000000..993b9eb73ac --- /dev/null +++ b/tests/cases/fourslash/completionsForRecursiveGenericTypesMember.ts @@ -0,0 +1,18 @@ +/// + +//// export class TestBase> +//// { +//// public publicMethod(p: any): void {} +//// private privateMethod(p: any): void {} +//// protected protectedMethod(p: any): void {} +//// public test(t: T): void +//// { +//// t./**/ +//// } +//// } + +goTo.marker(); + +verify.completionListContains('publicMethod'); +verify.completionListContains('privateMethod'); +verify.completionListContains('protectedMethod'); From 235356e6ffb9d9ad365758ab46ee245ec6df08d3 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 8 Nov 2017 18:15:23 -0800 Subject: [PATCH 42/73] Handle synthetic nodes correctly as namespace identifiers in system transform (#19623) * Handle synthetic nodes correctly as namespace identifiers in system transform * Add ref to issue in comment * Lock newline for ci --- src/compiler/factory.ts | 2 +- src/harness/unittests/transform.ts | 32 +++++++++++++++++++ ...nsformsCorrectly.transformAddImportStar.js | 13 ++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/transformApi/transformsCorrectly.transformAddImportStar.js diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 6a56b6da049..e8dfcbc1e94 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -4319,7 +4319,7 @@ namespace ts { const namespaceDeclaration = getNamespaceDeclarationNode(node); if (namespaceDeclaration && !isDefaultImport(node)) { const name = namespaceDeclaration.name; - return isGeneratedIdentifier(name) ? name : createIdentifier(getSourceTextOfNodeFromSourceFile(sourceFile, namespaceDeclaration.name)); + return isGeneratedIdentifier(name) ? name : createIdentifier(getSourceTextOfNodeFromSourceFile(sourceFile, name) || idText(name)); } if (node.kind === SyntaxKind.ImportDeclaration && (node).importClause) { return getGeneratedNameForNode(node); diff --git a/src/harness/unittests/transform.ts b/src/harness/unittests/transform.ts index 72f7072535c..a39249bb225 100644 --- a/src/harness/unittests/transform.ts +++ b/src/harness/unittests/transform.ts @@ -192,6 +192,38 @@ namespace ts { }; } }); + + // https://github.com/Microsoft/TypeScript/issues/19618 + testBaseline("transformAddImportStar", () => { + return ts.transpileModule("", { + transformers: { + before: [transformAddImportStar], + }, + compilerOptions: { + target: ts.ScriptTarget.ES5, + module: ts.ModuleKind.System, + newLine: NewLineKind.CarriageReturnLineFeed, + } + }).outputText; + + function transformAddImportStar(_context: ts.TransformationContext) { + return (sourceFile: ts.SourceFile): ts.SourceFile => { + return visitNode(sourceFile); + }; + function visitNode(sf: ts.SourceFile) { + // produce `import * as i0 from './comp'; + const importStar = ts.createImportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*importClause*/ ts.createImportClause( + /*name*/ undefined, + ts.createNamespaceImport(ts.createIdentifier("i0")) + ), + /*moduleSpecifier*/ ts.createLiteral("./comp1")); + return ts.updateSourceFileNode(sf, [importStar]); + } + } + }); }); } diff --git a/tests/baselines/reference/transformApi/transformsCorrectly.transformAddImportStar.js b/tests/baselines/reference/transformApi/transformsCorrectly.transformAddImportStar.js new file mode 100644 index 00000000000..167e8eaee09 --- /dev/null +++ b/tests/baselines/reference/transformApi/transformsCorrectly.transformAddImportStar.js @@ -0,0 +1,13 @@ +System.register(["./comp1"], function (exports_1, context_1) { + var __moduleName = context_1 && context_1.id; + var i0; + return { + setters: [ + function (i0_1) { + i0 = i0_1; + } + ], + execute: function () { + } + }; +}); From bfe74de0176f7eaabaf09674f5fcb9cb7248226e Mon Sep 17 00:00:00 2001 From: Yuval Greenfield Date: Wed, 8 Nov 2017 18:20:58 -0800 Subject: [PATCH 43/73] Only ignored params need underscores --- src/compiler/comments.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index bb8ec9bf3e7..1fec1e9562f 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -260,7 +260,7 @@ namespace ts { } } - function emitLeadingComment(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) { + function emitLeadingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) { if (!hasWrittenComment) { emitNewLineBeforeLeadingCommentOfPosition(currentLineMap, writer, rangePos, commentPos); hasWrittenComment = true; @@ -274,7 +274,7 @@ namespace ts { if (hasTrailingNewLine) { writer.writeLine(); } - else if (_kind === SyntaxKind.MultiLineCommentTrivia) { + else if (kind === SyntaxKind.MultiLineCommentTrivia) { writer.write(" "); } } From ceaeffa3ab2024aa4a8ff11a7a5d6826d1bd2bf3 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 8 Nov 2017 18:44:46 -0800 Subject: [PATCH 44/73] Fix declaration emit for imported export alias specifiers (#19852) * Badness * Revert #3641, whose original bug has been fixed by other means * Add another repro --- src/compiler/checker.ts | 1 - .../declarationEmitOfTypeofAliasedExport.js | 35 +++++++++ ...clarationEmitOfTypeofAliasedExport.symbols | 17 +++++ ...declarationEmitOfTypeofAliasedExport.types | 17 +++++ ...s6ExportClauseWithoutModuleSpecifier.types | 4 +- ...ortClauseWithoutModuleSpecifierInEs5.types | 4 +- .../exportSpecifierForAGlobal.errors.txt | 5 +- .../reference/exportSpecifierForAGlobal.js | 5 -- .../reference/exportsAndImports3-amd.symbols | 12 ++-- .../reference/exportsAndImports3-es6.symbols | 12 ++-- .../reference/exportsAndImports3.symbols | 12 ++-- .../reexportWrittenCorrectlyInDeclaration.js | 72 +++++++++++++++++++ ...xportWrittenCorrectlyInDeclaration.symbols | 29 ++++++++ ...eexportWrittenCorrectlyInDeclaration.types | 30 ++++++++ .../baselines/reference/systemModule15.types | 4 +- .../declarationEmitOfTypeofAliasedExport.ts | 8 +++ .../reexportWrittenCorrectlyInDeclaration.ts | 18 +++++ 17 files changed, 254 insertions(+), 31 deletions(-) create mode 100644 tests/baselines/reference/declarationEmitOfTypeofAliasedExport.js create mode 100644 tests/baselines/reference/declarationEmitOfTypeofAliasedExport.symbols create mode 100644 tests/baselines/reference/declarationEmitOfTypeofAliasedExport.types create mode 100644 tests/baselines/reference/reexportWrittenCorrectlyInDeclaration.js create mode 100644 tests/baselines/reference/reexportWrittenCorrectlyInDeclaration.symbols create mode 100644 tests/baselines/reference/reexportWrittenCorrectlyInDeclaration.types create mode 100644 tests/cases/compiler/declarationEmitOfTypeofAliasedExport.ts create mode 100644 tests/cases/compiler/reexportWrittenCorrectlyInDeclaration.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6f75bfa0d46..f619805628a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2161,7 +2161,6 @@ namespace ts { return forEachEntry(symbols, symbolFromSymbolTable => { if (symbolFromSymbolTable.flags & SymbolFlags.Alias && symbolFromSymbolTable.escapedName !== "export=" - && !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier) && !(isUMDExportSymbol(symbolFromSymbolTable) && enclosingDeclaration && isExternalModule(getSourceFileOfNode(enclosingDeclaration))) // If `!useOnlyExternalAliasing`, we can use any type of alias to get the name && (!useOnlyExternalAliasing || some(symbolFromSymbolTable.declarations, isExternalModuleImportEqualsDeclaration))) { diff --git a/tests/baselines/reference/declarationEmitOfTypeofAliasedExport.js b/tests/baselines/reference/declarationEmitOfTypeofAliasedExport.js new file mode 100644 index 00000000000..5f1f5743201 --- /dev/null +++ b/tests/baselines/reference/declarationEmitOfTypeofAliasedExport.js @@ -0,0 +1,35 @@ +//// [tests/cases/compiler/declarationEmitOfTypeofAliasedExport.ts] //// + +//// [a.ts] +class C {} +export { C as D } + +//// [b.ts] +import * as a from "./a"; +export default a.D; + + +//// [a.js] +"use strict"; +exports.__esModule = true; +var C = /** @class */ (function () { + function C() { + } + return C; +}()); +exports.D = C; +//// [b.js] +"use strict"; +exports.__esModule = true; +var a = require("./a"); +exports["default"] = a.D; + + +//// [a.d.ts] +declare class C { +} +export { C as D }; +//// [b.d.ts] +import * as a from "./a"; +declare const _default: typeof a.D; +export default _default; diff --git a/tests/baselines/reference/declarationEmitOfTypeofAliasedExport.symbols b/tests/baselines/reference/declarationEmitOfTypeofAliasedExport.symbols new file mode 100644 index 00000000000..d13d242105b --- /dev/null +++ b/tests/baselines/reference/declarationEmitOfTypeofAliasedExport.symbols @@ -0,0 +1,17 @@ +=== /a.ts === +class C {} +>C : Symbol(C, Decl(a.ts, 0, 0)) + +export { C as D } +>C : Symbol(D, Decl(a.ts, 1, 8)) +>D : Symbol(D, Decl(a.ts, 1, 8)) + +=== /b.ts === +import * as a from "./a"; +>a : Symbol(a, Decl(b.ts, 0, 6)) + +export default a.D; +>a.D : Symbol(a.D, Decl(a.ts, 1, 8)) +>a : Symbol(a, Decl(b.ts, 0, 6)) +>D : Symbol(a.D, Decl(a.ts, 1, 8)) + diff --git a/tests/baselines/reference/declarationEmitOfTypeofAliasedExport.types b/tests/baselines/reference/declarationEmitOfTypeofAliasedExport.types new file mode 100644 index 00000000000..ccd13107166 --- /dev/null +++ b/tests/baselines/reference/declarationEmitOfTypeofAliasedExport.types @@ -0,0 +1,17 @@ +=== /a.ts === +class C {} +>C : C + +export { C as D } +>C : typeof C +>D : typeof C + +=== /b.ts === +import * as a from "./a"; +>a : typeof a + +export default a.D; +>a.D : typeof a.D +>a : typeof a +>D : typeof a.D + diff --git a/tests/baselines/reference/es6ExportClauseWithoutModuleSpecifier.types b/tests/baselines/reference/es6ExportClauseWithoutModuleSpecifier.types index abb1c3b69e2..acbe40fb9ab 100644 --- a/tests/baselines/reference/es6ExportClauseWithoutModuleSpecifier.types +++ b/tests/baselines/reference/es6ExportClauseWithoutModuleSpecifier.types @@ -30,8 +30,8 @@ export { c as c2 } from "server"; export { i, m as instantiatedModule } from "server"; >i : any ->m : typeof m ->instantiatedModule : typeof m +>m : typeof instantiatedModule +>instantiatedModule : typeof instantiatedModule export { uninstantiated } from "server"; >uninstantiated : any diff --git a/tests/baselines/reference/es6ExportClauseWithoutModuleSpecifierInEs5.types b/tests/baselines/reference/es6ExportClauseWithoutModuleSpecifierInEs5.types index b407d9b16f5..8a7e9c29b10 100644 --- a/tests/baselines/reference/es6ExportClauseWithoutModuleSpecifierInEs5.types +++ b/tests/baselines/reference/es6ExportClauseWithoutModuleSpecifierInEs5.types @@ -30,8 +30,8 @@ export { c as c2 } from "./server"; export { i, m as instantiatedModule } from "./server"; >i : any ->m : typeof m ->instantiatedModule : typeof m +>m : typeof instantiatedModule +>instantiatedModule : typeof instantiatedModule export { uninstantiated } from "./server"; >uninstantiated : any diff --git a/tests/baselines/reference/exportSpecifierForAGlobal.errors.txt b/tests/baselines/reference/exportSpecifierForAGlobal.errors.txt index d2f103a91fa..20a1c9a7d41 100644 --- a/tests/baselines/reference/exportSpecifierForAGlobal.errors.txt +++ b/tests/baselines/reference/exportSpecifierForAGlobal.errors.txt @@ -1,14 +1,17 @@ tests/cases/compiler/b.ts(1,9): error TS2661: Cannot export 'X'. Only local declarations can be exported from a module. +tests/cases/compiler/b.ts(2,17): error TS4060: Return type of exported function has or is using private name 'X'. ==== tests/cases/compiler/a.d.ts (0 errors) ==== declare class X { } -==== tests/cases/compiler/b.ts (1 errors) ==== +==== tests/cases/compiler/b.ts (2 errors) ==== export {X}; ~ !!! error TS2661: Cannot export 'X'. Only local declarations can be exported from a module. export function f() { + ~ +!!! error TS4060: Return type of exported function has or is using private name 'X'. var x: X; return x; } diff --git a/tests/baselines/reference/exportSpecifierForAGlobal.js b/tests/baselines/reference/exportSpecifierForAGlobal.js index 6023b7c7f14..9f12241cbd1 100644 --- a/tests/baselines/reference/exportSpecifierForAGlobal.js +++ b/tests/baselines/reference/exportSpecifierForAGlobal.js @@ -19,8 +19,3 @@ function f() { return x; } exports.f = f; - - -//// [b.d.ts] -export { X }; -export declare function f(): X; diff --git a/tests/baselines/reference/exportsAndImports3-amd.symbols b/tests/baselines/reference/exportsAndImports3-amd.symbols index f71014281c2..edc5d5c2e4e 100644 --- a/tests/baselines/reference/exportsAndImports3-amd.symbols +++ b/tests/baselines/reference/exportsAndImports3-amd.symbols @@ -15,17 +15,17 @@ export enum E { >E : Symbol(E, Decl(t1.ts, 5, 1)) A, B, C ->A : Symbol(E.A, Decl(t1.ts, 6, 15)) ->B : Symbol(E.B, Decl(t1.ts, 7, 6)) ->C : Symbol(E.C, Decl(t1.ts, 7, 9)) +>A : Symbol(E1.A, Decl(t1.ts, 6, 15)) +>B : Symbol(E1.B, Decl(t1.ts, 7, 6)) +>C : Symbol(E1.C, Decl(t1.ts, 7, 9)) } export const enum D { >D : Symbol(D, Decl(t1.ts, 8, 1)) A, B, C ->A : Symbol(D.A, Decl(t1.ts, 9, 21)) ->B : Symbol(D.B, Decl(t1.ts, 10, 6)) ->C : Symbol(D.C, Decl(t1.ts, 10, 9)) +>A : Symbol(D1.A, Decl(t1.ts, 9, 21)) +>B : Symbol(D1.B, Decl(t1.ts, 10, 6)) +>C : Symbol(D1.C, Decl(t1.ts, 10, 9)) } export module M { >M : Symbol(M, Decl(t1.ts, 11, 1)) diff --git a/tests/baselines/reference/exportsAndImports3-es6.symbols b/tests/baselines/reference/exportsAndImports3-es6.symbols index f71014281c2..edc5d5c2e4e 100644 --- a/tests/baselines/reference/exportsAndImports3-es6.symbols +++ b/tests/baselines/reference/exportsAndImports3-es6.symbols @@ -15,17 +15,17 @@ export enum E { >E : Symbol(E, Decl(t1.ts, 5, 1)) A, B, C ->A : Symbol(E.A, Decl(t1.ts, 6, 15)) ->B : Symbol(E.B, Decl(t1.ts, 7, 6)) ->C : Symbol(E.C, Decl(t1.ts, 7, 9)) +>A : Symbol(E1.A, Decl(t1.ts, 6, 15)) +>B : Symbol(E1.B, Decl(t1.ts, 7, 6)) +>C : Symbol(E1.C, Decl(t1.ts, 7, 9)) } export const enum D { >D : Symbol(D, Decl(t1.ts, 8, 1)) A, B, C ->A : Symbol(D.A, Decl(t1.ts, 9, 21)) ->B : Symbol(D.B, Decl(t1.ts, 10, 6)) ->C : Symbol(D.C, Decl(t1.ts, 10, 9)) +>A : Symbol(D1.A, Decl(t1.ts, 9, 21)) +>B : Symbol(D1.B, Decl(t1.ts, 10, 6)) +>C : Symbol(D1.C, Decl(t1.ts, 10, 9)) } export module M { >M : Symbol(M, Decl(t1.ts, 11, 1)) diff --git a/tests/baselines/reference/exportsAndImports3.symbols b/tests/baselines/reference/exportsAndImports3.symbols index f71014281c2..edc5d5c2e4e 100644 --- a/tests/baselines/reference/exportsAndImports3.symbols +++ b/tests/baselines/reference/exportsAndImports3.symbols @@ -15,17 +15,17 @@ export enum E { >E : Symbol(E, Decl(t1.ts, 5, 1)) A, B, C ->A : Symbol(E.A, Decl(t1.ts, 6, 15)) ->B : Symbol(E.B, Decl(t1.ts, 7, 6)) ->C : Symbol(E.C, Decl(t1.ts, 7, 9)) +>A : Symbol(E1.A, Decl(t1.ts, 6, 15)) +>B : Symbol(E1.B, Decl(t1.ts, 7, 6)) +>C : Symbol(E1.C, Decl(t1.ts, 7, 9)) } export const enum D { >D : Symbol(D, Decl(t1.ts, 8, 1)) A, B, C ->A : Symbol(D.A, Decl(t1.ts, 9, 21)) ->B : Symbol(D.B, Decl(t1.ts, 10, 6)) ->C : Symbol(D.C, Decl(t1.ts, 10, 9)) +>A : Symbol(D1.A, Decl(t1.ts, 9, 21)) +>B : Symbol(D1.B, Decl(t1.ts, 10, 6)) +>C : Symbol(D1.C, Decl(t1.ts, 10, 9)) } export module M { >M : Symbol(M, Decl(t1.ts, 11, 1)) diff --git a/tests/baselines/reference/reexportWrittenCorrectlyInDeclaration.js b/tests/baselines/reference/reexportWrittenCorrectlyInDeclaration.js new file mode 100644 index 00000000000..ae3ce21ff49 --- /dev/null +++ b/tests/baselines/reference/reexportWrittenCorrectlyInDeclaration.js @@ -0,0 +1,72 @@ +//// [tests/cases/compiler/reexportWrittenCorrectlyInDeclaration.ts] //// + +//// [ThingA.ts] +// https://github.com/Microsoft/TypeScript/issues/8612 +export class ThingA { } + +//// [ThingB.ts] +export class ThingB { } + +//// [Things.ts] +export {ThingA} from "./ThingA"; +export {ThingB} from "./ThingB"; + +//// [Test.ts] +import * as things from "./Things"; + +export class Test { + public method = (input: things.ThingA) => { }; +} + +//// [ThingA.js] +"use strict"; +exports.__esModule = true; +// https://github.com/Microsoft/TypeScript/issues/8612 +var ThingA = /** @class */ (function () { + function ThingA() { + } + return ThingA; +}()); +exports.ThingA = ThingA; +//// [ThingB.js] +"use strict"; +exports.__esModule = true; +var ThingB = /** @class */ (function () { + function ThingB() { + } + return ThingB; +}()); +exports.ThingB = ThingB; +//// [Things.js] +"use strict"; +exports.__esModule = true; +var ThingA_1 = require("./ThingA"); +exports.ThingA = ThingA_1.ThingA; +var ThingB_1 = require("./ThingB"); +exports.ThingB = ThingB_1.ThingB; +//// [Test.js] +"use strict"; +exports.__esModule = true; +var Test = /** @class */ (function () { + function Test() { + this.method = function (input) { }; + } + return Test; +}()); +exports.Test = Test; + + +//// [ThingA.d.ts] +export declare class ThingA { +} +//// [ThingB.d.ts] +export declare class ThingB { +} +//// [Things.d.ts] +export { ThingA } from "./ThingA"; +export { ThingB } from "./ThingB"; +//// [Test.d.ts] +import * as things from "./Things"; +export declare class Test { + method: (input: things.ThingA) => void; +} diff --git a/tests/baselines/reference/reexportWrittenCorrectlyInDeclaration.symbols b/tests/baselines/reference/reexportWrittenCorrectlyInDeclaration.symbols new file mode 100644 index 00000000000..347ff41cc71 --- /dev/null +++ b/tests/baselines/reference/reexportWrittenCorrectlyInDeclaration.symbols @@ -0,0 +1,29 @@ +=== tests/cases/compiler/ThingA.ts === +// https://github.com/Microsoft/TypeScript/issues/8612 +export class ThingA { } +>ThingA : Symbol(ThingA, Decl(ThingA.ts, 0, 0)) + +=== tests/cases/compiler/ThingB.ts === +export class ThingB { } +>ThingB : Symbol(ThingB, Decl(ThingB.ts, 0, 0)) + +=== tests/cases/compiler/Things.ts === +export {ThingA} from "./ThingA"; +>ThingA : Symbol(ThingA, Decl(Things.ts, 0, 8)) + +export {ThingB} from "./ThingB"; +>ThingB : Symbol(ThingB, Decl(Things.ts, 1, 8)) + +=== tests/cases/compiler/Test.ts === +import * as things from "./Things"; +>things : Symbol(things, Decl(Test.ts, 0, 6)) + +export class Test { +>Test : Symbol(Test, Decl(Test.ts, 0, 35)) + + public method = (input: things.ThingA) => { }; +>method : Symbol(Test.method, Decl(Test.ts, 2, 19)) +>input : Symbol(input, Decl(Test.ts, 3, 21)) +>things : Symbol(things, Decl(Test.ts, 0, 6)) +>ThingA : Symbol(things.ThingA, Decl(Things.ts, 0, 8)) +} diff --git a/tests/baselines/reference/reexportWrittenCorrectlyInDeclaration.types b/tests/baselines/reference/reexportWrittenCorrectlyInDeclaration.types new file mode 100644 index 00000000000..515ad0f5ac9 --- /dev/null +++ b/tests/baselines/reference/reexportWrittenCorrectlyInDeclaration.types @@ -0,0 +1,30 @@ +=== tests/cases/compiler/ThingA.ts === +// https://github.com/Microsoft/TypeScript/issues/8612 +export class ThingA { } +>ThingA : ThingA + +=== tests/cases/compiler/ThingB.ts === +export class ThingB { } +>ThingB : ThingB + +=== tests/cases/compiler/Things.ts === +export {ThingA} from "./ThingA"; +>ThingA : typeof ThingA + +export {ThingB} from "./ThingB"; +>ThingB : typeof ThingB + +=== tests/cases/compiler/Test.ts === +import * as things from "./Things"; +>things : typeof things + +export class Test { +>Test : Test + + public method = (input: things.ThingA) => { }; +>method : (input: things.ThingA) => void +>(input: things.ThingA) => { } : (input: things.ThingA) => void +>input : things.ThingA +>things : any +>ThingA : things.ThingA +} diff --git a/tests/baselines/reference/systemModule15.types b/tests/baselines/reference/systemModule15.types index 747583323ad..ac24678e568 100644 --- a/tests/baselines/reference/systemModule15.types +++ b/tests/baselines/reference/systemModule15.types @@ -23,9 +23,9 @@ use(moduleB.moduleC); use(moduleB.moduleCStar); >use(moduleB.moduleCStar) : void >use : (v: any) => void ->moduleB.moduleCStar : typeof "tests/cases/compiler/file3" +>moduleB.moduleCStar : typeof moduleB.moduleCStar >moduleB : typeof moduleB ->moduleCStar : typeof "tests/cases/compiler/file3" +>moduleCStar : typeof moduleB.moduleCStar === tests/cases/compiler/file2.ts === import * as moduleCStar from "./file3" diff --git a/tests/cases/compiler/declarationEmitOfTypeofAliasedExport.ts b/tests/cases/compiler/declarationEmitOfTypeofAliasedExport.ts new file mode 100644 index 00000000000..ab2912a0f1c --- /dev/null +++ b/tests/cases/compiler/declarationEmitOfTypeofAliasedExport.ts @@ -0,0 +1,8 @@ +// @declaration: true +// @filename: /a.ts +class C {} +export { C as D } + +// @filename: /b.ts +import * as a from "./a"; +export default a.D; diff --git a/tests/cases/compiler/reexportWrittenCorrectlyInDeclaration.ts b/tests/cases/compiler/reexportWrittenCorrectlyInDeclaration.ts new file mode 100644 index 00000000000..71947ca80c1 --- /dev/null +++ b/tests/cases/compiler/reexportWrittenCorrectlyInDeclaration.ts @@ -0,0 +1,18 @@ +// https://github.com/Microsoft/TypeScript/issues/8612 +// @declaration: true +// @filename: ThingA.ts +export class ThingA { } + +// @filename: ThingB.ts +export class ThingB { } + +// @filename: Things.ts +export {ThingA} from "./ThingA"; +export {ThingB} from "./ThingB"; + +// @filename: Test.ts +import * as things from "./Things"; + +export class Test { + public method = (input: things.ThingA) => { }; +} \ No newline at end of file From a1014b2b13f6662205876046e1c2c01d9d3367ed Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 9 Nov 2017 00:26:33 -0800 Subject: [PATCH 45/73] Mark all parameters as needed for metadata when one is decorated (#19849) * Mark all properties as needed for metadata when one is decorated * Add restarg test --- src/compiler/checker.ts | 4 + .../decoratorReferenceOnOtherProperty.js | 109 ++++++++++++++++++ .../decoratorReferenceOnOtherProperty.symbols | 46 ++++++++ .../decoratorReferenceOnOtherProperty.types | 46 ++++++++ .../decoratorReferenceOnOtherProperty.ts | 25 ++++ 5 files changed, 230 insertions(+) create mode 100644 tests/baselines/reference/decoratorReferenceOnOtherProperty.js create mode 100644 tests/baselines/reference/decoratorReferenceOnOtherProperty.symbols create mode 100644 tests/baselines/reference/decoratorReferenceOnOtherProperty.types create mode 100644 tests/cases/compiler/decoratorReferenceOnOtherProperty.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f619805628a..a9aaa77fa74 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20262,6 +20262,10 @@ namespace ts { case SyntaxKind.Parameter: markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(node)); + const containingSignature = (node as ParameterDeclaration).parent; + for (const parameter of containingSignature.parameters) { + markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter)); + } break; } } diff --git a/tests/baselines/reference/decoratorReferenceOnOtherProperty.js b/tests/baselines/reference/decoratorReferenceOnOtherProperty.js new file mode 100644 index 00000000000..6313f339ba9 --- /dev/null +++ b/tests/baselines/reference/decoratorReferenceOnOtherProperty.js @@ -0,0 +1,109 @@ +//// [tests/cases/compiler/decoratorReferenceOnOtherProperty.ts] //// + +//// [yoha.ts] +// https://github.com/Microsoft/TypeScript/issues/19799 +export class Yoha {} + +//// [index.ts] +import {Yoha} from './yoha'; + +function foo(...args: any[]) {} + +class Bar { + yoha(@foo yoha, bar: Yoha) {} + // ^^^^ +} + +//// [index2.ts] +import {Yoha} from './yoha'; + +function foo(...args: any[]) {} + +class Bar { + yoha(@foo yoha, ...bar: Yoha[]) {} + // ^^^^ +} + +//// [yoha.js] +"use strict"; +exports.__esModule = true; +// https://github.com/Microsoft/TypeScript/issues/19799 +var Yoha = /** @class */ (function () { + function Yoha() { + } + return Yoha; +}()); +exports.Yoha = Yoha; +//// [index.js] +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +exports.__esModule = true; +var yoha_1 = require("./yoha"); +function foo() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } +} +var Bar = /** @class */ (function () { + function Bar() { + } + Bar.prototype.yoha = function (yoha, bar) { }; + __decorate([ + __param(0, foo), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, yoha_1.Yoha]), + __metadata("design:returntype", void 0) + ], Bar.prototype, "yoha"); + return Bar; +}()); +//// [index2.js] +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +exports.__esModule = true; +var yoha_1 = require("./yoha"); +function foo() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } +} +var Bar = /** @class */ (function () { + function Bar() { + } + Bar.prototype.yoha = function (yoha) { + var bar = []; + for (var _i = 1; _i < arguments.length; _i++) { + bar[_i - 1] = arguments[_i]; + } + }; + __decorate([ + __param(0, foo), + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object, yoha_1.Yoha]), + __metadata("design:returntype", void 0) + ], Bar.prototype, "yoha"); + return Bar; +}()); diff --git a/tests/baselines/reference/decoratorReferenceOnOtherProperty.symbols b/tests/baselines/reference/decoratorReferenceOnOtherProperty.symbols new file mode 100644 index 00000000000..619e2afe4e9 --- /dev/null +++ b/tests/baselines/reference/decoratorReferenceOnOtherProperty.symbols @@ -0,0 +1,46 @@ +=== tests/cases/compiler/yoha.ts === +// https://github.com/Microsoft/TypeScript/issues/19799 +export class Yoha {} +>Yoha : Symbol(Yoha, Decl(yoha.ts, 0, 0)) + +=== tests/cases/compiler/index.ts === +import {Yoha} from './yoha'; +>Yoha : Symbol(Yoha, Decl(index.ts, 0, 8)) + +function foo(...args: any[]) {} +>foo : Symbol(foo, Decl(index.ts, 0, 28)) +>args : Symbol(args, Decl(index.ts, 2, 13)) + +class Bar { +>Bar : Symbol(Bar, Decl(index.ts, 2, 31)) + + yoha(@foo yoha, bar: Yoha) {} +>yoha : Symbol(Bar.yoha, Decl(index.ts, 4, 11)) +>foo : Symbol(foo, Decl(index.ts, 0, 28)) +>yoha : Symbol(yoha, Decl(index.ts, 5, 7)) +>bar : Symbol(bar, Decl(index.ts, 5, 17)) +>Yoha : Symbol(Yoha, Decl(index.ts, 0, 8)) + + // ^^^^ +} + +=== tests/cases/compiler/index2.ts === +import {Yoha} from './yoha'; +>Yoha : Symbol(Yoha, Decl(index2.ts, 0, 8)) + +function foo(...args: any[]) {} +>foo : Symbol(foo, Decl(index2.ts, 0, 28)) +>args : Symbol(args, Decl(index2.ts, 2, 13)) + +class Bar { +>Bar : Symbol(Bar, Decl(index2.ts, 2, 31)) + + yoha(@foo yoha, ...bar: Yoha[]) {} +>yoha : Symbol(Bar.yoha, Decl(index2.ts, 4, 11)) +>foo : Symbol(foo, Decl(index2.ts, 0, 28)) +>yoha : Symbol(yoha, Decl(index2.ts, 5, 7)) +>bar : Symbol(bar, Decl(index2.ts, 5, 17)) +>Yoha : Symbol(Yoha, Decl(index2.ts, 0, 8)) + + // ^^^^ +} diff --git a/tests/baselines/reference/decoratorReferenceOnOtherProperty.types b/tests/baselines/reference/decoratorReferenceOnOtherProperty.types new file mode 100644 index 00000000000..5994657aa31 --- /dev/null +++ b/tests/baselines/reference/decoratorReferenceOnOtherProperty.types @@ -0,0 +1,46 @@ +=== tests/cases/compiler/yoha.ts === +// https://github.com/Microsoft/TypeScript/issues/19799 +export class Yoha {} +>Yoha : Yoha + +=== tests/cases/compiler/index.ts === +import {Yoha} from './yoha'; +>Yoha : typeof Yoha + +function foo(...args: any[]) {} +>foo : (...args: any[]) => void +>args : any[] + +class Bar { +>Bar : Bar + + yoha(@foo yoha, bar: Yoha) {} +>yoha : (yoha: any, bar: Yoha) => void +>foo : (...args: any[]) => void +>yoha : any +>bar : Yoha +>Yoha : Yoha + + // ^^^^ +} + +=== tests/cases/compiler/index2.ts === +import {Yoha} from './yoha'; +>Yoha : typeof Yoha + +function foo(...args: any[]) {} +>foo : (...args: any[]) => void +>args : any[] + +class Bar { +>Bar : Bar + + yoha(@foo yoha, ...bar: Yoha[]) {} +>yoha : (yoha: any, ...bar: Yoha[]) => void +>foo : (...args: any[]) => void +>yoha : any +>bar : Yoha[] +>Yoha : Yoha + + // ^^^^ +} diff --git a/tests/cases/compiler/decoratorReferenceOnOtherProperty.ts b/tests/cases/compiler/decoratorReferenceOnOtherProperty.ts new file mode 100644 index 00000000000..c7465471ed8 --- /dev/null +++ b/tests/cases/compiler/decoratorReferenceOnOtherProperty.ts @@ -0,0 +1,25 @@ +// https://github.com/Microsoft/TypeScript/issues/19799 +// @experimentalDecorators: true +// @emitDecoratorMetadata: true +// @filename: yoha.ts +export class Yoha {} + +// @filename: index.ts +import {Yoha} from './yoha'; + +function foo(...args: any[]) {} + +class Bar { + yoha(@foo yoha, bar: Yoha) {} + // ^^^^ +} + +// @filename: index2.ts +import {Yoha} from './yoha'; + +function foo(...args: any[]) {} + +class Bar { + yoha(@foo yoha, ...bar: Yoha[]) {} + // ^^^^ +} \ No newline at end of file From 90ae9ffe6ed92ab9d3478cc620e5752c658cf121 Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 9 Nov 2017 12:21:37 -0800 Subject: [PATCH 46/73] If there is an `export default x;` alias declaration, disallow other default exports (#19872) --- src/compiler/binder.ts | 9 ++++----- src/compiler/types.ts | 4 ++++ ...exportDefaultAlias_excludesEverything.errors.txt | 13 +++++++++++++ .../exportDefaultAlias_excludesEverything.js | 9 +++++++++ .../exportDefaultAlias_excludesEverything.symbols | 10 ++++++++++ .../exportDefaultAlias_excludesEverything.types | 10 ++++++++++ .../exportDefaultAlias_excludesEverything.ts | 3 +++ 7 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/exportDefaultAlias_excludesEverything.errors.txt create mode 100644 tests/baselines/reference/exportDefaultAlias_excludesEverything.js create mode 100644 tests/baselines/reference/exportDefaultAlias_excludesEverything.symbols create mode 100644 tests/baselines/reference/exportDefaultAlias_excludesEverything.types create mode 100644 tests/cases/compiler/exportDefaultAlias_excludesEverything.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index cf8b3eefde8..4e89abde780 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2205,15 +2205,14 @@ namespace ts { bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node)); } else { - // An export default clause with an expression exports a value - // We want to exclude both class and function here, this is necessary to issue an error when there are both - // default export-assignment and default export function and class declaration. - const flags = node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node) + const flags = node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node) // An export default clause with an EntityNameExpression exports all meanings of that identifier ? SymbolFlags.Alias // An export default clause with any other expression exports a value : SymbolFlags.Property; - declareSymbol(container.symbol.exports, container.symbol, node, flags, SymbolFlags.Property | SymbolFlags.AliasExcludes | SymbolFlags.Class | SymbolFlags.Function); + // If there is an `export default x;` alias declaration, can't `export default` anything else. + // (In contrast, you can still have `export default function f() {}` and `export default interface I {}`.) + declareSymbol(container.symbol.exports, container.symbol, node, flags, SymbolFlags.All); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 1874821727c..d2107572ab4 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3021,6 +3021,10 @@ namespace ts { Optional = 1 << 24, // Optional property Transient = 1 << 25, // Transient symbol (created during type check) + /* @internal */ + All = FunctionScopedVariable | BlockScopedVariable | Property | EnumMember | Function | Class | Interface | ConstEnum | RegularEnum | ValueModule | NamespaceModule | TypeLiteral + | ObjectLiteral | Method | Constructor | GetAccessor | SetAccessor | Signature | TypeParameter | TypeAlias | ExportValue | Alias | Prototype | ExportStar | Optional | Transient, + Enum = RegularEnum | ConstEnum, Variable = FunctionScopedVariable | BlockScopedVariable, Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor, diff --git a/tests/baselines/reference/exportDefaultAlias_excludesEverything.errors.txt b/tests/baselines/reference/exportDefaultAlias_excludesEverything.errors.txt new file mode 100644 index 00000000000..9181278db20 --- /dev/null +++ b/tests/baselines/reference/exportDefaultAlias_excludesEverything.errors.txt @@ -0,0 +1,13 @@ +tests/cases/compiler/exportDefaultAlias_excludesEverything.ts(1,26): error TS2528: A module cannot have multiple default exports. +tests/cases/compiler/exportDefaultAlias_excludesEverything.ts(3,16): error TS2528: A module cannot have multiple default exports. + + +==== tests/cases/compiler/exportDefaultAlias_excludesEverything.ts (2 errors) ==== + export default interface A {} + ~ +!!! error TS2528: A module cannot have multiple default exports. + interface B {} + export default B; + ~ +!!! error TS2528: A module cannot have multiple default exports. + \ No newline at end of file diff --git a/tests/baselines/reference/exportDefaultAlias_excludesEverything.js b/tests/baselines/reference/exportDefaultAlias_excludesEverything.js new file mode 100644 index 00000000000..27f75954c14 --- /dev/null +++ b/tests/baselines/reference/exportDefaultAlias_excludesEverything.js @@ -0,0 +1,9 @@ +//// [exportDefaultAlias_excludesEverything.ts] +export default interface A {} +interface B {} +export default B; + + +//// [exportDefaultAlias_excludesEverything.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/exportDefaultAlias_excludesEverything.symbols b/tests/baselines/reference/exportDefaultAlias_excludesEverything.symbols new file mode 100644 index 00000000000..73b403e0da1 --- /dev/null +++ b/tests/baselines/reference/exportDefaultAlias_excludesEverything.symbols @@ -0,0 +1,10 @@ +=== tests/cases/compiler/exportDefaultAlias_excludesEverything.ts === +export default interface A {} +>A : Symbol(A, Decl(exportDefaultAlias_excludesEverything.ts, 0, 0)) + +interface B {} +>B : Symbol(B, Decl(exportDefaultAlias_excludesEverything.ts, 0, 29)) + +export default B; +>B : Symbol(B, Decl(exportDefaultAlias_excludesEverything.ts, 0, 29)) + diff --git a/tests/baselines/reference/exportDefaultAlias_excludesEverything.types b/tests/baselines/reference/exportDefaultAlias_excludesEverything.types new file mode 100644 index 00000000000..cd9dd06f817 --- /dev/null +++ b/tests/baselines/reference/exportDefaultAlias_excludesEverything.types @@ -0,0 +1,10 @@ +=== tests/cases/compiler/exportDefaultAlias_excludesEverything.ts === +export default interface A {} +>A : A + +interface B {} +>B : B + +export default B; +>B : B + diff --git a/tests/cases/compiler/exportDefaultAlias_excludesEverything.ts b/tests/cases/compiler/exportDefaultAlias_excludesEverything.ts new file mode 100644 index 00000000000..eea8cb1e698 --- /dev/null +++ b/tests/cases/compiler/exportDefaultAlias_excludesEverything.ts @@ -0,0 +1,3 @@ +export default interface A {} +interface B {} +export default B; From ddd8c95c63766d2eb321404213bb7a999193aef8 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Thu, 9 Nov 2017 12:30:29 -0800 Subject: [PATCH 47/73] Remove testcases we don't like --- src/harness/unittests/tsserverProjectSystem.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index c72a27e173e..5b6c36d071f 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -1501,20 +1501,17 @@ namespace ts.projectSystem { ["jquery-max", "jquery-max"], ["jquery.min", "jquery"], ["jquery-min.4.2.3", "jquery"], - ["jquery.4.2-test.js", "jquery"], + // ["jquery.4.2-test.js", "jquery"], ["jquery.min.4.2.1", "jquery"], - ["jquery.7.min.js", "jquery"], - ["jquery.7.min-beta", "jquery"], + // ["jquery.7.min.js", "jquery"], + // ["jquery.7.min-beta", "jquery"], ["minimum", "minimum"], ["min", "min"], ["min.3.2", "min"], ["jquery", "jquery"] ]; - const suffixes = [".js", ".jsx", ""]; for (const t of testData) { - for (const suf of suffixes) { - assert.equal(removeMinAndVersionNumbers(t[0] + suf), t[1]); - } + assert.equal(removeMinAndVersionNumbers(t[0]), t[1], t[0]); } }); From 19cc42782b1abe17fdd3911505f8afe36689d053 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Thu, 9 Nov 2017 12:30:36 -0800 Subject: [PATCH 48/73] Format + new regex --- src/compiler/core.ts | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 626480035b1..657f362067b 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -74,13 +74,13 @@ namespace ts { } // The global Map object. This may not be available, so we must test for it. - declare const Map: { new(): Map } | undefined; + declare const Map: { new (): Map } | undefined; // Internet Explorer's Map doesn't support iteration, so don't use it. // tslint:disable-next-line:no-in-operator const MapCtr = typeof Map !== "undefined" && "entries" in Map.prototype ? Map : shimMap(); // Keep the class inside a function so it doesn't get compiled if it's not used. - function shimMap(): { new(): Map } { + function shimMap(): { new (): Map } { class MapIterator { private data: MapLike; @@ -103,7 +103,7 @@ namespace ts { } } - return class implements Map { + return class implements Map { private data = createDictionaryObject(); public size = 0; @@ -166,8 +166,8 @@ namespace ts { } export const enum Comparison { - LessThan = -1, - EqualTo = 0, + LessThan = -1, + EqualTo = 0, GreaterThan = 1 } @@ -2417,13 +2417,11 @@ namespace ts { * Takes a string like "jquery-min.4.2.3" and returns "jquery" */ export function removeMinAndVersionNumbers(fileName: string) { - const match = /((\w|(-(?!min)))+)(\.|-)?.*/.exec(fileName); - if (match) { - return match[1]; - } - else { - return fileName; - } + // Match a "." or "-" followed by a version number or 'min' at the end of the name + const trailingMinOrVersion = /[.-]((min)|(\d+(\.\d+)*))$/; + + // The "min" or version may both be present, in either order, so try applying the above twice. + return fileName.replace(trailingMinOrVersion, "").replace(trailingMinOrVersion, ""); } export interface ObjectAllocator { @@ -2627,7 +2625,7 @@ namespace ts { return findBestPatternMatch(patterns, _ => _, candidate); } - export function patternText({prefix, suffix}: Pattern): string { + export function patternText({ prefix, suffix }: Pattern): string { return `${prefix}*${suffix}`; } @@ -2657,7 +2655,7 @@ namespace ts { return matchedValue; } - function isPatternMatch({prefix, suffix}: Pattern, candidate: string) { + function isPatternMatch({ prefix, suffix }: Pattern, candidate: string) { return candidate.length >= prefix.length + suffix.length && startsWith(candidate, prefix) && endsWith(candidate, suffix); From 0e105ad8de2b64a262b978b78ebca6c465a45bbf Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Thu, 9 Nov 2017 12:30:44 -0800 Subject: [PATCH 49/73] Log more usefully when this test fails --- src/harness/unittests/typingsInstaller.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index fb1a7a26a7a..65d904940b3 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -1057,11 +1057,12 @@ namespace ts.projectSystem { const host = createServerHost([app, jquery, chroma]); const logger = trackingLogger(); const result = JsTyping.discoverTypings(host, logger.log, [app.path, jquery.path, chroma.path], getDirectoryPath(app.path), safeList, emptyMap, { enable: true }, emptyArray); - assert.deepEqual(logger.finish(), [ + const finish = logger.finish(); + assert.deepEqual(finish, [ 'Inferred typings from file names: ["jquery","chroma-js"]', "Inferred typings from unresolved imports: []", 'Result: {"cachedTypingPaths":[],"newTypingNames":["jquery","chroma-js"],"filesToWatch":["/a/b/bower_components","/a/b/node_modules"]}', - ]); + ], finish.join("\r\n")); assert.deepEqual(result.newTypingNames, ["jquery", "chroma-js"]); }); From 65a191fa2b0d6671d4ce0b1eec5affd426e74739 Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 9 Nov 2017 13:13:23 -0800 Subject: [PATCH 50/73] For import completion of default import, convert module name to identifier (#19875) * For import completion of default import, convert module name to identifier * Suggestions from code review --- src/compiler/scanner.ts | 2 +- src/compiler/types.ts | 6 ++-- src/compiler/utilities.ts | 8 +++++ src/harness/fourslash.ts | 2 +- src/services/codefixes/importFixes.ts | 36 +++++++++++++++++-- src/services/completions.ts | 34 +++++++++++------- .../completionsImport_default_anonymous.ts | 26 ++++++++++++++ .../importNameCodeFixDefaultExport.ts | 12 +++++++ 8 files changed, 108 insertions(+), 18 deletions(-) create mode 100644 tests/cases/fourslash/completionsImport_default_anonymous.ts create mode 100644 tests/cases/fourslash/importNameCodeFixDefaultExport.ts diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index fd8c54a18cc..9fddece11d0 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -294,7 +294,7 @@ namespace ts { } /* @internal */ - export function stringToToken(s: string): SyntaxKind { + export function stringToToken(s: string): SyntaxKind | undefined { return textToToken.get(s); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d2107572ab4..bb62bead00b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -214,7 +214,7 @@ namespace ts { UndefinedKeyword, FromKeyword, GlobalKeyword, - OfKeyword, // LastKeyword and LastToken + OfKeyword, // LastKeyword and LastToken and LastContextualKeyword // Parse tree nodes @@ -431,7 +431,9 @@ namespace ts { FirstJSDocNode = JSDocTypeExpression, LastJSDocNode = JSDocPropertyTag, FirstJSDocTagNode = JSDocTag, - LastJSDocTagNode = JSDocPropertyTag + LastJSDocTagNode = JSDocPropertyTag, + /* @internal */ FirstContextualKeyword = AbstractKeyword, + /* @internal */ LastContextualKeyword = OfKeyword, } export const enum NodeFlags { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 41a5512cb2a..1931c397ae7 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1905,6 +1905,14 @@ namespace ts { return SyntaxKind.FirstKeyword <= token && token <= SyntaxKind.LastKeyword; } + export function isContextualKeyword(token: SyntaxKind): boolean { + return SyntaxKind.FirstContextualKeyword <= token && token <= SyntaxKind.LastContextualKeyword; + } + + export function isNonContextualKeyword(token: SyntaxKind): boolean { + return isKeyword(token) && !isContextualKeyword(token); + } + export function isTrivia(token: SyntaxKind) { return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken; } diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index c9aa1c6403d..2687a660ca8 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -3102,7 +3102,7 @@ Actual: ${stringify(fullActual)}`); } } - const itemsString = items.map(item => stringify({ name: item.name, kind: item.kind })).join(",\n"); + const itemsString = items.map(item => stringify({ name: item.name, source: item.source, kind: item.kind })).join(",\n"); this.raiseError(`Expected "${stringify({ entryId, text, documentation, kind })}" to be in list [${itemsString}]`); } diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index a0c7ffd75ea..838e19fa35d 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -699,9 +699,10 @@ namespace ts.codefix { const defaultExport = checker.tryGetMemberInModuleExports("default", moduleSymbol); if (defaultExport) { const localSymbol = getLocalSymbolForExportDefault(defaultExport); - if (localSymbol && localSymbol.escapedName === symbolName && checkSymbolHasMeaning(localSymbol, currentTokenMeaning)) { + if ((localSymbol && localSymbol.escapedName === symbolName || moduleSymbolToValidIdentifier(moduleSymbol, context.compilerOptions.target) === symbolName) + && checkSymbolHasMeaning(localSymbol || defaultExport, currentTokenMeaning)) { // check if this symbol is already used - const symbolId = getUniqueSymbolId(localSymbol, checker); + const symbolId = getUniqueSymbolId(localSymbol || defaultExport, checker); symbolIdActionMap.addActions(symbolId, getCodeActionForImport(moduleSymbol, { ...context, kind: ImportKind.Default })); } } @@ -731,4 +732,35 @@ namespace ts.codefix { } } } + + export function moduleSymbolToValidIdentifier(moduleSymbol: Symbol, target: ScriptTarget): string { + return moduleSpecifierToValidIdentifier(removeFileExtension(getBaseFileName(moduleSymbol.name)), target); + } + + function moduleSpecifierToValidIdentifier(moduleSpecifier: string, target: ScriptTarget): string { + let res = ""; + let lastCharWasValid = true; + const firstCharCode = moduleSpecifier.charCodeAt(0); + if (isIdentifierStart(firstCharCode, target)) { + res += String.fromCharCode(firstCharCode); + } + else { + lastCharWasValid = false; + } + for (let i = 1; i < moduleSpecifier.length; i++) { + const ch = moduleSpecifier.charCodeAt(i); + const isValid = isIdentifierPart(ch, target); + if (isValid) { + let char = String.fromCharCode(ch); + if (!lastCharWasValid) { + char = char.toUpperCase(); + } + res += char; + } + lastCharWasValid = isValid; + } + // Need `|| "_"` to ensure result isn't empty. + const token = stringToToken(res); + return token === undefined || !isNonContextualKeyword(token) ? res || "_" : `_${res}`; + } } diff --git a/src/services/completions.ts b/src/services/completions.ts index f66242ca864..6a9af1e1941 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -39,7 +39,7 @@ namespace ts.Completions { return getStringLiteralCompletionEntries(sourceFile, position, typeChecker, compilerOptions, host, log); } - const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles, options); + const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles, options, compilerOptions.target); if (!completionData) { return undefined; } @@ -136,12 +136,12 @@ namespace ts.Completions { typeChecker: TypeChecker, target: ScriptTarget, allowStringLiteral: boolean, - origin: SymbolOriginInfo, + origin: SymbolOriginInfo | undefined, ): CompletionEntry | undefined { // Try to get a valid display name for this symbol, if we could not find one, then ignore it. // We would like to only show things that can be added after a dot, so for instance numeric properties can // not be accessed with a dot (a.1 <- invalid) - const displayName = getCompletionEntryDisplayNameForSymbol(symbol, target, performCharacterChecks, allowStringLiteral); + const displayName = getCompletionEntryDisplayNameForSymbol(symbol, target, performCharacterChecks, allowStringLiteral, origin); if (!displayName) { return undefined; } @@ -381,7 +381,7 @@ namespace ts.Completions { { name, source }: CompletionEntryIdentifier, allSourceFiles: ReadonlyArray, ): { type: "symbol", symbol: Symbol, location: Node, symbolToOriginInfoMap: SymbolOriginInfoMap } | { type: "request", request: Request } | { type: "none" } { - const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles, { includeExternalModuleExports: true }); + const completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles, { includeExternalModuleExports: true }, compilerOptions.target); if (!completionData) { return { type: "none" }; } @@ -395,12 +395,18 @@ namespace ts.Completions { // We don't need to perform character checks here because we're only comparing the // name against 'entryName' (which is known to be good), not building a new // completion entry. - const symbol = find(symbols, s => - getCompletionEntryDisplayNameForSymbol(s, compilerOptions.target, /*performCharacterChecks*/ false, allowStringLiteral) === name - && getSourceFromOrigin(symbolToOriginInfoMap[getSymbolId(s)]) === source); + const symbol = find(symbols, s => { + const origin = symbolToOriginInfoMap[getSymbolId(s)]; + return getCompletionEntryDisplayNameForSymbol(s, compilerOptions.target, /*performCharacterChecks*/ false, allowStringLiteral, origin) === name + && getSourceFromOrigin(origin) === source; + }); return symbol ? { type: "symbol", symbol, location, symbolToOriginInfoMap } : { type: "none" }; } + function getSymbolName(symbol: Symbol, origin: SymbolOriginInfo | undefined, target: ScriptTarget): string { + return origin && origin.isDefaultExport && symbol.name === "default" ? codefix.moduleSymbolToValidIdentifier(origin.moduleSymbol, target) : symbol.name; + } + export interface CompletionEntryIdentifier { name: string; source?: string; @@ -482,7 +488,7 @@ namespace ts.Completions { compilerOptions, sourceFile, formatContext, - symbolName: symbol.name, + symbolName: getSymbolName(symbol, symbolOriginInfo, compilerOptions.target), getCanonicalFileName: createGetCanonicalFileName(host.useCaseSensitiveFileNames ? host.useCaseSensitiveFileNames() : false), symbolToken: undefined, kind: isDefaultExport ? codefix.ImportKind.Default : codefix.ImportKind.Named, @@ -523,6 +529,7 @@ namespace ts.Completions { position: number, allSourceFiles: ReadonlyArray, options: GetCompletionsAtPositionOptions, + target: ScriptTarget, ): CompletionData | undefined { const isJavaScriptFile = isSourceFileJavaScript(sourceFile); @@ -921,7 +928,7 @@ namespace ts.Completions { symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings); if (options.includeExternalModuleExports) { - getSymbolsFromOtherSourceFileExports(symbols, previousToken && isIdentifier(previousToken) ? previousToken.text : ""); + getSymbolsFromOtherSourceFileExports(symbols, previousToken && isIdentifier(previousToken) ? previousToken.text : "", target); } filterGlobalCompletion(symbols); @@ -1003,7 +1010,7 @@ namespace ts.Completions { } } - function getSymbolsFromOtherSourceFileExports(symbols: Symbol[], tokenText: string): void { + function getSymbolsFromOtherSourceFileExports(symbols: Symbol[], tokenText: string, target: ScriptTarget): void { const tokenTextLowerCase = tokenText.toLowerCase(); codefix.forEachExternalModule(typeChecker, allSourceFiles, moduleSymbol => { @@ -1020,6 +1027,9 @@ namespace ts.Completions { symbol = localSymbol; name = localSymbol.name; } + else { + name = codefix.moduleSymbolToValidIdentifier(moduleSymbol, target); + } } if (symbol.declarations && symbol.declarations.some(d => isExportSpecifier(d) && !!d.parent.parent.moduleSpecifier)) { @@ -1847,8 +1857,8 @@ namespace ts.Completions { * * @return undefined if the name is of external module */ - function getCompletionEntryDisplayNameForSymbol(symbol: Symbol, target: ScriptTarget, performCharacterChecks: boolean, allowStringLiteral: boolean): string | undefined { - const name = symbol.name; + function getCompletionEntryDisplayNameForSymbol(symbol: Symbol, target: ScriptTarget, performCharacterChecks: boolean, allowStringLiteral: boolean, origin: SymbolOriginInfo | undefined): string | undefined { + const name = getSymbolName(symbol, origin, target); if (!name) return undefined; // First check of the displayName is not external module; if it is an external module, it is not valid entry diff --git a/tests/cases/fourslash/completionsImport_default_anonymous.ts b/tests/cases/fourslash/completionsImport_default_anonymous.ts new file mode 100644 index 00000000000..7c0697584f9 --- /dev/null +++ b/tests/cases/fourslash/completionsImport_default_anonymous.ts @@ -0,0 +1,26 @@ +/// + +// Use `/src` to test that directory names are not included in conversion from module path to identifier. + +// @Filename: /src/foo-bar.ts +////export default 0; + +// @Filename: /src/b.ts +////def/*0*/ +////fooB/*1*/ + +goTo.marker("0"); +verify.not.completionListContains({ name: "default", source: "/src/foo-bar" }, undefined, undefined, undefined, undefined, undefined, { includeExternalModuleExports: true }); + +goTo.marker("1"); +verify.completionListContains({ name: "fooBar", source: "/src/foo-bar" }, "(property) default: 0", "", "property", /*spanIndex*/ undefined, /*hasAction*/ true, { includeExternalModuleExports: true }); +verify.applyCodeActionFromCompletion("1", { + name: "fooBar", + source: "/src/foo-bar", + description: `Import 'fooBar' from "./foo-bar".`, + // TODO: GH#18445 + newFileContent: `import fooBar from "./foo-bar";\r +\r +def +fooB`, +}); diff --git a/tests/cases/fourslash/importNameCodeFixDefaultExport.ts b/tests/cases/fourslash/importNameCodeFixDefaultExport.ts new file mode 100644 index 00000000000..2f502aa66fa --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFixDefaultExport.ts @@ -0,0 +1,12 @@ +/// + +// @Filename: /foo-bar.ts +////export default 0; + +// @Filename: /b.ts +////[|foo/**/Bar|] + +goTo.file("/b.ts"); +verify.importFixAtPosition([`import fooBar from "./foo-bar"; + +fooBar`]); From b94940525b77f31a8e7782c92fe3ea53371c93fb Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 9 Nov 2017 13:17:47 -0800 Subject: [PATCH 51/73] Allow applyCodeActionCommand to take an array (#19870) * Allow applyCodeActionCommand to take an array * Use this.host.newLine --- src/server/protocol.ts | 1 + src/server/session.ts | 7 +++++-- src/services/services.ts | 10 ++++++++-- src/services/types.ts | 2 ++ src/services/utilities.ts | 1 + tests/baselines/reference/api/tsserverlibrary.d.ts | 3 +++ tests/baselines/reference/api/typescript.d.ts | 2 ++ 7 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/server/protocol.ts b/src/server/protocol.ts index f44efa0db21..3761049017d 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -586,6 +586,7 @@ namespace ts.server.protocol { } export interface ApplyCodeActionCommandRequestArgs extends FileRequestArgs { + /** May also be an array of commands. */ command: {}; } diff --git a/src/server/session.ts b/src/server/session.ts index 6c97c3c8bd4..f9a145d16fd 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1571,9 +1571,12 @@ namespace ts.server { private applyCodeActionCommand(commandName: string, requestSeq: number, args: protocol.ApplyCodeActionCommandRequestArgs): void { const { file, project } = this.getFileAndProject(args); const output = (success: boolean, message: string) => this.doOutput({}, commandName, requestSeq, success, message); - const command = args.command as CodeActionCommand; // They should be sending back the command we sent them. + const command = args.command as CodeActionCommand | CodeActionCommand[]; // They should be sending back the command we sent them. + project.getLanguageService().applyCodeActionCommand(file, command).then( - ({ successMessage }) => { output(/*success*/ true, successMessage); }, + result => { + output(/*success*/ true, isArray(result) ? result.map(res => res.successMessage).join(`${this.host.newLine}${this.host.newLine}`) : result.successMessage); + }, error => { output(/*success*/ false, error); }); } diff --git a/src/services/services.ts b/src/services/services.ts index 37298c8eba8..06358d3a720 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1868,8 +1868,14 @@ namespace ts { }); } - function applyCodeActionCommand(fileName: Path, action: CodeActionCommand): Promise { - fileName = toPath(fileName, currentDirectory, getCanonicalFileName); + function applyCodeActionCommand(fileName: Path, action: CodeActionCommand): Promise; + function applyCodeActionCommand(fileName: Path, action: CodeActionCommand[]): Promise; + function applyCodeActionCommand(fileName: Path, action: CodeActionCommand | CodeActionCommand[]): Promise { + const path = toPath(fileName, currentDirectory, getCanonicalFileName); + return isArray(action) ? Promise.all(action.map(a => applySingleCodeActionCommand(path, a))) : applySingleCodeActionCommand(path, action); + } + + function applySingleCodeActionCommand(fileName: Path, action: CodeActionCommand): Promise { switch (action.type) { case "install package": return host.installPackage diff --git a/src/services/types.ts b/src/services/types.ts index a9244982fbb..bcebc437892 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -294,6 +294,8 @@ namespace ts { getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[]; applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise; + applyCodeActionCommand(fileName: string, action: CodeActionCommand[]): Promise; + applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise; getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined; diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 1ed44d29f95..cf71118292a 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -3,6 +3,7 @@ interface PromiseConstructor { new (executor: (resolve: (value?: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; reject(reason: any): Promise; + all(values: (T | PromiseLike)[]): Promise; } /* @internal */ declare var Promise: PromiseConstructor; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index a3499de08ab..78e8a377ec0 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3965,6 +3965,8 @@ declare namespace ts { getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[]; applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise; + applyCodeActionCommand(fileName: string, action: CodeActionCommand[]): Promise; + applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise; getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined; getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput; @@ -5263,6 +5265,7 @@ declare namespace ts.server.protocol { errorCodes?: number[]; } interface ApplyCodeActionCommandRequestArgs extends FileRequestArgs { + /** May also be an array of commands. */ command: {}; } /** diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 98d7137ddeb..3344193d0ce 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3965,6 +3965,8 @@ declare namespace ts { getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan; getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[]; applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise; + applyCodeActionCommand(fileName: string, action: CodeActionCommand[]): Promise; + applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise; getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[]; getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined; getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput; From 0d5dec9a9870637cb4602cd7eb05683d97d0dcda Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Thu, 9 Nov 2017 13:55:20 -0800 Subject: [PATCH 52/73] Remove commented tests --- src/harness/unittests/tsserverProjectSystem.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 018934e9d7d..ea573726eb8 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -1544,10 +1544,7 @@ namespace ts.projectSystem { ["jquery-max", "jquery-max"], ["jquery.min", "jquery"], ["jquery-min.4.2.3", "jquery"], - // ["jquery.4.2-test.js", "jquery"], ["jquery.min.4.2.1", "jquery"], - // ["jquery.7.min.js", "jquery"], - // ["jquery.7.min-beta", "jquery"], ["minimum", "minimum"], ["min", "min"], ["min.3.2", "min"], From a5fa75a0cd095702d41e259cd2eb73d2c777b162 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 9 Nov 2017 14:21:08 -0800 Subject: [PATCH 53/73] DefinitelyTypedRunner skips ExpectErrors If all errors were ExpectErrors, then it does not fail. --- src/harness/externalCompileRunner.ts | 91 +++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 16 deletions(-) diff --git a/src/harness/externalCompileRunner.ts b/src/harness/externalCompileRunner.ts index 9b8fc8c4fc5..ec8acf4872e 100644 --- a/src/harness/externalCompileRunner.ts +++ b/src/harness/externalCompileRunner.ts @@ -1,14 +1,17 @@ /// /// +const fs = require("fs"); +const path = require("path"); abstract class ExternalCompileRunnerBase extends RunnerBase { abstract testDir: string; - public enumerateTestFiles() { + abstract report(result: any, cwd: string): string; + enumerateTestFiles() { return Harness.IO.getDirectories(this.testDir); } /** Setup the runner's tests so that they are ready to be executed by the harness * The first test should be a describe/it block that sets up the harness's compiler instance appropriately */ - public initializeTests(): void { + initializeTests(): void { // Read in and evaluate the test list const testList = this.tests && this.tests.length ? this.tests : this.enumerateTestFiles(); @@ -36,15 +39,7 @@ abstract class ExternalCompileRunnerBase extends RunnerBase { if (install.status !== 0) throw new Error(`NPM Install for ${directoryName} failed!`); } Harness.Baseline.runBaseline(`${this.kind()}/${directoryName}.log`, () => { - const result = cp.spawnSync(`node`, [path.join(__dirname, "tsc.js")], { cwd, timeout, shell: true }); - // tslint:disable-next-line:no-null-keyword - return result.status === 0 && !result.stdout.length && !result.stderr.length ? null : `Exit Code: ${result.status} -Standard output: -${result.stdout.toString().replace(/\r\n/g, "\n")} - - -Standard error: -${result.stderr.toString().replace(/\r\n/g, "\n")}`; + return this.report(cp.spawnSync(`node`, [path.join(__dirname, "tsc.js")], { cwd, timeout, shell: true }), cwd); }); }); }); @@ -52,16 +47,80 @@ ${result.stderr.toString().replace(/\r\n/g, "\n")}`; } class UserCodeRunner extends ExternalCompileRunnerBase { - public readonly testDir = "tests/cases/user/"; - public kind(): TestRunnerKind { + readonly testDir = "tests/cases/user/"; + kind(): TestRunnerKind { return "user"; } + report(result: any) { + // tslint:disable-next-line:no-null-keyword + return result.status === 0 && !result.stdout.length && !result.stderr.length ? null : `Exit Code: ${result.status} +Standard output: +${result.stdout.toString().replace(/\r\n/g, "\n")} + + +Standard error: +${result.stderr.toString().replace(/\r\n/g, "\n")}`; + } } class DefinitelyTypedRunner extends ExternalCompileRunnerBase { - public readonly testDir = "../DefinitelyTyped/types/"; - public workingDirectory = this.testDir; - public kind(): TestRunnerKind { + readonly testDir = "../DefinitelyTyped/types/"; + workingDirectory = this.testDir; + kind(): TestRunnerKind { return "dt"; } + report(result: any, cwd: string) { + const stdout = filterExpectedErrors(result.stdout.toString(), cwd) + const stderr = result.stderr.toString() + // tslint:disable-next-line:no-null-keyword + return !stdout.length && !stderr.length ? null : `Exit Code: ${result.status} +Standard output: +${stdout.replace(/\r\n/g, "\n")} + + +Standard error: +${stderr.replace(/\r\n/g, "\n")}`; + } +} + +function filterExpectedErrors(errors: string, cwd: string): string { + return breaks(errors.split("\n"), s => /^\w+/.test(s)).filter(isExpectedError(cwd)).map(lines => lines.join("\n")).join("\n"); +} +function isExpectedError(cwd: string) { + return (error: string[]) => { + if (error.length === 0) { + return true; + } + const match = error[0].match(/(.+\.ts)\((\d+),\d+\): error TS/); + if (!match) { + return true; + } + const errlines = fs.readFileSync(path.join(cwd, match[1]), { encoding: "utf8" }).split("\n"); + const index = parseInt(match[2]); + const errline = index < errlines.length ? errlines[index] : ""; + const prevline = index - 1 < errlines.length && index > 0 ? errlines[index - 1] : ""; + if (errline.indexOf("$ExpectError") > -1 || prevline.indexOf("$ExpectError") > -1) { + return false; + } + return true; + } +} +function breaks(xs: T[], isStart: (T: any) => boolean): T[][] { + const result = []; + let group: T[] = []; + for (const x of xs) { + if (isStart(x)) { + if (group.length) { + result.push(group); + } + group = [x]; + } + else { + group.push(x); + } + } + if (group.length) { + result.push(group); + } + return result; } From 2372ffcddc22c567d81f7667cd3ae8451f82e6ca Mon Sep 17 00:00:00 2001 From: csigs Date: Thu, 9 Nov 2017 23:10:34 +0000 Subject: [PATCH 54/73] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 160 +++++++++--------- 1 file changed, 77 insertions(+), 83 deletions(-) diff --git a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl index 8dab90a1ba2..3bb9642d207 100644 --- a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1620,12 +1620,9 @@ - + - - - - + @@ -3735,6 +3732,24 @@ + + + + + + + + + + + + + + + + + + @@ -3966,6 +3981,15 @@ + + + + + + + + + @@ -5211,24 +5235,6 @@ - - - - - - - - - - - - - - - - - - @@ -5256,24 +5262,6 @@ - - - - - - - - - - - - - - - - - - @@ -5292,6 +5280,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -5997,6 +6009,24 @@ + + + + + + + + + + + + + + + + + + @@ -6024,30 +6054,21 @@ - + - - - - + - + - - - - + - + - - - - + @@ -6078,33 +6099,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - From 16efae24338f09c9059c8ec1525166f521110935 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 9 Nov 2017 16:49:04 -0800 Subject: [PATCH 55/73] Consider the commonjs module indicator as a module indicator (#18490) * Consider the commonjs module indicator as an indicator that something is effectively an external module * Only use commonjs module indicator when targeting commonjs --- src/compiler/transformers/module/module.ts | 2 +- src/compiler/utilities.ts | 2 +- .../reference/javascriptCommonjsModule.js | 23 +++++++++++++++++++ .../javascriptCommonjsModule.symbols | 13 +++++++++++ .../reference/javascriptCommonjsModule.types | 15 ++++++++++++ .../compiler/javascriptCommonjsModule.ts | 11 +++++++++ 6 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/javascriptCommonjsModule.js create mode 100644 tests/baselines/reference/javascriptCommonjsModule.symbols create mode 100644 tests/baselines/reference/javascriptCommonjsModule.types create mode 100644 tests/cases/compiler/javascriptCommonjsModule.ts diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index f60e50ea365..0c8e2cda0f5 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -57,7 +57,7 @@ namespace ts { * @param node The SourceFile node. */ function transformSourceFile(node: SourceFile) { - if (node.isDeclarationFile || !(isExternalModule(node) || compilerOptions.isolatedModules || node.transformFlags & TransformFlags.ContainsDynamicImport)) { + if (node.isDeclarationFile || !(isEffectiveExternalModule(node, compilerOptions) || node.transformFlags & TransformFlags.ContainsDynamicImport)) { return node; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 1931c397ae7..e67635cba04 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -461,7 +461,7 @@ namespace ts { } export function isEffectiveExternalModule(node: SourceFile, compilerOptions: CompilerOptions) { - return isExternalModule(node) || compilerOptions.isolatedModules; + return isExternalModule(node) || compilerOptions.isolatedModules || ((getEmitModuleKind(compilerOptions) === ModuleKind.CommonJS) && !!node.commonJsModuleIndicator); } /* @internal */ diff --git a/tests/baselines/reference/javascriptCommonjsModule.js b/tests/baselines/reference/javascriptCommonjsModule.js new file mode 100644 index 00000000000..ab517f63805 --- /dev/null +++ b/tests/baselines/reference/javascriptCommonjsModule.js @@ -0,0 +1,23 @@ +//// [index.js] +class Foo {} + +class Bar extends Foo {} + +module.exports = Bar; + + +//// [index.js] +var tslib_1 = require("tslib"); +var Foo = /** @class */ (function () { + function Foo() { + } + return Foo; +}()); +var Bar = /** @class */ (function (_super) { + tslib_1.__extends(Bar, _super); + function Bar() { + return _super !== null && _super.apply(this, arguments) || this; + } + return Bar; +}(Foo)); +module.exports = Bar; diff --git a/tests/baselines/reference/javascriptCommonjsModule.symbols b/tests/baselines/reference/javascriptCommonjsModule.symbols new file mode 100644 index 00000000000..923e0b3467b --- /dev/null +++ b/tests/baselines/reference/javascriptCommonjsModule.symbols @@ -0,0 +1,13 @@ +=== tests/cases/compiler/index.js === +class Foo {} +>Foo : Symbol(Foo, Decl(index.js, 0, 0)) + +class Bar extends Foo {} +>Bar : Symbol(Bar, Decl(index.js, 0, 12)) +>Foo : Symbol(Foo, Decl(index.js, 0, 0)) + +module.exports = Bar; +>module : Symbol(export=, Decl(index.js, 2, 24)) +>exports : Symbol(export=, Decl(index.js, 2, 24)) +>Bar : Symbol(Bar, Decl(index.js, 0, 12)) + diff --git a/tests/baselines/reference/javascriptCommonjsModule.types b/tests/baselines/reference/javascriptCommonjsModule.types new file mode 100644 index 00000000000..88126ce4737 --- /dev/null +++ b/tests/baselines/reference/javascriptCommonjsModule.types @@ -0,0 +1,15 @@ +=== tests/cases/compiler/index.js === +class Foo {} +>Foo : Foo + +class Bar extends Foo {} +>Bar : Bar +>Foo : Foo + +module.exports = Bar; +>module.exports = Bar : typeof Bar +>module.exports : any +>module : any +>exports : any +>Bar : typeof Bar + diff --git a/tests/cases/compiler/javascriptCommonjsModule.ts b/tests/cases/compiler/javascriptCommonjsModule.ts new file mode 100644 index 00000000000..dde30580f70 --- /dev/null +++ b/tests/cases/compiler/javascriptCommonjsModule.ts @@ -0,0 +1,11 @@ +// @allowJS: true +// @outDir: ./out +// @module: commonjs +// @noEmitHelpers: true +// @importHelpers: true +// @filename: index.js +class Foo {} + +class Bar extends Foo {} + +module.exports = Bar; From 2010c4cda1097697390d981d63d31600d1fe9808 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 10 Nov 2017 08:30:59 -0800 Subject: [PATCH 56/73] Give lowest priority to inferences made from empty array literals --- src/compiler/checker.ts | 17 ++++++++++------- src/compiler/types.ts | 1 + 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a9aaa77fa74..fedc0c77c8f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10898,22 +10898,25 @@ namespace ts { // it as an inference candidate. Hopefully, a better candidate will come along that does // not contain anyFunctionType when we come back to this argument for its second round // of inference. Also, we exclude inferences for silentNeverType (which is used as a wildcard - // when constructing types from type parameters that had no inference candidates) and - // implicitNeverType (which is used as the element type for empty array literals). - if (source.flags & TypeFlags.ContainsAnyFunctionType || source === silentNeverType || source === implicitNeverType) { + // when constructing types from type parameters that had no inference candidates). + if (source.flags & TypeFlags.ContainsAnyFunctionType || source === silentNeverType) { return; } const inference = getInferenceInfoForType(target); if (inference) { if (!inference.isFixed) { - if (!inference.candidates || priority < inference.priority) { + // We give lowest priority to inferences of implicitNeverType (which is used as the + // element type for empty array literals). Thus, inferences from empty array literals + // only matter when no other inferences are made. + const p = priority | (source === implicitNeverType ? InferencePriority.NeverType : 0); + if (!inference.candidates || p < inference.priority) { inference.candidates = [source]; - inference.priority = priority; + inference.priority = p; } - else if (priority === inference.priority) { + else if (p === inference.priority) { inference.candidates.push(source); } - if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, target)) { + if (!(p & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, target)) { inference.topLevel = false; } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index bb62bead00b..3141e3f22d9 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3613,6 +3613,7 @@ namespace ts { NakedTypeVariable = 1 << 1, // Naked type variable in union or intersection type MappedType = 1 << 2, // Reverse inference for mapped type ReturnType = 1 << 3, // Inference made from return type of generic function + NeverType = 1 << 4, // Inference made from the never type } export interface InferenceInfo { From 197c635994a5d02c50d6066f05f4382da446a8fa Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 10 Nov 2017 08:36:50 -0800 Subject: [PATCH 57/73] Update tests --- .../cases/conformance/types/never/neverInference.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/cases/conformance/types/never/neverInference.ts b/tests/cases/conformance/types/never/neverInference.ts index 1258a35e3d3..c28d30d92c2 100644 --- a/tests/cases/conformance/types/never/neverInference.ts +++ b/tests/cases/conformance/types/never/neverInference.ts @@ -1,11 +1,11 @@ // @strict: true -declare function f(x: T[]): T; +declare function f1(x: T[]): T; let neverArray: never[] = []; -let a1 = f([]); // {} -let a2 = f(neverArray); // never +let a1 = f1([]); // never +let a2 = f1(neverArray); // never // Repro from #19576 @@ -22,3 +22,9 @@ declare function compareNumbers(x: number, y: number): number; declare function mkList(items: T[], comparator: Comparator): LinkedList; const list: LinkedList = mkList([], compareNumbers); + +// Repro from #19858 + +declare function f2(as1: a[], as2: a[], cmp: (a1: a, a2: a) => number): void; +f2(Array.from([0]), [], (a1, a2) => a1 - a2); +f2(Array.from([]), [0], (a1, a2) => a1 - a2); From afec1e1fa154e1a51ec60ef15433f93ace5b74b9 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 10 Nov 2017 08:39:29 -0800 Subject: [PATCH 58/73] Update test --- tests/cases/conformance/types/never/neverInference.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/cases/conformance/types/never/neverInference.ts b/tests/cases/conformance/types/never/neverInference.ts index c28d30d92c2..549d27ae109 100644 --- a/tests/cases/conformance/types/never/neverInference.ts +++ b/tests/cases/conformance/types/never/neverInference.ts @@ -1,4 +1,5 @@ // @strict: true +// @target: es2015 declare function f1(x: T[]): T; From 2c43ef1e9b262477ced59124f2541a5102d0894d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 10 Nov 2017 08:39:49 -0800 Subject: [PATCH 59/73] Accept new baselines --- tests/baselines/reference/neverInference.js | 22 ++++-- .../reference/neverInference.symbols | 61 +++++++++++++---- .../baselines/reference/neverInference.types | 67 ++++++++++++++++--- 3 files changed, 121 insertions(+), 29 deletions(-) diff --git a/tests/baselines/reference/neverInference.js b/tests/baselines/reference/neverInference.js index d13e537eba4..3b570599772 100644 --- a/tests/baselines/reference/neverInference.js +++ b/tests/baselines/reference/neverInference.js @@ -1,10 +1,10 @@ //// [neverInference.ts] -declare function f(x: T[]): T; +declare function f1(x: T[]): T; let neverArray: never[] = []; -let a1 = f([]); // {} -let a2 = f(neverArray); // never +let a1 = f1([]); // never +let a2 = f1(neverArray); // never // Repro from #19576 @@ -21,11 +21,19 @@ declare function compareNumbers(x: number, y: number): number; declare function mkList(items: T[], comparator: Comparator): LinkedList; const list: LinkedList = mkList([], compareNumbers); + +// Repro from #19858 + +declare function f2(as1: a[], as2: a[], cmp: (a1: a, a2: a) => number): void; +f2(Array.from([0]), [], (a1, a2) => a1 - a2); +f2(Array.from([]), [0], (a1, a2) => a1 - a2); //// [neverInference.js] "use strict"; -var neverArray = []; -var a1 = f([]); // {} -var a2 = f(neverArray); // never -var list = mkList([], compareNumbers); +let neverArray = []; +let a1 = f1([]); // never +let a2 = f1(neverArray); // never +const list = mkList([], compareNumbers); +f2(Array.from([0]), [], (a1, a2) => a1 - a2); +f2(Array.from([]), [0], (a1, a2) => a1 - a2); diff --git a/tests/baselines/reference/neverInference.symbols b/tests/baselines/reference/neverInference.symbols index 683e079b2f8..0441770dd3f 100644 --- a/tests/baselines/reference/neverInference.symbols +++ b/tests/baselines/reference/neverInference.symbols @@ -1,27 +1,27 @@ === tests/cases/conformance/types/never/neverInference.ts === -declare function f(x: T[]): T; ->f : Symbol(f, Decl(neverInference.ts, 0, 0)) ->T : Symbol(T, Decl(neverInference.ts, 0, 19)) ->x : Symbol(x, Decl(neverInference.ts, 0, 22)) ->T : Symbol(T, Decl(neverInference.ts, 0, 19)) ->T : Symbol(T, Decl(neverInference.ts, 0, 19)) +declare function f1(x: T[]): T; +>f1 : Symbol(f1, Decl(neverInference.ts, 0, 0)) +>T : Symbol(T, Decl(neverInference.ts, 0, 20)) +>x : Symbol(x, Decl(neverInference.ts, 0, 23)) +>T : Symbol(T, Decl(neverInference.ts, 0, 20)) +>T : Symbol(T, Decl(neverInference.ts, 0, 20)) let neverArray: never[] = []; >neverArray : Symbol(neverArray, Decl(neverInference.ts, 2, 3)) -let a1 = f([]); // {} +let a1 = f1([]); // never >a1 : Symbol(a1, Decl(neverInference.ts, 4, 3)) ->f : Symbol(f, Decl(neverInference.ts, 0, 0)) +>f1 : Symbol(f1, Decl(neverInference.ts, 0, 0)) -let a2 = f(neverArray); // never +let a2 = f1(neverArray); // never >a2 : Symbol(a2, Decl(neverInference.ts, 5, 3)) ->f : Symbol(f, Decl(neverInference.ts, 0, 0)) +>f1 : Symbol(f1, Decl(neverInference.ts, 0, 0)) >neverArray : Symbol(neverArray, Decl(neverInference.ts, 2, 3)) // Repro from #19576 type Comparator = (x: T, y: T) => number; ->Comparator : Symbol(Comparator, Decl(neverInference.ts, 5, 23)) +>Comparator : Symbol(Comparator, Decl(neverInference.ts, 5, 24)) >T : Symbol(T, Decl(neverInference.ts, 9, 16)) >x : Symbol(x, Decl(neverInference.ts, 9, 22)) >T : Symbol(T, Decl(neverInference.ts, 9, 16)) @@ -34,7 +34,7 @@ interface LinkedList { comparator: Comparator, >comparator : Symbol(LinkedList.comparator, Decl(neverInference.ts, 11, 25)) ->Comparator : Symbol(Comparator, Decl(neverInference.ts, 5, 23)) +>Comparator : Symbol(Comparator, Decl(neverInference.ts, 5, 24)) >T : Symbol(T, Decl(neverInference.ts, 11, 21)) nodes: Node @@ -63,7 +63,7 @@ declare function mkList(items: T[], comparator: Comparator): LinkedList >items : Symbol(items, Decl(neverInference.ts, 19, 27)) >T : Symbol(T, Decl(neverInference.ts, 19, 24)) >comparator : Symbol(comparator, Decl(neverInference.ts, 19, 38)) ->Comparator : Symbol(Comparator, Decl(neverInference.ts, 5, 23)) +>Comparator : Symbol(Comparator, Decl(neverInference.ts, 5, 24)) >T : Symbol(T, Decl(neverInference.ts, 19, 24)) >LinkedList : Symbol(LinkedList, Decl(neverInference.ts, 9, 44)) >T : Symbol(T, Decl(neverInference.ts, 19, 24)) @@ -74,3 +74,38 @@ const list: LinkedList = mkList([], compareNumbers); >mkList : Symbol(mkList, Decl(neverInference.ts, 18, 62)) >compareNumbers : Symbol(compareNumbers, Decl(neverInference.ts, 16, 49)) +// Repro from #19858 + +declare function f2(as1: a[], as2: a[], cmp: (a1: a, a2: a) => number): void; +>f2 : Symbol(f2, Decl(neverInference.ts, 21, 60)) +>a : Symbol(a, Decl(neverInference.ts, 25, 20)) +>as1 : Symbol(as1, Decl(neverInference.ts, 25, 23)) +>a : Symbol(a, Decl(neverInference.ts, 25, 20)) +>as2 : Symbol(as2, Decl(neverInference.ts, 25, 32)) +>a : Symbol(a, Decl(neverInference.ts, 25, 20)) +>cmp : Symbol(cmp, Decl(neverInference.ts, 25, 42)) +>a1 : Symbol(a1, Decl(neverInference.ts, 25, 49)) +>a : Symbol(a, Decl(neverInference.ts, 25, 20)) +>a2 : Symbol(a2, Decl(neverInference.ts, 25, 55)) +>a : Symbol(a, Decl(neverInference.ts, 25, 20)) + +f2(Array.from([0]), [], (a1, a2) => a1 - a2); +>f2 : Symbol(f2, Decl(neverInference.ts, 21, 60)) +>Array.from : Symbol(ArrayConstructor.from, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>from : Symbol(ArrayConstructor.from, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>a1 : Symbol(a1, Decl(neverInference.ts, 26, 25)) +>a2 : Symbol(a2, Decl(neverInference.ts, 26, 28)) +>a1 : Symbol(a1, Decl(neverInference.ts, 26, 25)) +>a2 : Symbol(a2, Decl(neverInference.ts, 26, 28)) + +f2(Array.from([]), [0], (a1, a2) => a1 - a2); +>f2 : Symbol(f2, Decl(neverInference.ts, 21, 60)) +>Array.from : Symbol(ArrayConstructor.from, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>from : Symbol(ArrayConstructor.from, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>a1 : Symbol(a1, Decl(neverInference.ts, 27, 25)) +>a2 : Symbol(a2, Decl(neverInference.ts, 27, 28)) +>a1 : Symbol(a1, Decl(neverInference.ts, 27, 25)) +>a2 : Symbol(a2, Decl(neverInference.ts, 27, 28)) + diff --git a/tests/baselines/reference/neverInference.types b/tests/baselines/reference/neverInference.types index a7dd05a3f8b..2f4b9e0cc1e 100644 --- a/tests/baselines/reference/neverInference.types +++ b/tests/baselines/reference/neverInference.types @@ -1,6 +1,6 @@ === tests/cases/conformance/types/never/neverInference.ts === -declare function f(x: T[]): T; ->f : (x: T[]) => T +declare function f1(x: T[]): T; +>f1 : (x: T[]) => T >T : T >x : T[] >T : T @@ -10,16 +10,16 @@ let neverArray: never[] = []; >neverArray : never[] >[] : never[] -let a1 = f([]); // {} ->a1 : {} ->f([]) : {} ->f : (x: T[]) => T +let a1 = f1([]); // never +>a1 : never +>f1([]) : never +>f1 : (x: T[]) => T >[] : never[] -let a2 = f(neverArray); // never +let a2 = f1(neverArray); // never >a2 : never ->f(neverArray) : never ->f : (x: T[]) => T +>f1(neverArray) : never +>f1 : (x: T[]) => T >neverArray : never[] // Repro from #19576 @@ -81,3 +81,52 @@ const list: LinkedList = mkList([], compareNumbers); >[] : never[] >compareNumbers : (x: number, y: number) => number +// Repro from #19858 + +declare function f2(as1: a[], as2: a[], cmp: (a1: a, a2: a) => number): void; +>f2 : (as1: a[], as2: a[], cmp: (a1: a, a2: a) => number) => void +>a : a +>as1 : a[] +>a : a +>as2 : a[] +>a : a +>cmp : (a1: a, a2: a) => number +>a1 : a +>a : a +>a2 : a +>a : a + +f2(Array.from([0]), [], (a1, a2) => a1 - a2); +>f2(Array.from([0]), [], (a1, a2) => a1 - a2) : void +>f2 : (as1: a[], as2: a[], cmp: (a1: a, a2: a) => number) => void +>Array.from([0]) : number[] +>Array.from : { (iterable: Iterable): T[]; (iterable: Iterable, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; (arrayLike: ArrayLike): T[]; (arrayLike: ArrayLike, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; } +>Array : ArrayConstructor +>from : { (iterable: Iterable): T[]; (iterable: Iterable, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; (arrayLike: ArrayLike): T[]; (arrayLike: ArrayLike, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; } +>[0] : number[] +>0 : 0 +>[] : never[] +>(a1, a2) => a1 - a2 : (a1: number, a2: number) => number +>a1 : number +>a2 : number +>a1 - a2 : number +>a1 : number +>a2 : number + +f2(Array.from([]), [0], (a1, a2) => a1 - a2); +>f2(Array.from([]), [0], (a1, a2) => a1 - a2) : void +>f2 : (as1: a[], as2: a[], cmp: (a1: a, a2: a) => number) => void +>Array.from([]) : never[] +>Array.from : { (iterable: Iterable): T[]; (iterable: Iterable, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; (arrayLike: ArrayLike): T[]; (arrayLike: ArrayLike, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; } +>Array : ArrayConstructor +>from : { (iterable: Iterable): T[]; (iterable: Iterable, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; (arrayLike: ArrayLike): T[]; (arrayLike: ArrayLike, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; } +>[] : never[] +>[0] : number[] +>0 : 0 +>(a1, a2) => a1 - a2 : (a1: number, a2: number) => number +>a1 : number +>a2 : number +>a1 - a2 : number +>a1 : number +>a2 : number + From c3b650fb38eaba314301edc0a6ce64a7b122acd2 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 10 Nov 2017 08:44:38 -0800 Subject: [PATCH 60/73] Accept API baseline changes --- tests/baselines/reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 78e8a377ec0..ffca9ca6c5a 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2142,6 +2142,7 @@ declare namespace ts { NakedTypeVariable = 2, MappedType = 4, ReturnType = 8, + NeverType = 16, } interface InferenceInfo { typeParameter: TypeParameter; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 3344193d0ce..dcc077d2cd7 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2142,6 +2142,7 @@ declare namespace ts { NakedTypeVariable = 2, MappedType = 4, ReturnType = 8, + NeverType = 16, } interface InferenceInfo { typeParameter: TypeParameter; From d6614447fd0d02f71580fd74e4ad33bb3cc08d56 Mon Sep 17 00:00:00 2001 From: csigs Date: Fri, 10 Nov 2017 17:10:05 +0000 Subject: [PATCH 61/73] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 160 +++++++++--------- .../diagnosticMessages.generated.json.lcl | 160 +++++++++--------- .../diagnosticMessages.generated.json.lcl | 160 +++++++++--------- 3 files changed, 231 insertions(+), 249 deletions(-) diff --git a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl index c59e9c20060..292a20a49bf 100644 --- a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1611,12 +1611,9 @@ - + - - - - + @@ -3726,6 +3723,24 @@ + + + + + + + + + + + + + + + + + + @@ -3957,6 +3972,15 @@ + + + + + + + + + @@ -5202,24 +5226,6 @@ - - - - - - - - - - - - - - - - - - @@ -5247,24 +5253,6 @@ - - - - - - - - - - - - - - - - - - @@ -5283,6 +5271,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -5988,6 +6000,24 @@ + + + + + + + + + + + + + + + + + + @@ -6015,30 +6045,21 @@ - + - - - - + - + - - - - + - + - - - - + @@ -6069,33 +6090,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl index b2ae023f5a4..6ea7ba86fc7 100644 --- a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1611,12 +1611,9 @@ - + - - - - + @@ -3726,6 +3723,24 @@ + + + + + + + + + + + + + + + + + + @@ -3957,6 +3972,15 @@ + + + + + + + + + @@ -5202,24 +5226,6 @@ - - - - - - - - - - - - - - - - - - @@ -5247,24 +5253,6 @@ - - - - - - - - - - - - - - - - - - @@ -5283,6 +5271,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -5988,6 +6000,24 @@ + + + + + + + + + + + + + + + + + + @@ -6015,30 +6045,21 @@ - + - - - - + - + - - - - + - + - - - - + @@ -6069,33 +6090,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl index 2693d7cce27..80c5f4e15d2 100644 --- a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1611,12 +1611,9 @@ - + - - - - + @@ -3726,6 +3723,24 @@ + + + + + + + + + + + + + + + + + + @@ -3957,6 +3972,15 @@ + + + + + + + + + @@ -5202,24 +5226,6 @@ - - - - - - - - - - - - - - - - - - @@ -5247,24 +5253,6 @@ - - - - - - - - - - - - - - - - - - @@ -5283,6 +5271,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -5988,6 +6000,24 @@ + + + + + + + + + + + + + + + + + + @@ -6015,30 +6045,21 @@ - + - - - - + - + - - - - + - + - - - - + @@ -6069,33 +6090,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - From 5ffcc421696a11e3db9398629d84fcfb4305826b Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 10 Nov 2017 09:34:20 -0800 Subject: [PATCH 62/73] Simplify setting constEnumOnlyModule (#19735) --- src/compiler/binder.ts | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 4e89abde780..a0146740678 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1570,7 +1570,7 @@ namespace ts { else { let pattern: Pattern | undefined; if (node.name.kind === SyntaxKind.StringLiteral) { - const text = (node.name).text; + const { text } = node.name; if (hasZeroOrOneAsteriskCharacter(text)) { pattern = tryParsePattern(text); } @@ -1589,22 +1589,13 @@ namespace ts { else { const state = declareModuleSymbol(node); if (state !== ModuleInstanceState.NonInstantiated) { - if (node.symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum)) { - // if module was already merged with some function, class or non-const enum - // treat is a non-const-enum-only - node.symbol.constEnumOnlyModule = false; - } - else { - const currentModuleIsConstEnumOnly = state === ModuleInstanceState.ConstEnumOnly; - if (node.symbol.constEnumOnlyModule === undefined) { - // non-merged case - use the current state - node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly; - } - else { - // merged case: module is const enum only if all its pieces are non-instantiated or const enum - node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly; - } - } + const { symbol } = node; + // if module was already merged with some function, class or non-const enum, treat it as non-const-enum-only + symbol.constEnumOnlyModule = (!(symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum))) + // Current must be `const enum` only + && state === ModuleInstanceState.ConstEnumOnly + // Can't have been set to 'false' in a previous merged symbol. ('undefined' OK) + && symbol.constEnumOnlyModule !== false; } } } From 0d5800a17bc0ed88094b5dc3e8190128f4f71446 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 10 Nov 2017 09:37:06 -0800 Subject: [PATCH 63/73] Address PR comments --- src/harness/externalCompileRunner.ts | 62 +++++++++++++++++----------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/src/harness/externalCompileRunner.ts b/src/harness/externalCompileRunner.ts index ec8acf4872e..5730c5c3c83 100644 --- a/src/harness/externalCompileRunner.ts +++ b/src/harness/externalCompileRunner.ts @@ -2,9 +2,16 @@ /// const fs = require("fs"); const path = require("path"); + +interface ExecResult { + stdout: Buffer; + stderr: Buffer; + status: number; +} + abstract class ExternalCompileRunnerBase extends RunnerBase { abstract testDir: string; - abstract report(result: any, cwd: string): string; + abstract report(result: ExecResult, cwd: string): string; enumerateTestFiles() { return Harness.IO.getDirectories(this.testDir); } @@ -24,8 +31,6 @@ abstract class ExternalCompileRunnerBase extends RunnerBase { private runTest(directoryName: string) { describe(directoryName, () => { const cp = require("child_process"); - const path = require("path"); - const fs = require("fs"); it("should build successfully", () => { const cwd = path.join(__dirname, "../../", this.testDir, directoryName); @@ -51,7 +56,7 @@ class UserCodeRunner extends ExternalCompileRunnerBase { kind(): TestRunnerKind { return "user"; } - report(result: any) { + report(result: ExecResult) { // tslint:disable-next-line:no-null-keyword return result.status === 0 && !result.stdout.length && !result.stderr.length ? null : `Exit Code: ${result.status} Standard output: @@ -69,9 +74,9 @@ class DefinitelyTypedRunner extends ExternalCompileRunnerBase { kind(): TestRunnerKind { return "dt"; } - report(result: any, cwd: string) { - const stdout = filterExpectedErrors(result.stdout.toString(), cwd) - const stderr = result.stderr.toString() + report(result: ExecResult, cwd: string) { + const stdout = removeExpectedErrors(result.stdout.toString(), cwd); + const stderr = result.stderr.toString(); // tslint:disable-next-line:no-null-keyword return !stdout.length && !stderr.length ? null : `Exit Code: ${result.status} Standard output: @@ -83,29 +88,40 @@ ${stderr.replace(/\r\n/g, "\n")}`; } } -function filterExpectedErrors(errors: string, cwd: string): string { - return breaks(errors.split("\n"), s => /^\w+/.test(s)).filter(isExpectedError(cwd)).map(lines => lines.join("\n")).join("\n"); +function removeExpectedErrors(errors: string, cwd: string): string { + return ts.flatten(splitBy(errors.split("\n"), s => /^\S+/.test(s)).filter(isUnexpectedError(cwd))).join("\n"); } -function isExpectedError(cwd: string) { +/** + * Returns true if the line that caused the error contains '$ExpectError', + * or if the line before that one contains '$ExpectError'. + * '$ExpectError' is a marker used in Definitely Typed tests, + * meaning that the error should not contribute toward our error baslines. + */ +function isUnexpectedError(cwd: string) { return (error: string[]) => { - if (error.length === 0) { - return true; - } + ts.Debug.assertGreaterThanOrEqual(error.length, 1); const match = error[0].match(/(.+\.ts)\((\d+),\d+\): error TS/); if (!match) { return true; } - const errlines = fs.readFileSync(path.join(cwd, match[1]), { encoding: "utf8" }).split("\n"); - const index = parseInt(match[2]); - const errline = index < errlines.length ? errlines[index] : ""; - const prevline = index - 1 < errlines.length && index > 0 ? errlines[index - 1] : ""; - if (errline.indexOf("$ExpectError") > -1 || prevline.indexOf("$ExpectError") > -1) { - return false; - } - return true; - } + const [, errorFile, lineNumberString] = match; + const lines = fs.readFileSync(path.join(cwd, errorFile), { encoding: "utf8" }).split("\n"); + const lineNumber = parseInt(lineNumberString); + ts.Debug.assertGreaterThanOrEqual(lineNumber, 0); + ts.Debug.assertLessThan(lineNumber, lines.length); + const previousLine = lineNumber - 1 > 0 ? lines[lineNumber - 1] : ""; + return lines[lineNumber].indexOf("$ExpectError") === -1 && previousLine.indexOf("$ExpectError") === -1; + }; } -function breaks(xs: T[], isStart: (T: any) => boolean): T[][] { +/** + * Split an array into multiple arrays whenever `isStart` returns true. + * @example + * splitBy([1,2,3,4,5,6], isOdd) + * ==> [[1, 2], [3, 4], [5, 6]] + * where + * const isOdd = n => !!(n % 2) + */ +function splitBy(xs: T[], isStart: (x: T) => boolean): T[][] { const result = []; let group: T[] = []; for (const x of xs) { From 5fff71742b019be600b5bfe4c60e03afc73fe594 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 10 Nov 2017 10:11:44 -0800 Subject: [PATCH 64/73] Use ts.stringContains instead of String.indexOf --- src/harness/externalCompileRunner.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/harness/externalCompileRunner.ts b/src/harness/externalCompileRunner.ts index 5730c5c3c83..33803752f94 100644 --- a/src/harness/externalCompileRunner.ts +++ b/src/harness/externalCompileRunner.ts @@ -110,7 +110,7 @@ function isUnexpectedError(cwd: string) { ts.Debug.assertGreaterThanOrEqual(lineNumber, 0); ts.Debug.assertLessThan(lineNumber, lines.length); const previousLine = lineNumber - 1 > 0 ? lines[lineNumber - 1] : ""; - return lines[lineNumber].indexOf("$ExpectError") === -1 && previousLine.indexOf("$ExpectError") === -1; + return !ts.stringContains(lines[lineNumber], "$ExpectError") && !ts.stringContains(previousLine, "$ExpectError"); }; } /** From 06dd3f246f56c763d2df0eb8bcdccdb55cca869a Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 10 Nov 2017 12:55:07 -0800 Subject: [PATCH 65/73] Fail fast on synthetic nodes in services (#19894) --- src/services/services.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/services/services.ts b/src/services/services.ts index 06358d3a720..95e23a708a3 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -62,39 +62,52 @@ namespace ts { this.kind = kind; } + private assertHasRealPosition(message?: string) { + // tslint:disable-next-line:debug-assert + Debug.assert(!positionIsSynthesized(this.pos) && !positionIsSynthesized(this.end), message || "Node must have a real position for this operation"); + } + public getSourceFile(): SourceFile { return getSourceFileOfNode(this); } public getStart(sourceFile?: SourceFileLike, includeJsDocComment?: boolean): number { + this.assertHasRealPosition(); return getTokenPosOfNode(this, sourceFile, includeJsDocComment); } public getFullStart(): number { + this.assertHasRealPosition(); return this.pos; } public getEnd(): number { + this.assertHasRealPosition(); return this.end; } public getWidth(sourceFile?: SourceFile): number { + this.assertHasRealPosition(); return this.getEnd() - this.getStart(sourceFile); } public getFullWidth(): number { + this.assertHasRealPosition(); return this.end - this.pos; } public getLeadingTriviaWidth(sourceFile?: SourceFile): number { + this.assertHasRealPosition(); return this.getStart(sourceFile) - this.pos; } public getFullText(sourceFile?: SourceFile): string { + this.assertHasRealPosition(); return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end); } public getText(sourceFile?: SourceFile): string { + this.assertHasRealPosition(); if (!sourceFile) { sourceFile = this.getSourceFile(); } @@ -183,21 +196,25 @@ namespace ts { } public getChildCount(sourceFile?: SourceFile): number { + this.assertHasRealPosition(); if (!this._children) this.createChildren(sourceFile); return this._children.length; } public getChildAt(index: number, sourceFile?: SourceFile): Node { + this.assertHasRealPosition(); if (!this._children) this.createChildren(sourceFile); return this._children[index]; } public getChildren(sourceFile?: SourceFileLike): Node[] { + this.assertHasRealPosition("Node without a real position cannot be scanned and thus has no token nodes - use forEachChild and collect the result if that's fine"); if (!this._children) this.createChildren(sourceFile); return this._children; } public getFirstToken(sourceFile?: SourceFile): Node { + this.assertHasRealPosition(); const children = this.getChildren(sourceFile); if (!children.length) { return undefined; @@ -210,6 +227,7 @@ namespace ts { } public getLastToken(sourceFile?: SourceFile): Node { + this.assertHasRealPosition(); const children = this.getChildren(sourceFile); const child = lastOrUndefined(children); From 1579f2f7bf1d6b5d1716876ad3b2d41f4f4b9842 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 14 Jul 2017 16:26:37 -0700 Subject: [PATCH 66/73] Add 'scripthost' to 'lib' for the 'generate-spec' target. --- Jakefile.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Jakefile.js b/Jakefile.js index c2d0717641f..4f39d6af5c6 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -731,7 +731,10 @@ compileFile(word2mdJs, [word2mdTs], [word2mdTs], [], - /*useBuiltCompiler*/ false); + /*useBuiltCompiler*/ false, + { + lib: "scripthost,es5" + }); // The generated spec.md; built for the 'generate-spec' task file(specMd, [word2mdJs, specWord], function () { From 7d5f5fd5556339311b2bf41de9edb92d1a53585c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 10 Nov 2017 13:13:21 -0800 Subject: [PATCH 67/73] Make comparable relationship bidirectional for primitive types --- src/compiler/checker.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a9aaa77fa74..19cc2351e39 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8907,7 +8907,9 @@ namespace ts { if (target.flags & TypeFlags.StringOrNumberLiteral && target.flags & TypeFlags.FreshLiteral) { target = (target).regularType; } - if (source === target || relation !== identityRelation && isSimpleTypeRelatedTo(source, target, relation)) { + if (source === target || + relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) || + relation !== identityRelation && isSimpleTypeRelatedTo(source, target, relation)) { return true; } if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) { @@ -9050,7 +9052,8 @@ namespace ts { return isIdenticalTo(source, target); } - if (isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True; + if (relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) || + isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True; if (isObjectLiteralType(source) && source.flags & TypeFlags.FreshLiteral) { if (hasExcessProperties(source, target, reportErrors)) { From d15926d9c7bdef8efc4c671914777304695e316f Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 10 Nov 2017 13:13:32 -0800 Subject: [PATCH 68/73] Add test --- .../reference/independentPropertyVariance.js | 13 +++++++++++++ .../independentPropertyVariance.symbols | 17 +++++++++++++++++ .../independentPropertyVariance.types | 18 ++++++++++++++++++ .../comparable/independentPropertyVariance.ts | 8 ++++++++ 4 files changed, 56 insertions(+) create mode 100644 tests/baselines/reference/independentPropertyVariance.js create mode 100644 tests/baselines/reference/independentPropertyVariance.symbols create mode 100644 tests/baselines/reference/independentPropertyVariance.types create mode 100644 tests/cases/conformance/types/typeRelationships/comparable/independentPropertyVariance.ts diff --git a/tests/baselines/reference/independentPropertyVariance.js b/tests/baselines/reference/independentPropertyVariance.js new file mode 100644 index 00000000000..612877bd973 --- /dev/null +++ b/tests/baselines/reference/independentPropertyVariance.js @@ -0,0 +1,13 @@ +//// [independentPropertyVariance.ts] +// Verify that properties can vary idependently in comparable relationship + +declare const x: { a: 1, b: string }; +declare const y: { a: number, b: 'a' }; + +x === y; + + +//// [independentPropertyVariance.js] +"use strict"; +// Verify that properties can vary idependently in comparable relationship +x === y; diff --git a/tests/baselines/reference/independentPropertyVariance.symbols b/tests/baselines/reference/independentPropertyVariance.symbols new file mode 100644 index 00000000000..19c691e6348 --- /dev/null +++ b/tests/baselines/reference/independentPropertyVariance.symbols @@ -0,0 +1,17 @@ +=== tests/cases/conformance/types/typeRelationships/comparable/independentPropertyVariance.ts === +// Verify that properties can vary idependently in comparable relationship + +declare const x: { a: 1, b: string }; +>x : Symbol(x, Decl(independentPropertyVariance.ts, 2, 13)) +>a : Symbol(a, Decl(independentPropertyVariance.ts, 2, 18)) +>b : Symbol(b, Decl(independentPropertyVariance.ts, 2, 24)) + +declare const y: { a: number, b: 'a' }; +>y : Symbol(y, Decl(independentPropertyVariance.ts, 3, 13)) +>a : Symbol(a, Decl(independentPropertyVariance.ts, 3, 18)) +>b : Symbol(b, Decl(independentPropertyVariance.ts, 3, 29)) + +x === y; +>x : Symbol(x, Decl(independentPropertyVariance.ts, 2, 13)) +>y : Symbol(y, Decl(independentPropertyVariance.ts, 3, 13)) + diff --git a/tests/baselines/reference/independentPropertyVariance.types b/tests/baselines/reference/independentPropertyVariance.types new file mode 100644 index 00000000000..cb5261a2114 --- /dev/null +++ b/tests/baselines/reference/independentPropertyVariance.types @@ -0,0 +1,18 @@ +=== tests/cases/conformance/types/typeRelationships/comparable/independentPropertyVariance.ts === +// Verify that properties can vary idependently in comparable relationship + +declare const x: { a: 1, b: string }; +>x : { a: 1; b: string; } +>a : 1 +>b : string + +declare const y: { a: number, b: 'a' }; +>y : { a: number; b: "a"; } +>a : number +>b : "a" + +x === y; +>x === y : boolean +>x : { a: 1; b: string; } +>y : { a: number; b: "a"; } + diff --git a/tests/cases/conformance/types/typeRelationships/comparable/independentPropertyVariance.ts b/tests/cases/conformance/types/typeRelationships/comparable/independentPropertyVariance.ts new file mode 100644 index 00000000000..9f71a0c656d --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/comparable/independentPropertyVariance.ts @@ -0,0 +1,8 @@ +// @strict: true + +// Verify that properties can vary idependently in comparable relationship + +declare const x: { a: 1, b: string }; +declare const y: { a: number, b: 'a' }; + +x === y; From 16b68ff25b538bb233a8e7f3dd8092c91bf9f3c5 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 10 Nov 2017 13:46:51 -0800 Subject: [PATCH 69/73] Fix typo --- tests/baselines/reference/independentPropertyVariance.js | 4 ++-- tests/baselines/reference/independentPropertyVariance.symbols | 2 +- tests/baselines/reference/independentPropertyVariance.types | 2 +- .../comparable/independentPropertyVariance.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/baselines/reference/independentPropertyVariance.js b/tests/baselines/reference/independentPropertyVariance.js index 612877bd973..2439d8140fa 100644 --- a/tests/baselines/reference/independentPropertyVariance.js +++ b/tests/baselines/reference/independentPropertyVariance.js @@ -1,5 +1,5 @@ //// [independentPropertyVariance.ts] -// Verify that properties can vary idependently in comparable relationship +// Verify that properties can vary independently in comparable relationship declare const x: { a: 1, b: string }; declare const y: { a: number, b: 'a' }; @@ -9,5 +9,5 @@ x === y; //// [independentPropertyVariance.js] "use strict"; -// Verify that properties can vary idependently in comparable relationship +// Verify that properties can vary independently in comparable relationship x === y; diff --git a/tests/baselines/reference/independentPropertyVariance.symbols b/tests/baselines/reference/independentPropertyVariance.symbols index 19c691e6348..cf503476008 100644 --- a/tests/baselines/reference/independentPropertyVariance.symbols +++ b/tests/baselines/reference/independentPropertyVariance.symbols @@ -1,5 +1,5 @@ === tests/cases/conformance/types/typeRelationships/comparable/independentPropertyVariance.ts === -// Verify that properties can vary idependently in comparable relationship +// Verify that properties can vary independently in comparable relationship declare const x: { a: 1, b: string }; >x : Symbol(x, Decl(independentPropertyVariance.ts, 2, 13)) diff --git a/tests/baselines/reference/independentPropertyVariance.types b/tests/baselines/reference/independentPropertyVariance.types index cb5261a2114..d2808166e01 100644 --- a/tests/baselines/reference/independentPropertyVariance.types +++ b/tests/baselines/reference/independentPropertyVariance.types @@ -1,5 +1,5 @@ === tests/cases/conformance/types/typeRelationships/comparable/independentPropertyVariance.ts === -// Verify that properties can vary idependently in comparable relationship +// Verify that properties can vary independently in comparable relationship declare const x: { a: 1, b: string }; >x : { a: 1; b: string; } diff --git a/tests/cases/conformance/types/typeRelationships/comparable/independentPropertyVariance.ts b/tests/cases/conformance/types/typeRelationships/comparable/independentPropertyVariance.ts index 9f71a0c656d..cec30104c49 100644 --- a/tests/cases/conformance/types/typeRelationships/comparable/independentPropertyVariance.ts +++ b/tests/cases/conformance/types/typeRelationships/comparable/independentPropertyVariance.ts @@ -1,6 +1,6 @@ // @strict: true -// Verify that properties can vary idependently in comparable relationship +// Verify that properties can vary independently in comparable relationship declare const x: { a: 1, b: string }; declare const y: { a: number, b: 'a' }; From c82c6f21cb0305ec1dc18a6118895444b05489d1 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 10 Nov 2017 14:03:41 -0800 Subject: [PATCH 70/73] Ensure that enum member value is computed before using it Fixes #19898 --- src/compiler/checker.ts | 2 +- src/harness/unittests/tscWatchMode.ts | 30 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a9aaa77fa74..664d93d57ed 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22412,7 +22412,7 @@ namespace ts { const declaration = memberSymbol.valueDeclaration; if (declaration !== member) { if (isBlockScopedNameDeclaredBeforeUse(declaration, member)) { - return getNodeLinks(declaration).enumMemberValue; + return getEnumMemberValue(declaration as EnumMember); } error(expr, Diagnostics.A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums); return 0; diff --git a/src/harness/unittests/tscWatchMode.ts b/src/harness/unittests/tscWatchMode.ts index fc80a6f39ef..4e2d63cec90 100644 --- a/src/harness/unittests/tscWatchMode.ts +++ b/src/harness/unittests/tscWatchMode.ts @@ -1616,6 +1616,36 @@ namespace ts.tscWatch { return files.slice(0, 2); } }); + + it("Elides const enums correctly in incremental compilation", () => { + const currentDirectory = "/user/someone/projects/myproject"; + const file1: FileOrFolder = { + path: `${currentDirectory}/file1.ts`, + content: "export const enum E1 { V = 1 }" + }; + const file2: FileOrFolder = { + path: `${currentDirectory}/file2.ts`, + content: `import { E1 } from "./file1"; export const enum E2 { V = E1.V }` + }; + const file3: FileOrFolder = { + path: `${currentDirectory}/file3.ts`, + content: `import { E2 } from "./file2"; const v: E2 = E2.V;` + }; + const strictAndEsModule = `"use strict";\nexports.__esModule = true;\n`; + verifyEmittedFileContents("\n", [file3, file2, file1], [ + `${strictAndEsModule}var v = 1 /* V */;\n`, + strictAndEsModule, + strictAndEsModule + ], modifyFiles); + + function modifyFiles(files: FileOrFolderEmit[], emittedFiles: EmittedFile[]) { + files[0].content += `function foo2() { return 2; }`; + emittedFiles[0].content += `function foo2() { return 2; }\n`; + emittedFiles[1].shouldBeWritten = false; + emittedFiles[2].shouldBeWritten = false; + return [files[0]]; + } + }); }); describe("tsc-watch module resolution caching", () => { From 19b26c564cf18a3a76d00204d8fa92979f20e1f9 Mon Sep 17 00:00:00 2001 From: csigs Date: Fri, 10 Nov 2017 23:10:42 +0000 Subject: [PATCH 71/73] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 160 +++++++++--------- .../diagnosticMessages.generated.json.lcl | 160 +++++++++--------- .../diagnosticMessages.generated.json.lcl | 160 +++++++++--------- .../diagnosticMessages.generated.json.lcl | 160 +++++++++--------- .../diagnosticMessages.generated.json.lcl | 142 +++++++--------- .../diagnosticMessages.generated.json.lcl | 160 +++++++++--------- 6 files changed, 444 insertions(+), 498 deletions(-) diff --git a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl index 2bf61430d60..803d5940ac2 100644 --- a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1620,12 +1620,9 @@ - + - - - - + @@ -3735,6 +3732,24 @@ + + + + + + + + + + + + + + + + + + @@ -3966,6 +3981,15 @@ + + + + + + + + + @@ -5211,24 +5235,6 @@ - - - - - - - - - - - - - - - - - - @@ -5256,24 +5262,6 @@ - - - - - - - - - - - - - - - - - - @@ -5292,6 +5280,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -5997,6 +6009,24 @@ + + + + + + + + + + + + + + + + + + @@ -6024,30 +6054,21 @@ - + - - - - + - + - - - - + - + - - - - + @@ -6078,33 +6099,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl index 31f3bfdefd5..2e603f114b6 100644 --- a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1611,12 +1611,9 @@ - + - - - - + @@ -3726,6 +3723,24 @@ + + + + + + + + + + + + + + + + + + @@ -3957,6 +3972,15 @@ + + + + + + + + + @@ -5202,24 +5226,6 @@ - - - - - - - - - - - - - - - - - - @@ -5247,24 +5253,6 @@ - - - - - - - - - - - - - - - - - - @@ -5283,6 +5271,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -5988,6 +6000,24 @@ + + + + + + + + + + + + + + + + + + @@ -6015,30 +6045,21 @@ - + - - - - + - + - - - - + - + - - - - + @@ -6069,33 +6090,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl index b9d115872b6..0badf531a75 100644 --- a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1598,12 +1598,9 @@ - + - - - - + @@ -3707,6 +3704,24 @@ + + + + + + + + + + + + + + + + + + @@ -3938,6 +3953,15 @@ + + + + + + + + + @@ -5183,24 +5207,6 @@ - - - - - - - - - - - - - - - - - - @@ -5228,24 +5234,6 @@ - - - - - - - - - - - - - - - - - - @@ -5264,6 +5252,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -5963,6 +5975,24 @@ + + + + + + + + + + + + + + + + + + @@ -5990,30 +6020,21 @@ - + - - - - + - + - - - - + - + - - - - + @@ -6044,33 +6065,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl index 1e480ff2a08..7677920dd1d 100644 --- a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1598,12 +1598,9 @@ - + - - - - + @@ -3707,6 +3704,24 @@ + + + + + + + + + + + + + + + + + + @@ -3938,6 +3953,15 @@ + + + + + + + + + @@ -5183,24 +5207,6 @@ - - - - - - - - - - - - - - - - - - @@ -5228,24 +5234,6 @@ - - - - - - - - - - - - - - - - - - @@ -5264,6 +5252,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -5963,6 +5975,24 @@ + + + + + + + + + + + + + + + + + + @@ -5990,30 +6020,21 @@ - + - - - - + - + - - - - + - + - - - - + @@ -6044,33 +6065,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl index bd78324f196..b71915fbd67 100644 --- a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1610,12 +1610,9 @@ - + - - - - + @@ -3728,12 +3725,18 @@ + + + + + + @@ -3971,6 +3974,9 @@ + + + @@ -5219,24 +5225,6 @@ - - - - - - - - - - - - - - - - - - @@ -5264,24 +5252,6 @@ - - - - - - - - - - - - - - - - - - @@ -5300,6 +5270,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -6005,6 +5999,24 @@ + + + + + + + + + + + + + + + + + + @@ -6032,30 +6044,21 @@ - + - - - - + - + - - - - + - + - - - - + @@ -6086,33 +6089,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 0eafa4da0b2..6c92a1c0bd1 100644 --- a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1604,12 +1604,9 @@ - + - - - - + @@ -3719,6 +3716,24 @@ + + + + + + + + + + + + + + + + + + @@ -3950,6 +3965,15 @@ + + + + + + + + + @@ -5195,24 +5219,6 @@ - - - - - - - - - - - - - - - - - - @@ -5240,24 +5246,6 @@ - - - - - - - - - - - - - - - - - - @@ -5276,6 +5264,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -5981,6 +5993,24 @@ + + + + + + + + + + + + + + + + + + @@ -6008,30 +6038,21 @@ - + - - - - + - + - - - - + - + - - - - + @@ -6062,33 +6083,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - From 59fca7fc30bfbcdde8d5b3e544bdf09da5fa9e9a Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 10 Nov 2017 16:26:16 -0800 Subject: [PATCH 72/73] Fix crash when running tsc with -diagnostics --- src/compiler/performance.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/performance.ts b/src/compiler/performance.ts index 225b34de9cf..104148ed4ab 100644 --- a/src/compiler/performance.ts +++ b/src/compiler/performance.ts @@ -10,7 +10,8 @@ namespace ts { namespace ts.performance { declare const onProfilerEvent: { (markName: string): void; profiler: boolean; }; - const profilerEvent: (markName: string) => void = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true ? onProfilerEvent : noop; + // NOTE: cannot use ts.noop as core.ts loads after this + const profilerEvent: (markName: string) => void = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true ? onProfilerEvent : () => { /*empty*/ }; let enabled = false; let profilerStart = 0; From cba2e966a37f843150809659e0f762985f988bcd Mon Sep 17 00:00:00 2001 From: csigs Date: Sat, 11 Nov 2017 05:10:06 +0000 Subject: [PATCH 73/73] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 160 +++++++++--------- 1 file changed, 77 insertions(+), 83 deletions(-) diff --git a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl index c00e5a2a2e7..d362101e51f 100644 --- a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1605,12 +1605,9 @@ - + - - - - + @@ -3714,6 +3711,24 @@ + + + + + + + + + + + + + + + + + + @@ -3945,6 +3960,15 @@ + + + + + + + + + @@ -5190,24 +5214,6 @@ - - - - - - - - - - - - - - - - - - @@ -5235,24 +5241,6 @@ - - - - - - - - - - - - - - - - - - @@ -5271,6 +5259,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -5970,6 +5982,24 @@ + + + + + + + + + + + + + + + + + + @@ -5997,30 +6027,21 @@ - + - - - - + - + - - - - + - + - - - - + @@ -6051,33 +6072,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - -