From 456a6bf658b25d559d3eadc9e9ea04aaa5faf7f4 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Sat, 3 Jun 2017 00:10:41 +0200 Subject: [PATCH 001/138] program.getSourceFile[ByPath] can return undefined --- src/compiler/program.ts | 4 ++-- src/compiler/types.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 834122b3584..d481e72b689 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -969,11 +969,11 @@ namespace ts { return emitResult; } - function getSourceFile(fileName: string): SourceFile { + function getSourceFile(fileName: string): SourceFile | undefined { return getSourceFileByPath(toPath(fileName, currentDirectory, getCanonicalFileName)); } - function getSourceFileByPath(path: Path): SourceFile { + function getSourceFileByPath(path: Path): SourceFile | undefined { return filesByName.get(path); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ed1d5dcbe23..da438809d92 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2352,8 +2352,8 @@ namespace ts { export interface ScriptReferenceHost { getCompilerOptions(): CompilerOptions; - getSourceFile(fileName: string): SourceFile; - getSourceFileByPath(path: Path): SourceFile; + getSourceFile(fileName: string): SourceFile | undefined; + getSourceFileByPath(path: Path): SourceFile | undefined; getCurrentDirectory(): string; } From 1f77317b6459641212efcf3fd6b9b6aa005ba968 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sun, 13 Aug 2017 15:12:11 +0800 Subject: [PATCH 002/138] 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 003/138] 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 004/138] Yes space after multiline comments --- src/compiler/comments.ts | 3 +++ .../reference/baseIndexSignatureResolution.js | 2 +- .../reference/commentEmitWithCommentOnLastLine.js | 2 +- tests/baselines/reference/commentOnArrayElement1.js | 2 +- tests/baselines/reference/commentOnArrayElement3.js | 4 ++-- tests/baselines/reference/commentOnBlock1.js | 2 +- .../reference/commentsArgumentsOfCallExpression1.js | 2 +- .../reference/commentsArgumentsOfCallExpression2.js | 6 +++--- tests/baselines/reference/commentsCommentParsing.js | 10 +++++----- tests/baselines/reference/commentsFunction.js | 4 ++-- .../reference/commentsOnPropertyOfObjectLiteral1.js | 2 +- tests/baselines/reference/concatError.js | 2 +- tests/baselines/reference/parserSkippedTokens10.js | 2 +- .../recursivelySpecializedConstructorDeclaration.js | 2 +- tests/baselines/reference/scannerS7.4_A2_T2.js | 2 +- 15 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index b936c0655e1..bb8ec9bf3e7 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -274,6 +274,9 @@ namespace ts { if (hasTrailingNewLine) { writer.writeLine(); } + else if (_kind === SyntaxKind.MultiLineCommentTrivia) { + writer.write(" "); + } } function emitLeadingCommentsOfPosition(pos: number) { diff --git a/tests/baselines/reference/baseIndexSignatureResolution.js b/tests/baselines/reference/baseIndexSignatureResolution.js index 3fdeecf78f6..4053e588e44 100644 --- a/tests/baselines/reference/baseIndexSignatureResolution.js +++ b/tests/baselines/reference/baseIndexSignatureResolution.js @@ -59,4 +59,4 @@ interface B extends A { } var b: B = null; var z: Derived = b.foo(); -*/ +*/ diff --git a/tests/baselines/reference/commentEmitWithCommentOnLastLine.js b/tests/baselines/reference/commentEmitWithCommentOnLastLine.js index 077286a7364..ffd4addb264 100644 --- a/tests/baselines/reference/commentEmitWithCommentOnLastLine.js +++ b/tests/baselines/reference/commentEmitWithCommentOnLastLine.js @@ -8,4 +8,4 @@ var bar; var x; /* var bar; -*/ +*/ diff --git a/tests/baselines/reference/commentOnArrayElement1.js b/tests/baselines/reference/commentOnArrayElement1.js index c93cf634096..960df336dbb 100644 --- a/tests/baselines/reference/commentOnArrayElement1.js +++ b/tests/baselines/reference/commentOnArrayElement1.js @@ -11,7 +11,7 @@ var array = [ var array = [ /* element 1*/ 1 - /* end of element 1 */, + /* end of element 1 */ , 2 /* end of element 2 */ ]; diff --git a/tests/baselines/reference/commentOnArrayElement3.js b/tests/baselines/reference/commentOnArrayElement3.js index f19ef5d6050..e31f8adf26a 100644 --- a/tests/baselines/reference/commentOnArrayElement3.js +++ b/tests/baselines/reference/commentOnArrayElement3.js @@ -12,8 +12,8 @@ var array = [ var array = [ /* element 1*/ 1 - /* end of element 1 */, + /* end of element 1 */ , 2 - /* end of element 2 */, + /* end of element 2 */ , , ]; diff --git a/tests/baselines/reference/commentOnBlock1.js b/tests/baselines/reference/commentOnBlock1.js index 20df3764b77..ed5437c1f66 100644 --- a/tests/baselines/reference/commentOnBlock1.js +++ b/tests/baselines/reference/commentOnBlock1.js @@ -7,5 +7,5 @@ function f() { //// [commentOnBlock1.js] // asdf function f() { - /*asdf*/{ } + /*asdf*/ { } } diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression1.js b/tests/baselines/reference/commentsArgumentsOfCallExpression1.js index f32e0bb8098..4e6d693c5c2 100644 --- a/tests/baselines/reference/commentsArgumentsOfCallExpression1.js +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression1.js @@ -29,4 +29,4 @@ function () { }); foo(/*c7*/ function () { }); foo( /*c7*/ -/*c8*/function () { }); +/*c8*/ function () { }); diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression2.js b/tests/baselines/reference/commentsArgumentsOfCallExpression2.js index 1e1079a4d22..f89e67ef3d8 100644 --- a/tests/baselines/reference/commentsArgumentsOfCallExpression2.js +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression2.js @@ -17,7 +17,7 @@ foo(/*c2*/ 1, /*d2*/ 1 + 2, /*e1*/ a + b); foo(/*c3*/ function () { }, /*d2*/ function () { }, /*e2*/ a + /*e3*/ b); foo(/*c3*/ function () { }, /*d3*/ function () { }, /*e3*/ (a + b)); foo( -/*c4*/function () { }, -/*d4*/function () { }, +/*c4*/ function () { }, +/*d4*/ function () { }, /*e4*/ -/*e5*/"hello"); +/*e5*/ "hello"); diff --git a/tests/baselines/reference/commentsCommentParsing.js b/tests/baselines/reference/commentsCommentParsing.js index c39bf05e556..889067a3c05 100644 --- a/tests/baselines/reference/commentsCommentParsing.js +++ b/tests/baselines/reference/commentsCommentParsing.js @@ -178,7 +178,7 @@ jsDocMultiLine(); *New line1 *New Line2*/ /** Shoul mege this line as well -* and this too*//** Another this one too*/ +* and this too*/ /** Another this one too*/ function jsDocMultiLineMerge() { } jsDocMultiLineMerge(); @@ -188,23 +188,23 @@ function jsDocMixedComments1() { } jsDocMixedComments1(); /// Triple slash comment -/** jsdoc comment *//*** another jsDocComment*/ +/** jsdoc comment */ /*** another jsDocComment*/ function jsDocMixedComments2() { } jsDocMixedComments2(); -/** jsdoc comment *//*** another jsDocComment*/ +/** jsdoc comment */ /*** another jsDocComment*/ /// Triple slash comment function jsDocMixedComments3() { } jsDocMixedComments3(); -/** jsdoc comment *//*** another jsDocComment*/ +/** jsdoc comment */ /*** another jsDocComment*/ /// Triple slash comment /// Triple slash comment 2 function jsDocMixedComments4() { } jsDocMixedComments4(); /// Triple slash comment 1 -/** jsdoc comment *//*** another jsDocComment*/ +/** jsdoc comment */ /*** another jsDocComment*/ /// Triple slash comment /// Triple slash comment 2 function jsDocMixedComments5() { diff --git a/tests/baselines/reference/commentsFunction.js b/tests/baselines/reference/commentsFunction.js index a02ffb3b364..ad31aa47b91 100644 --- a/tests/baselines/reference/commentsFunction.js +++ b/tests/baselines/reference/commentsFunction.js @@ -86,8 +86,8 @@ function blah3(a // trailing commen single line ) { } lambdaFoo = function (a, b) { return a * b; }; // This is trailing comment -/*leading comment*/(function () { return 0; }); // Needs to be wrapped in parens to be a valid expression (not declaration) -/*leading comment*/(function () { return 0; }); //trailing comment +/*leading comment*/ (function () { return 0; }); // Needs to be wrapped in parens to be a valid expression (not declaration) +/*leading comment*/ (function () { return 0; }); //trailing comment function blah4(/*1*/ a /*2*/, /*3*/ b /*4*/) { } function foo1() { diff --git a/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js index 39190d9173a..fa7790443ac 100644 --- a/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js +++ b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js @@ -18,7 +18,7 @@ var resolve = { id: /*! @ngInject */ function (details) { return details.id; }, id1: /* c1 */ "hello", id2: - /*! @ngInject */function (details) { return details.id; }, + /*! @ngInject */ function (details) { return details.id; }, id3: /*! @ngInject */ function (details) { return details.id; }, diff --git a/tests/baselines/reference/concatError.js b/tests/baselines/reference/concatError.js index d2b30218e50..67361719702 100644 --- a/tests/baselines/reference/concatError.js +++ b/tests/baselines/reference/concatError.js @@ -56,4 +56,4 @@ var c: C; var cc: C>; c = c.m(cc); -*/ +*/ diff --git a/tests/baselines/reference/parserSkippedTokens10.js b/tests/baselines/reference/parserSkippedTokens10.js index 3af628a2e1e..cfacb2e21bd 100644 --- a/tests/baselines/reference/parserSkippedTokens10.js +++ b/tests/baselines/reference/parserSkippedTokens10.js @@ -5,4 +5,4 @@ //// [parserSkippedTokens10.js] -/*existing trivia*/; +/*existing trivia*/ ; diff --git a/tests/baselines/reference/recursivelySpecializedConstructorDeclaration.js b/tests/baselines/reference/recursivelySpecializedConstructorDeclaration.js index dbf4b6b27d1..beff303c540 100644 --- a/tests/baselines/reference/recursivelySpecializedConstructorDeclaration.js +++ b/tests/baselines/reference/recursivelySpecializedConstructorDeclaration.js @@ -78,4 +78,4 @@ declare module MsPortal.Controls.Base.ItemList { class ViewModel extends ItemValue { } } -*/ +*/ diff --git a/tests/baselines/reference/scannerS7.4_A2_T2.js b/tests/baselines/reference/scannerS7.4_A2_T2.js index 4a446b520ad..9cfc0b03bd8 100644 --- a/tests/baselines/reference/scannerS7.4_A2_T2.js +++ b/tests/baselines/reference/scannerS7.4_A2_T2.js @@ -26,4 +26,4 @@ */ /*CHECK#1/ - + From 405d8cf8ebd3f6c9c2a5f7e19c2a687235ec0a18 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 9 Oct 2017 10:45:50 -0700 Subject: [PATCH 005/138] In getSuggestionForNonexistentSymbol, guard name against undefined --- src/compiler/checker.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a8e18c432a6..738a484d254 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15064,7 +15064,10 @@ namespace ts { function getSuggestionForNonexistentSymbol(location: Node, name: __String, meaning: SymbolFlags): string { const result = resolveNameHelper(location, name, meaning, /*nameNotFoundMessage*/ undefined, name, /*isUse*/ false, (symbols, name, meaning) => { - // `name` from the callback === the outer `name` + // NOTE: `name` from the callback is supposed to === the outer `name`, but is undefined in some cases + if (name === undefined) { + return undefined; + } const symbol = getSymbol(symbols, name, meaning); // Sometimes the symbol is found when location is a return type of a function: `typeof x` and `x` is declared in the body of the function // So the table *contains* `x` but `x` isn't actually in scope. From b75ccb1c49f3ed42e819fd741c8f2655d571a593 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Sun, 22 Oct 2017 23:01:23 +0200 Subject: [PATCH 006/138] accept baselines --- tests/baselines/reference/api/tsserverlibrary.d.ts | 4 ++-- tests/baselines/reference/api/typescript.d.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 62f4f68d148..9769a9b1a7c 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1592,8 +1592,8 @@ declare namespace ts { } interface ScriptReferenceHost { getCompilerOptions(): CompilerOptions; - getSourceFile(fileName: string): SourceFile; - getSourceFileByPath(path: Path): SourceFile; + getSourceFile(fileName: string): SourceFile | undefined; + getSourceFileByPath(path: Path): SourceFile | undefined; getCurrentDirectory(): string; } interface ParseConfigHost { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index c7c8ba88d72..f185ef0daeb 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1592,8 +1592,8 @@ declare namespace ts { } interface ScriptReferenceHost { getCompilerOptions(): CompilerOptions; - getSourceFile(fileName: string): SourceFile; - getSourceFileByPath(path: Path): SourceFile; + getSourceFile(fileName: string): SourceFile | undefined; + getSourceFileByPath(path: Path): SourceFile | undefined; getCurrentDirectory(): string; } interface ParseConfigHost { From 71ab810d9d8f07bda255115893bd37cb2ab71e06 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 24 Oct 2017 13:37:16 -0700 Subject: [PATCH 007/138] Clean up outdated string comparison logic --- src/compiler/core.ts | 125 +++++++++++++++++++++++++++++++++---------- 1 file changed, 98 insertions(+), 27 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 12b8dd2f87e..ddcd8c849e7 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -20,12 +20,6 @@ namespace ts { /* @internal */ namespace ts { - - // More efficient to create a collator once and use its `compare` than to call `a.localeCompare(b)` many times. - export const collator: { compare(a: string, b: string): number } = typeof Intl === "object" && typeof Intl.Collator === "function" ? new Intl.Collator(/*locales*/ undefined, { usage: "sort", sensitivity: "accent" }) : undefined; - // Intl is missing in Safari, and node 0.10 treats "a" as greater than "B". - export const localeCompareIsCorrect = ts.collator && ts.collator.compare("a", "B") < 0; - /** Create a MapLike with good performance. */ function createDictionaryObject(): MapLike { const map = Object.create(/*prototype*/ null); // tslint:disable-line:no-null-keyword @@ -1489,37 +1483,114 @@ namespace ts { return headChain; } - export function compareValues(a: T, b: T): Comparison { - if (a === b) return Comparison.EqualTo; - if (a === undefined) return Comparison.LessThan; - if (b === undefined) return Comparison.GreaterThan; - return a < b ? Comparison.LessThan : Comparison.GreaterThan; + function toComparison(value: number) { + return value < 0 ? Comparison.LessThan : value > 0 ? Comparison.GreaterThan : Comparison.EqualTo; } - export function compareStrings(a: string, b: string, ignoreCase?: boolean): Comparison { + function compareNonNullValues(a: T, b: T): Comparison { + return a < b ? Comparison.LessThan : a > b ? Comparison.GreaterThan : Comparison.EqualTo; + } + + function compareValuesWithCallback(a: T | undefined, b: T | undefined, comparer: (a: T, b: T) => number) { if (a === b) return Comparison.EqualTo; if (a === undefined) return Comparison.LessThan; if (b === undefined) return Comparison.GreaterThan; - if (ignoreCase) { - // Checking if "collator exists indicates that Intl is available. - // We still have to check if "collator.compare" is correct. If it is not, use "String.localeComapre" - if (collator) { - const result = localeCompareIsCorrect ? - collator.compare(a, b) : - a.localeCompare(b, /*locales*/ undefined, { usage: "sort", sensitivity: "accent" }); // accent means a ≠ b, a ≠ á, a = A - return result < 0 ? Comparison.LessThan : result > 0 ? Comparison.GreaterThan : Comparison.EqualTo; - } + return toComparison(comparer(a, b)); + } - a = a.toUpperCase(); - b = b.toUpperCase(); - if (a === b) return Comparison.EqualTo; + export function compareValues(a: T | undefined, b: T | undefined): Comparison { + return compareValuesWithCallback(a, b, compareNonNullValues); + } + + interface StringComparers { + caseSensitive(a: string, b: string): number; + caseInsensitive(a: string, b: string): number; + } + + // Gets string comparers compatible with the current host + function createStringComparers() { + function createIntlComparers(): StringComparers { + // Strings that differ in base, accents/diacritic marks, or case compare as unequal. + // An `undefined` locale uses the default locale of the host. + const caseSensitiveCollator = new Intl.Collator(/*locales*/ undefined, { usage: "sort", sensitivity: "variant" }); + + // Strings that differ in base or accents/diacritic marks compare as unequal. + // An `undefined` locale uses the default locale of the host. + const caseInsensitiveCollator = new Intl.Collator(/*locales*/ undefined, { usage: "sort", sensitivity: "accent" }); + + return { + caseSensitive: (a, b) => caseSensitiveCollator.compare(a, b), + caseInsensitive: (a, b) => caseInsensitiveCollator.compare(a, b) + }; } - return a < b ? Comparison.LessThan : Comparison.GreaterThan; + function createStringLocaleComparers(): StringComparers { + // for case-insensitive comparisons we always map both strings to their + // upper-case form as some unicode characters do not properly round-trip to + // lowercase (such as ẞ). + return { + caseSensitive: (a, b) => a.localeCompare(b), + caseInsensitive: (a, b) => a.toLocaleUpperCase().localeCompare(b.toLocaleUpperCase()) + }; + } + + function createOrdinalComparers(): StringComparers { + // for case-insensitive comparisons we always map both strings to their + // upper-case form as some unicode characters do not properly round-trip to + // lowercase (such as ẞ). + // + // The ordinal comparison cannot properly handle comparison of the Turkish + // (dotted) i and (dotless) ı to the uppercase forms of (dotted) İ and (dotless) I. + // This is best handled by Intl and not supported in the fallback case. + return { + caseSensitive: compareNonNullValues, + caseInsensitive: (a, b) => compareNonNullValues(a.toUpperCase(), b.toUpperCase()) + }; + } + + // If the host supports Intl (ECMA-402), we use Intl for comparisons using the default + // locale. + if (typeof Intl === "object" && typeof Intl.Collator === "function") { + return createIntlComparers(); + } + + // If the host does not support Intl (Safari, Node v0.10), we fall back to localeCompare. + // Node v0.10 provides incorrect results for comparisons using localeCompare, so we must + // verify the implementation. + if (typeof String.prototype.localeCompare === "function" && + typeof String.prototype.toLocaleUpperCase === "function" && + "a".localeCompare("B") < 0) { + return createStringLocaleComparers(); + } + + // fall back to ordinal comparison + return createOrdinalComparers(); } - export function compareStringsCaseInsensitive(a: string, b: string) { - return compareStrings(a, b, /*ignoreCase*/ true); + const stringComparers = createStringComparers(); + + /** + * Performs a case-sensitive comparison between two strings. + * + * If supported by the host, the default locale is used for comparisons. Otherwise, an ordinal + * comparison is used. + */ + export function compareStringsCaseSensitive(a: string | undefined, b: string | undefined) { + return compareValuesWithCallback(a, b, stringComparers.caseSensitive); + } + + /** + * Performs a case-insensitive comparison between two strings. + * + * If supported by the host, the default locale is used for comparisons. Otherwise, an ordinal + * comparison is used. + */ + export function compareStringsCaseInsensitive(a: string | undefined, b: string | undefined) { + return compareValuesWithCallback(a, b, stringComparers.caseInsensitive); + } + + export function compareStrings(a: string | undefined, b: string | undefined, ignoreCase?: boolean): Comparison { + return ignoreCase ? compareStringsCaseInsensitive(a, b) : compareStringsCaseSensitive(a, b); } function getDiagnosticFileName(diagnostic: Diagnostic): string { From 763d17e947fc8bafc66f586e42697128361ae543 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 24 Oct 2017 14:17:29 -0700 Subject: [PATCH 008/138] Manually inline a few cases to reduce repeated 'ignoreCase' conditionals in loops --- src/compiler/core.ts | 10 ++++++---- src/compiler/program.ts | 3 ++- src/services/navigateTo.ts | 5 +---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index ddcd8c849e7..f11ace7f6c4 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1975,8 +1975,9 @@ namespace ts { const aComponents = getNormalizedPathComponents(a, currentDirectory); const bComponents = getNormalizedPathComponents(b, currentDirectory); const sharedLength = Math.min(aComponents.length, bComponents.length); + const stringComparer = ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive; for (let i = 0; i < sharedLength; i++) { - const result = compareStrings(aComponents[i], bComponents[i], ignoreCase); + const result = stringComparer(aComponents[i], bComponents[i]); if (result !== Comparison.EqualTo) { return result; } @@ -1997,8 +1998,9 @@ namespace ts { return false; } + const stringComparer = ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive; for (let i = 0; i < parentComponents.length; i++) { - const result = compareStrings(parentComponents[i], childComponents[i], ignoreCase); + const result = stringComparer(parentComponents[i], childComponents[i]); if (result !== Comparison.EqualTo) { return false; } @@ -2255,7 +2257,7 @@ namespace ts { // If there are no "includes", then just put everything in results[0]. const results: string[][] = includeFileRegexes ? includeFileRegexes.map(() => []) : [[]]; - const comparer = useCaseSensitiveFileNames ? compareStrings : compareStringsCaseInsensitive; + const comparer = useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive; for (const basePath of patterns.basePaths) { visitDirectory(basePath, combinePaths(currentDirectory, basePath), depth); } @@ -2320,7 +2322,7 @@ namespace ts { } // Sort the offsets array using either the literal or canonical path representations. - includeBasePaths.sort(useCaseSensitiveFileNames ? compareStrings : compareStringsCaseInsensitive); + includeBasePaths.sort(useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive); // Iterate over each include base path and include unique base paths that are not a // subpath of an existing base path diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 0ff78a77ecd..e87a4997f13 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1105,7 +1105,8 @@ namespace ts { return compareStrings(file.fileName, getDefaultLibraryFileName(), /*ignoreCase*/ !host.useCaseSensitiveFileNames()) === Comparison.EqualTo; } else { - return forEach(options.lib, libFileName => compareStrings(file.fileName, combinePaths(defaultLibraryPath, libFileName), /*ignoreCase*/ !host.useCaseSensitiveFileNames()) === Comparison.EqualTo); + const stringComparer = host.useCaseSensitiveFileNames() ? compareStringsCaseSensitive : compareStringsCaseInsensitive; + return forEach(options.lib, libFileName => stringComparer(file.fileName, combinePaths(defaultLibraryPath, libFileName)) === Comparison.EqualTo); } } diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index 7fa177b6a30..be2c7b61a7e 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -176,11 +176,8 @@ namespace ts.NavigateTo { function compareNavigateToItems(i1: RawNavigateToItem, i2: RawNavigateToItem): number { // TODO(cyrusn): get the gamut of comparisons that VS already uses here. // Right now we just sort by kind first, and then by name of the item. - // We first sort case insensitively. So "Aaa" will come before "bar". - // Then we sort case sensitively, so "aaa" will come before "Aaa". return i1.matchKind - i2.matchKind || - ts.compareStringsCaseInsensitive(i1.name, i2.name) || - ts.compareStrings(i1.name, i2.name); + ts.compareStringsCaseSensitive(i1.name, i2.name); } function createNavigateToItem(rawItem: RawNavigateToItem): NavigateToItem { From 5f8b392f7df76fea985d9f8ab43ae844b7c2ee77 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 24 Oct 2017 15:50:19 -0700 Subject: [PATCH 009/138] Revert use of Intl/localeCompare for CS comparisons --- src/compiler/core.ts | 120 ++++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 76 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index f11ace7f6c4..7c4139e3e07 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1483,101 +1483,58 @@ namespace ts { return headChain; } - function toComparison(value: number) { - return value < 0 ? Comparison.LessThan : value > 0 ? Comparison.GreaterThan : Comparison.EqualTo; - } - - function compareNonNullValues(a: T, b: T): Comparison { - return a < b ? Comparison.LessThan : a > b ? Comparison.GreaterThan : Comparison.EqualTo; - } - - function compareValuesWithCallback(a: T | undefined, b: T | undefined, comparer: (a: T, b: T) => number) { + export function compareValues(a: T | undefined, b: T | undefined) { if (a === b) return Comparison.EqualTo; if (a === undefined) return Comparison.LessThan; if (b === undefined) return Comparison.GreaterThan; - return toComparison(comparer(a, b)); - } - - export function compareValues(a: T | undefined, b: T | undefined): Comparison { - return compareValuesWithCallback(a, b, compareNonNullValues); - } - - interface StringComparers { - caseSensitive(a: string, b: string): number; - caseInsensitive(a: string, b: string): number; + return a < b ? Comparison.LessThan : Comparison.GreaterThan; } // Gets string comparers compatible with the current host - function createStringComparers() { - function createIntlComparers(): StringComparers { - // Strings that differ in base, accents/diacritic marks, or case compare as unequal. - // An `undefined` locale uses the default locale of the host. - const caseSensitiveCollator = new Intl.Collator(/*locales*/ undefined, { usage: "sort", sensitivity: "variant" }); - + function createCaseInsensitiveStringComparer(): (a: string, b: string) => number { + // If the host supports Intl (ECMA-402), we use Intl for comparisons using the default + // locale: + if (typeof Intl === "object" && typeof Intl.Collator === "function") { // Strings that differ in base or accents/diacritic marks compare as unequal. // An `undefined` locale uses the default locale of the host. - const caseInsensitiveCollator = new Intl.Collator(/*locales*/ undefined, { usage: "sort", sensitivity: "accent" }); - - return { - caseSensitive: (a, b) => caseSensitiveCollator.compare(a, b), - caseInsensitive: (a, b) => caseInsensitiveCollator.compare(a, b) - }; - } - - function createStringLocaleComparers(): StringComparers { - // for case-insensitive comparisons we always map both strings to their - // upper-case form as some unicode characters do not properly round-trip to - // lowercase (such as ẞ). - return { - caseSensitive: (a, b) => a.localeCompare(b), - caseInsensitive: (a, b) => a.toLocaleUpperCase().localeCompare(b.toLocaleUpperCase()) - }; - } - - function createOrdinalComparers(): StringComparers { - // for case-insensitive comparisons we always map both strings to their - // upper-case form as some unicode characters do not properly round-trip to - // lowercase (such as ẞ). // - // The ordinal comparison cannot properly handle comparison of the Turkish - // (dotted) i and (dotless) ı to the uppercase forms of (dotted) İ and (dotless) I. - // This is best handled by Intl and not supported in the fallback case. - return { - caseSensitive: compareNonNullValues, - caseInsensitive: (a, b) => compareNonNullValues(a.toUpperCase(), b.toUpperCase()) - }; + // Intl.Collator.prototype.compare is bound to the collator. See NOTE in + // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare + return new Intl.Collator(/*locales*/ undefined, { usage: "sort", sensitivity: "accent" }).compare; } - // If the host supports Intl (ECMA-402), we use Intl for comparisons using the default - // locale. - if (typeof Intl === "object" && typeof Intl.Collator === "function") { - return createIntlComparers(); - } - - // If the host does not support Intl (Safari, Node v0.10), we fall back to localeCompare. + // If the host does not support Intl, we fall back to localeCompare: + // // Node v0.10 provides incorrect results for comparisons using localeCompare, so we must // verify the implementation. if (typeof String.prototype.localeCompare === "function" && typeof String.prototype.toLocaleUpperCase === "function" && "a".localeCompare("B") < 0) { - return createStringLocaleComparers(); + // for case-insensitive comparisons we always map both strings to their + // upper-case form as some unicode characters do not properly round-trip to + // lowercase (such as ẞ). + return (a, b) => a.toLocaleUpperCase().localeCompare(b.toLocaleUpperCase()); } - // fall back to ordinal comparison - return createOrdinalComparers(); + // Otherwise, fall back to ordinal comparison: + // + // for case-insensitive comparisons we always map both strings to their + // upper-case form as some unicode characters do not properly round-trip to + // lowercase (such as ẞ). + // + // The ordinal comparison cannot properly handle comparison of the Turkish + // (dotted) i and (dotless) ı to the uppercase forms of (dotted) İ and (dotless) I. + // This is best handled by Intl and not supported in the fallback case. + return (a, b) => { + const upperA = a.toUpperCase(); + const upperB = b.toUpperCase(); + return upperA < upperB ? Comparison.LessThan : + upperA > upperB ? Comparison.GreaterThan : + Comparison.EqualTo; + }; } - const stringComparers = createStringComparers(); - - /** - * Performs a case-sensitive comparison between two strings. - * - * If supported by the host, the default locale is used for comparisons. Otherwise, an ordinal - * comparison is used. - */ - export function compareStringsCaseSensitive(a: string | undefined, b: string | undefined) { - return compareValuesWithCallback(a, b, stringComparers.caseSensitive); - } + const caseInsensitiveComparer = createCaseInsensitiveStringComparer(); /** * Performs a case-insensitive comparison between two strings. @@ -1586,7 +1543,18 @@ namespace ts { * comparison is used. */ export function compareStringsCaseInsensitive(a: string | undefined, b: string | undefined) { - return compareValuesWithCallback(a, b, stringComparers.caseInsensitive); + if (a === b) return Comparison.EqualTo; + if (a === undefined) return Comparison.LessThan; + if (b === undefined) return Comparison.GreaterThan; + const result = caseInsensitiveComparer(a, b); + return result < 0 ? Comparison.LessThan : result > 0 ? Comparison.GreaterThan : Comparison.EqualTo; + } + + /** + * Performs a case-sensitive comparison between two strings. + */ + export function compareStringsCaseSensitive(a: string | undefined, b: string | undefined) { + return compareValues(a, b); } export function compareStrings(a: string | undefined, b: string | undefined, ignoreCase?: boolean): Comparison { From dee77ced7c3e19ca8bf16ab0b3b0d382512ca9b4 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 24 Oct 2017 16:14:49 -0700 Subject: [PATCH 010/138] Added 'equateStrings' for string equality comparisons (rather than sorting) --- src/compiler/core.ts | 111 +++++++++++++++++++++++++++++----------- src/compiler/parser.ts | 2 +- src/compiler/program.ts | 6 +-- 3 files changed, 84 insertions(+), 35 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 7c4139e3e07..79a9aa8e019 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1490,17 +1490,60 @@ namespace ts { return a < b ? Comparison.LessThan : Comparison.GreaterThan; } + interface StringCollator { + compare(a: string, b: string): number; + equals(a: string, b: string): boolean; + } + // Gets string comparers compatible with the current host - function createCaseInsensitiveStringComparer(): (a: string, b: string) => number { + function createCaseInsensitiveStringComparers() { + function createIntlStringCollator(): StringCollator { + // Strings that differ in base or accents/diacritic marks compare as unequal. + // An `undefined` locale uses the default locale of the host. + const sortCollator = new Intl.Collator(/*locales*/ undefined, { usage: "sort", sensitivity: "accent" }); + const searchCollator = new Intl.Collator(/*locales*/ undefined, { usage: "search", sensitivity: "accent" }); + return { + // Intl.Collator.prototype.compare is bound to the collator. See NOTE in + // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare + compare: sortCollator.compare, + equals: (a, b) => searchCollator.compare(a, b) === 0 + }; + } + + function createLocaleCompareStringCollator(): StringCollator { + // for case-insensitive comparisons we always map both strings to their + // upper-case form as some unicode characters do not properly round-trip to + // lowercase (such as ẞ). + return { + compare: (a, b) => a.toLocaleUpperCase().localeCompare(b.toLocaleUpperCase()), + equals: (a, b) => a.toLocaleUpperCase() === b.toLocaleUpperCase() + }; + } + + function createOrdinalStringCollator(): StringCollator { + // for case-insensitive comparisons we always map both strings to their + // upper-case form as some unicode characters do not properly round-trip to + // lowercase (such as ẞ). + // + // The ordinal comparison cannot properly handle comparison of the Turkish + // (dotted) i and (dotless) ı to the uppercase forms of (dotted) İ and (dotless) I. + // This is best handled by Intl and not supported in the fallback case. + return { + compare: (a, b) => { + const upperA = a.toUpperCase(); + const upperB = b.toUpperCase(); + return upperA < upperB ? Comparison.LessThan : + upperA > upperB ? Comparison.GreaterThan : + Comparison.EqualTo; + }, + equals: (a, b) => a.toUpperCase() === b.toUpperCase() + }; + } + // If the host supports Intl (ECMA-402), we use Intl for comparisons using the default // locale: if (typeof Intl === "object" && typeof Intl.Collator === "function") { - // Strings that differ in base or accents/diacritic marks compare as unequal. - // An `undefined` locale uses the default locale of the host. - // - // Intl.Collator.prototype.compare is bound to the collator. See NOTE in - // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare - return new Intl.Collator(/*locales*/ undefined, { usage: "sort", sensitivity: "accent" }).compare; + return createIntlStringCollator(); } // If the host does not support Intl, we fall back to localeCompare: @@ -1510,31 +1553,14 @@ namespace ts { if (typeof String.prototype.localeCompare === "function" && typeof String.prototype.toLocaleUpperCase === "function" && "a".localeCompare("B") < 0) { - // for case-insensitive comparisons we always map both strings to their - // upper-case form as some unicode characters do not properly round-trip to - // lowercase (such as ẞ). - return (a, b) => a.toLocaleUpperCase().localeCompare(b.toLocaleUpperCase()); + return createLocaleCompareStringCollator(); } // Otherwise, fall back to ordinal comparison: - // - // for case-insensitive comparisons we always map both strings to their - // upper-case form as some unicode characters do not properly round-trip to - // lowercase (such as ẞ). - // - // The ordinal comparison cannot properly handle comparison of the Turkish - // (dotted) i and (dotless) ı to the uppercase forms of (dotted) İ and (dotless) I. - // This is best handled by Intl and not supported in the fallback case. - return (a, b) => { - const upperA = a.toUpperCase(); - const upperB = b.toUpperCase(); - return upperA < upperB ? Comparison.LessThan : - upperA > upperB ? Comparison.GreaterThan : - Comparison.EqualTo; - }; + return createOrdinalStringCollator(); } - const caseInsensitiveComparer = createCaseInsensitiveStringComparer(); + const caseInsensitiveCollator = createCaseInsensitiveStringComparers(); /** * Performs a case-insensitive comparison between two strings. @@ -1546,7 +1572,7 @@ namespace ts { if (a === b) return Comparison.EqualTo; if (a === undefined) return Comparison.LessThan; if (b === undefined) return Comparison.GreaterThan; - const result = caseInsensitiveComparer(a, b); + const result = caseInsensitiveCollator.compare(a, b); return result < 0 ? Comparison.LessThan : result > 0 ? Comparison.GreaterThan : Comparison.EqualTo; } @@ -1561,6 +1587,30 @@ namespace ts { return ignoreCase ? compareStringsCaseInsensitive(a, b) : compareStringsCaseSensitive(a, b); } + /** + * Performs a case-insensitive equality comparison between two strings. + * + * If supported by the host, the default locale is used for comparisons. Otherwise, an ordinal + * comparison is used. + */ + export function equateStringsCaseInsensitive(a: string | undefined, b: string | undefined) { + return a === b + || a !== undefined + && b !== undefined + && caseInsensitiveCollator.equals(a, b); + } + + /** + * Performs a case-sensitive equality comparison between two strings. + */ + export function equateStringsCaseSensitive(a: string | undefined, b: string | undefined) { + return a === b; + } + + export function equateStrings(a: string | undefined, b: string | undefined, ignoreCase?: boolean) { + return ignoreCase ? equateStringsCaseInsensitive(a, b) : equateStringsCaseSensitive(a, b); + } + function getDiagnosticFileName(diagnostic: Diagnostic): string { return diagnostic.file ? diagnostic.file.fileName : undefined; } @@ -1966,10 +2016,9 @@ namespace ts { return false; } - const stringComparer = ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive; + const stringEqualityComparer = ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive; for (let i = 0; i < parentComponents.length; i++) { - const result = stringComparer(parentComponents[i], childComponents[i]); - if (result !== Comparison.EqualTo) { + if (!stringEqualityComparer(parentComponents[i], childComponents[i])) { return false; } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b27d4811ecb..ef93dfe7d4f 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6069,7 +6069,7 @@ namespace ts { const checkJsDirectiveMatchResult = checkJsDirectiveRegEx.exec(comment); if (checkJsDirectiveMatchResult) { checkJsDirective = { - enabled: compareStrings(checkJsDirectiveMatchResult[1], "@ts-check", /*ignoreCase*/ true) === Comparison.EqualTo, + enabled: equateStrings(checkJsDirectiveMatchResult[1], "@ts-check", /*ignoreCase*/ true), end: range.end, pos: range.pos }; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index e87a4997f13..394dc2a7669 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1102,11 +1102,11 @@ namespace ts { // If '--lib' is not specified, include default library file according to '--target' // otherwise, using options specified in '--lib' instead of '--target' default library file if (!options.lib) { - return compareStrings(file.fileName, getDefaultLibraryFileName(), /*ignoreCase*/ !host.useCaseSensitiveFileNames()) === Comparison.EqualTo; + return equateStrings(file.fileName, getDefaultLibraryFileName(), /*ignoreCase*/ !host.useCaseSensitiveFileNames()); } else { - const stringComparer = host.useCaseSensitiveFileNames() ? compareStringsCaseSensitive : compareStringsCaseInsensitive; - return forEach(options.lib, libFileName => stringComparer(file.fileName, combinePaths(defaultLibraryPath, libFileName)) === Comparison.EqualTo); + const stringEqualityComparer = host.useCaseSensitiveFileNames() ? equateStringsCaseSensitive : equateStringsCaseInsensitive; + return forEach(options.lib, libFileName => stringEqualityComparer(file.fileName, combinePaths(defaultLibraryPath, libFileName))); } } From 7bc3b73ab974afc34af29ac87782fbb2323d1508 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 24 Oct 2017 16:26:11 -0700 Subject: [PATCH 011/138] Clean up existing equality comparisons --- src/compiler/core.ts | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 79a9aa8e019..5c9f23af19a 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -650,13 +650,13 @@ namespace ts { } // TODO: fixme (N^2) - add optional comparer so collection can be sorted before deduplication. - export function deduplicate(array: ReadonlyArray, areEqual?: (a: T, b: T) => boolean): T[] { + export function deduplicate(array: ReadonlyArray, equalityComparer: (a: T, b: T) => boolean = equateValues): T[] { let result: T[]; if (array) { result = []; loop: for (const item of array) { for (const res of result) { - if (areEqual ? areEqual(res, item) : res === item) { + if (equalityComparer(res, item)) { continue loop; } } @@ -666,7 +666,7 @@ namespace ts { return result; } - export function arrayIsEqualTo(array1: ReadonlyArray, array2: ReadonlyArray, equaler?: (a: T, b: T) => boolean): boolean { + export function arrayIsEqualTo(array1: ReadonlyArray, array2: ReadonlyArray, equalityComparer: (a: T, b: T) => boolean = equateValues): boolean { if (!array1 || !array2) { return array1 === array2; } @@ -676,8 +676,7 @@ namespace ts { } for (let i = 0; i < array1.length; i++) { - const equals = equaler ? equaler(array1[i], array2[i]) : array1[i] === array2[i]; - if (!equals) { + if (!equalityComparer(array1[i], array2[i])) { return false; } } @@ -916,6 +915,7 @@ namespace ts { } export type Comparer = (a: T, b: T) => Comparison; + export type EqualityComparer = (a: T, b: T) => boolean; /** * Performs a binary search, finding the index at which 'value' occurs in 'array'. @@ -1124,13 +1124,13 @@ namespace ts { * @param left A map-like whose properties should be compared. * @param right A map-like whose properties should be compared. */ - export function equalOwnProperties(left: MapLike, right: MapLike, equalityComparer?: (left: T, right: T) => boolean) { + export function equalOwnProperties(left: MapLike, right: MapLike, equalityComparer: EqualityComparer = equateValues) { if (left === right) return true; if (!left || !right) return false; for (const key in left) { if (hasOwnProperty.call(left, key)) { if (!hasOwnProperty.call(right, key) === undefined) return false; - if (equalityComparer ? !equalityComparer(left[key], right[key]) : left[key] !== right[key]) return false; + if (!equalityComparer(left[key], right[key])) return false; } } @@ -1483,6 +1483,9 @@ namespace ts { return headChain; } + /** + * Compare two values for their order relative to each other. + */ export function compareValues(a: T | undefined, b: T | undefined) { if (a === b) return Comparison.EqualTo; if (a === undefined) return Comparison.LessThan; @@ -1490,9 +1493,16 @@ namespace ts { return a < b ? Comparison.LessThan : Comparison.GreaterThan; } + /** + * Compare two values for their equality. + */ + export function equateValues(a: T | undefined, b: T | undefined) { + return a === b; + } + interface StringCollator { compare(a: string, b: string): number; - equals(a: string, b: string): boolean; + equate(a: string, b: string): boolean; } // Gets string comparers compatible with the current host @@ -1506,7 +1516,7 @@ namespace ts { // Intl.Collator.prototype.compare is bound to the collator. See NOTE in // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare compare: sortCollator.compare, - equals: (a, b) => searchCollator.compare(a, b) === 0 + equate: (a, b) => searchCollator.compare(a, b) === 0 }; } @@ -1516,7 +1526,7 @@ namespace ts { // lowercase (such as ẞ). return { compare: (a, b) => a.toLocaleUpperCase().localeCompare(b.toLocaleUpperCase()), - equals: (a, b) => a.toLocaleUpperCase() === b.toLocaleUpperCase() + equate: (a, b) => a.toLocaleUpperCase() === b.toLocaleUpperCase() }; } @@ -1536,7 +1546,7 @@ namespace ts { upperA > upperB ? Comparison.GreaterThan : Comparison.EqualTo; }, - equals: (a, b) => a.toUpperCase() === b.toUpperCase() + equate: (a, b) => a.toUpperCase() === b.toUpperCase() }; } @@ -1597,14 +1607,14 @@ namespace ts { return a === b || a !== undefined && b !== undefined - && caseInsensitiveCollator.equals(a, b); + && caseInsensitiveCollator.equate(a, b); } /** * Performs a case-sensitive equality comparison between two strings. */ export function equateStringsCaseSensitive(a: string | undefined, b: string | undefined) { - return a === b; + return equateValues(a, b); } export function equateStrings(a: string | undefined, b: string | undefined, ignoreCase?: boolean) { @@ -1993,9 +2003,9 @@ namespace ts { const aComponents = getNormalizedPathComponents(a, currentDirectory); const bComponents = getNormalizedPathComponents(b, currentDirectory); const sharedLength = Math.min(aComponents.length, bComponents.length); - const stringComparer = ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive; + const comparer = ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive; for (let i = 0; i < sharedLength; i++) { - const result = stringComparer(aComponents[i], bComponents[i]); + const result = comparer(aComponents[i], bComponents[i]); if (result !== Comparison.EqualTo) { return result; } @@ -2016,9 +2026,9 @@ namespace ts { return false; } - const stringEqualityComparer = ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive; + const equalityComparer = ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive; for (let i = 0; i < parentComponents.length; i++) { - if (!stringEqualityComparer(parentComponents[i], childComponents[i])) { + if (!equalityComparer(parentComponents[i], childComponents[i])) { return false; } } From 27d0b9f4fc927d8fd409a7301f4d295363bb9426 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 24 Oct 2017 16:30:23 -0700 Subject: [PATCH 012/138] Minor name change --- src/compiler/core.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 5c9f23af19a..3aea96ef354 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1506,7 +1506,7 @@ namespace ts { } // Gets string comparers compatible with the current host - function createCaseInsensitiveStringComparers() { + function createCaseInsensitiveStringCollator() { function createIntlStringCollator(): StringCollator { // Strings that differ in base or accents/diacritic marks compare as unequal. // An `undefined` locale uses the default locale of the host. @@ -1570,7 +1570,7 @@ namespace ts { return createOrdinalStringCollator(); } - const caseInsensitiveCollator = createCaseInsensitiveStringComparers(); + const caseInsensitiveCollator = createCaseInsensitiveStringCollator(); /** * Performs a case-insensitive comparison between two strings. From 6d4e2a006ffe44657dc9f917551fd598cd28fd73 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 24 Oct 2017 16:36:35 -0700 Subject: [PATCH 013/138] Revert change in navigateTo --- src/services/navigateTo.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index be2c7b61a7e..2647a87ada7 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -176,8 +176,11 @@ namespace ts.NavigateTo { function compareNavigateToItems(i1: RawNavigateToItem, i2: RawNavigateToItem): number { // TODO(cyrusn): get the gamut of comparisons that VS already uses here. // Right now we just sort by kind first, and then by name of the item. + // We first sort case insensitively. So "Aaa" will come before "bar". + // Then we sort case sensitively, so "aaa" will come before "Aaa". return i1.matchKind - i2.matchKind || - ts.compareStringsCaseSensitive(i1.name, i2.name); + compareStringsCaseInsensitive(i1.name, i2.name) || + compareStringsCaseSensitive(i1.name, i2.name); } function createNavigateToItem(rawItem: RawNavigateToItem): NavigateToItem { From 4d7923af00f09bf6cbd2d79fd3c14dcd39ffe965 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 24 Oct 2017 16:37:41 -0700 Subject: [PATCH 014/138] Consistent naming --- src/compiler/program.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 394dc2a7669..bca10eceb67 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1105,8 +1105,8 @@ namespace ts { return equateStrings(file.fileName, getDefaultLibraryFileName(), /*ignoreCase*/ !host.useCaseSensitiveFileNames()); } else { - const stringEqualityComparer = host.useCaseSensitiveFileNames() ? equateStringsCaseSensitive : equateStringsCaseInsensitive; - return forEach(options.lib, libFileName => stringEqualityComparer(file.fileName, combinePaths(defaultLibraryPath, libFileName))); + const equalityComparer = host.useCaseSensitiveFileNames() ? equateStringsCaseSensitive : equateStringsCaseInsensitive; + return forEach(options.lib, libFileName => equalityComparer(file.fileName, combinePaths(defaultLibraryPath, libFileName))); } } From 130c407708993304170a2720966cdddd4d907bd5 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 25 Oct 2017 16:30:19 -0700 Subject: [PATCH 015/138] More control over which collator to use in each situation --- src/compiler/core.ts | 394 ++++++++++++++++-------- src/compiler/parser.ts | 2 +- src/compiler/program.ts | 8 +- src/compiler/utilities.ts | 3 + src/harness/harness.ts | 4 +- src/harness/unittests/compileOnSave.ts | 6 +- src/server/session.ts | 3 +- src/services/navigateTo.ts | 6 +- src/services/navigationBar.ts | 9 +- src/services/refactors/extractSymbol.ts | 4 +- 10 files changed, 296 insertions(+), 143 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 3aea96ef354..3a706a9119d 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1486,140 +1486,288 @@ namespace ts { /** * Compare two values for their order relative to each other. */ - export function compareValues(a: T | undefined, b: T | undefined) { - if (a === b) return Comparison.EqualTo; - if (a === undefined) return Comparison.LessThan; - if (b === undefined) return Comparison.GreaterThan; - return a < b ? Comparison.LessThan : Comparison.GreaterThan; + export function compareValues(a: T, b: T) { + return a === b ? Comparison.EqualTo : + a === undefined ? Comparison.LessThan : + b === undefined ? Comparison.GreaterThan : + a < b ? Comparison.LessThan : + Comparison.GreaterThan; } /** * Compare two values for their equality. */ - export function equateValues(a: T | undefined, b: T | undefined) { + export function equateValues(a: T, b: T) { return a === b; } - interface StringCollator { - compare(a: string, b: string): number; - equate(a: string, b: string): boolean; + export interface StringCollator { + compare(a: string | undefined, b: string | undefined): number; + equate(a: string | undefined, b: string | undefined): boolean; } - // Gets string comparers compatible with the current host - function createCaseInsensitiveStringCollator() { - function createIntlStringCollator(): StringCollator { - // Strings that differ in base or accents/diacritic marks compare as unequal. - // An `undefined` locale uses the default locale of the host. - const sortCollator = new Intl.Collator(/*locales*/ undefined, { usage: "sort", sensitivity: "accent" }); - const searchCollator = new Intl.Collator(/*locales*/ undefined, { usage: "search", sensitivity: "accent" }); - return { + export interface StringCollators { + /** + * Gets a string collator for case-insensitive ordinal comparisons of strings. + * + * Ordinal comparisons are based on the difference between the unicode code points of + * both strings. Characters with multiple unicode representations are considered + * unequal. + * + * Case-insensitive comparisons compare both strings after applying `toUpperCase` to + * each string. + */ + readonly ordinalCaseInsensitive: StringCollator; + + /** + * Gets a string collator for case-sensitive ordinal comparisons of strings. + * + * Ordinal comparisons are based on the difference between the unicode code points of + * both strings. Characters with multiple unicode representations are considered + * unequal. They provide predictable ordering, but place "a" after "B". + */ + readonly ordinalCaseSensitive: StringCollator; + + /** + * Gets or sets a string collator for case-insensitive comparisons of strings in the host default locale. + * + * UI comparisons are based on the sort order of the host default locale. Ordering is not + * predictable between different host locales, but is best for displaying ordered data + * for UI presentation. Characters with multiple unicode representations may be considered + * equal. + * + * Case-insensitive comparisons compare strings that differ in only base characters or + * accents/diacritic marks as unequal. + */ + readonly uiCaseInsensitive: StringCollator; + + /** + * Gets a string collator for case-sensitive comparisons of strings in the host default locale. + * + * UI comparisons are based on the sort order of the host default locale. Ordering is not + * predictable between different host locales, but is best for displaying ordered data + * for UI presentation. Characters with multiple unicode representations may be considered + * equal. + */ + readonly uiCaseSensitive: StringCollator; + + /** + * Gets a string collator for case-insensitive comparisons of strings in an invariant locale. + * + * Invariant comparisons are based on the sort order of an invariant locale ('en-US'). + * They provide predictable ordering, placing "a" before "B". Characters with multiple + * unicode representations may be considered equal. Invariant comparisons are best used + * when interacting with the file system. + * + * Case-insensitive comparisons compare strings that differ in only base characters or + * accents/diacritic marks as unequal. + */ + readonly invariantCaseInsensitive: StringCollator; + + /** + * Gets a string collator for case-sensitive comparisons of strings in an invariant locale. + * + * Invariant comparisons are based on the sort order of an invariant locale ('en-US'). + * They provide predictable ordering, placing "a" before "B". Characters with multiple + * unicode representations may be considered equal. Invariant comparisons are best used + * when interacting with the file system. + */ + readonly invariantCaseSensitive: StringCollator; + + /** + * Gets or sets the locale for UI collators + */ + uiLocale: string | undefined; + + /** + * Creates a `StringCollator` for a specific locale and case sensitivity. + */ + create(locale: string | undefined, caseSensitive: boolean): StringCollator; + + /** + * Gets the ordinal `StringCollator` for the provided case sensitivity. + */ + getOrdinalCollator(caseSensitive: boolean): StringCollator; + + /** + * Gets the UI `StringCollator` for the provided case sensitivity. + */ + getUICollator(caseSensitive: boolean): StringCollator; + + /** + * Gets the invariant `StringCollator` for the provided case sensitivity. + */ + getInvariantCollator(caseSensitive: boolean): StringCollator; + + /** + * Gets a `StringCollator` for comparing code fragments for code generation. + */ + getCodeCollator(caseSensitive: boolean): StringCollator; + + /** + * Gets a `StringCollator` for comparing paths. + */ + getPathCollator(caseSensitive: boolean): StringCollator; + } + + export const StringCollator: StringCollators = (function () { + const invariantLocaleName = "en-US"; // we use en-US for the invariant locale + const create = getStringCollatorFactory(); + const ordinalCS: StringCollator = { + compare: compareValues, + equate: equateValues + }; + const ordinalCI: StringCollator = { + compare: (a, b) => compareValues(toUpperCase(a), toUpperCase(b)), + equate: (a, b) => toUpperCase(a) === toUpperCase(b) + }; + let invariantCI: StringCollator | undefined; + let invariantCS: StringCollator | undefined; + let uiCI: StringCollator | undefined; + let uiCS: StringCollator | undefined; + let uiLocale: string | undefined; + + return { + get ordinalCaseInsensitive() { return ordinalCI; }, + get ordinalCaseSensitive() { return ordinalCS; }, + get uiCaseInsensitive() { return uiCI || (uiCI = create(uiLocale, /*caseInsensitive*/ true)); }, + get uiCaseSensitive() { return uiCS || (uiCS = create(uiLocale, /*caseInsensitive*/ false)); }, + get invariantCaseInsensitive() { return invariantCI || (invariantCI = create(invariantLocaleName, /*caseInsensitive*/ true)); }, + get invariantCaseSensitive() { return invariantCS || (invariantCS = create(invariantLocaleName, /*caseInsensitive*/ false)); }, + get uiLocale() { return uiLocale; }, + set uiLocale(value) { + if (uiLocale !== value) { + uiLocale = value; + uiCI = undefined; + uiCS = undefined; + } + }, + create, + getOrdinalCollator, + getUICollator, + getInvariantCollator, + getCodeCollator: getInvariantCollator, + getPathCollator: getInvariantCollator + }; + + function getOrdinalCollator(caseInsensitive: boolean) { + return caseInsensitive ? StringCollator.ordinalCaseInsensitive : StringCollator.ordinalCaseSensitive; + } + + function getUICollator(caseInsensitive: boolean) { + return caseInsensitive ? StringCollator.uiCaseInsensitive : StringCollator.uiCaseSensitive; + } + + function getInvariantCollator(caseInsensitive: boolean) { + return caseInsensitive ? StringCollator.invariantCaseInsensitive : StringCollator.invariantCaseSensitive; + } + + function toUpperCase(value: string | undefined): string | undefined { + return value === undefined ? undefined : value.toUpperCase(); + } + + function compareDefined(a: string, b: string) { + return a < b ? Comparison.LessThan : a > b ? Comparison.GreaterThan : Comparison.EqualTo; + } + + function compareWithCallback(a: string | undefined, b: string | undefined, comparer: (a: string, b: string) => number) { + return a === b ? Comparison.EqualTo : + a === undefined ? Comparison.LessThan : + b === undefined ? Comparison.GreaterThan : + toComparison(comparer(a, b)); + } + + function toComparison(value: number) { + return value < 0 ? Comparison.LessThan : value > 0 ? Comparison.GreaterThan : Comparison.EqualTo; + } + + function createIntlStringCollator(locale: string | undefined, caseInsensitive: boolean): StringCollator { + // Initialize the sort collator on first use + let sortComparer: Comparer = (a, b) => { // Intl.Collator.prototype.compare is bound to the collator. See NOTE in // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare - compare: sortCollator.compare, - equate: (a, b) => searchCollator.compare(a, b) === 0 + sortComparer = new Intl.Collator(locale, { usage: "sort", sensitivity: caseInsensitive ? "accent" : "variant" }).compare; + return sortComparer(a, b); + }; + + // Initialize the search collator on first use + let searchComparer: Comparer = (a, b) => { + // Intl.Collator.prototype.compare is bound to the collator. See NOTE in + // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare + searchComparer = new Intl.Collator(locale, { usage: "search", sensitivity: caseInsensitive ? "accent" : "variant" }).compare; + return searchComparer(a, b); }; - } - function createLocaleCompareStringCollator(): StringCollator { - // for case-insensitive comparisons we always map both strings to their - // upper-case form as some unicode characters do not properly round-trip to - // lowercase (such as ẞ). return { - compare: (a, b) => a.toLocaleUpperCase().localeCompare(b.toLocaleUpperCase()), - equate: (a, b) => a.toLocaleUpperCase() === b.toLocaleUpperCase() + compare: (a, b) => compareWithCallback(a, b, sortComparer), + equate: (a, b) => compareWithCallback(a, b, searchComparer) === 0 }; } - function createOrdinalStringCollator(): StringCollator { - // for case-insensitive comparisons we always map both strings to their - // upper-case form as some unicode characters do not properly round-trip to - // lowercase (such as ẞ). + function createLocaleCompareStringCollator(locale: string | undefined, caseInsensitive: boolean): StringCollator { + if (locale !== undefined) return getFallbackStringCollator(/*locale*/ undefined, caseInsensitive); + if (caseInsensitive) { + // for case-insensitive comparisons we always map both strings to their + // upper-case form as some unicode characters do not properly round-trip to + // lowercase (such as `ẞ` (German sharp capital s)). + return { + compare: (a, b) => compareWithCallback(a, b, localeCompareCaseInsensitive), + equate: (a, b) => compareWithCallback(a, b, localeCompareCaseInsensitive) === 0 + }; + } + else { + return { + compare: (a, b) => compareWithCallback(a, b, localeCompare), + equate: (a, b) => compareWithCallback(a, b, localeCompare) === 0 + }; + } + + function localeCompareCaseInsensitive(a: string, b: string) { + return a.toLocaleUpperCase().localeCompare(b.toLocaleUpperCase()); + } + + function localeCompare(a: string, b: string) { + return a.localeCompare(b); + } + } + + function getFallbackStringCollator(_locale: string | undefined, caseInsensitive: boolean): StringCollator { + if (caseInsensitive) return ordinalCI; + + function compareLowerCaseFirst(a: string, b: string) { + // An ordinal comparison puts "A" after "b", but for the UI we want "A" before "b". + // We first sort case insensitively. So "Aaa" will come before "baa". + // Then we sort case sensitively, so "aaa" will come before "Aaa". + return compareDefined(a.toUpperCase(), b.toUpperCase()) || compareDefined(a, b); + } + + return { + compare: (a, b) => compareWithCallback(a, b, compareLowerCaseFirst), + equate: ordinalCS.equate + }; + } + + function getStringCollatorFactory() { + // If the host supports Intl (ECMA-402), we use Intl for comparisons using the default + // locale: + if (typeof Intl === "object" && typeof Intl.Collator === "function") { + return createIntlStringCollator; + } + + // If the host does not support Intl, we fall back to localeCompare: // - // The ordinal comparison cannot properly handle comparison of the Turkish - // (dotted) i and (dotless) ı to the uppercase forms of (dotted) İ and (dotless) I. - // This is best handled by Intl and not supported in the fallback case. - return { - compare: (a, b) => { - const upperA = a.toUpperCase(); - const upperB = b.toUpperCase(); - return upperA < upperB ? Comparison.LessThan : - upperA > upperB ? Comparison.GreaterThan : - Comparison.EqualTo; - }, - equate: (a, b) => a.toUpperCase() === b.toUpperCase() - }; + // Node v0.10 provides incorrect results for comparisons using localeCompare, so we must + // verify the implementation. + if (typeof String.prototype.localeCompare === "function" && + typeof String.prototype.toLocaleUpperCase === "function" && + "a".localeCompare("B") < 0) { + return createLocaleCompareStringCollator; + } + + // Otherwise, fall back to ordinal comparison: + return getFallbackStringCollator; } - - // If the host supports Intl (ECMA-402), we use Intl for comparisons using the default - // locale: - if (typeof Intl === "object" && typeof Intl.Collator === "function") { - return createIntlStringCollator(); - } - - // If the host does not support Intl, we fall back to localeCompare: - // - // Node v0.10 provides incorrect results for comparisons using localeCompare, so we must - // verify the implementation. - if (typeof String.prototype.localeCompare === "function" && - typeof String.prototype.toLocaleUpperCase === "function" && - "a".localeCompare("B") < 0) { - return createLocaleCompareStringCollator(); - } - - // Otherwise, fall back to ordinal comparison: - return createOrdinalStringCollator(); - } - - const caseInsensitiveCollator = createCaseInsensitiveStringCollator(); - - /** - * Performs a case-insensitive comparison between two strings. - * - * If supported by the host, the default locale is used for comparisons. Otherwise, an ordinal - * comparison is used. - */ - export function compareStringsCaseInsensitive(a: string | undefined, b: string | undefined) { - if (a === b) return Comparison.EqualTo; - if (a === undefined) return Comparison.LessThan; - if (b === undefined) return Comparison.GreaterThan; - const result = caseInsensitiveCollator.compare(a, b); - return result < 0 ? Comparison.LessThan : result > 0 ? Comparison.GreaterThan : Comparison.EqualTo; - } - - /** - * Performs a case-sensitive comparison between two strings. - */ - export function compareStringsCaseSensitive(a: string | undefined, b: string | undefined) { - return compareValues(a, b); - } - - export function compareStrings(a: string | undefined, b: string | undefined, ignoreCase?: boolean): Comparison { - return ignoreCase ? compareStringsCaseInsensitive(a, b) : compareStringsCaseSensitive(a, b); - } - - /** - * Performs a case-insensitive equality comparison between two strings. - * - * If supported by the host, the default locale is used for comparisons. Otherwise, an ordinal - * comparison is used. - */ - export function equateStringsCaseInsensitive(a: string | undefined, b: string | undefined) { - return a === b - || a !== undefined - && b !== undefined - && caseInsensitiveCollator.equate(a, b); - } - - /** - * Performs a case-sensitive equality comparison between two strings. - */ - export function equateStringsCaseSensitive(a: string | undefined, b: string | undefined) { - return equateValues(a, b); - } - - export function equateStrings(a: string | undefined, b: string | undefined, ignoreCase?: boolean) { - return ignoreCase ? equateStringsCaseInsensitive(a, b) : equateStringsCaseSensitive(a, b); - } + })(); function getDiagnosticFileName(diagnostic: Diagnostic): string { return diagnostic.file ? diagnostic.file.fileName : undefined; @@ -2003,9 +2151,9 @@ namespace ts { const aComponents = getNormalizedPathComponents(a, currentDirectory); const bComponents = getNormalizedPathComponents(b, currentDirectory); const sharedLength = Math.min(aComponents.length, bComponents.length); - const comparer = ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive; + const collator = StringCollator.getPathCollator(ignoreCase); for (let i = 0; i < sharedLength; i++) { - const result = comparer(aComponents[i], bComponents[i]); + const result = collator.compare(aComponents[i], bComponents[i]); if (result !== Comparison.EqualTo) { return result; } @@ -2026,9 +2174,10 @@ namespace ts { return false; } - const equalityComparer = ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive; + // File-system comparisons should use predictable ordering + const collator = StringCollator.getPathCollator(ignoreCase); for (let i = 0; i < parentComponents.length; i++) { - if (!equalityComparer(parentComponents[i], childComponents[i])) { + if (!collator.equate(parentComponents[i], childComponents[i])) { return false; } } @@ -2284,7 +2433,7 @@ namespace ts { // If there are no "includes", then just put everything in results[0]. const results: string[][] = includeFileRegexes ? includeFileRegexes.map(() => []) : [[]]; - const comparer = useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive; + const collator = StringCollator.getPathCollator(!useCaseSensitiveFileNames); for (const basePath of patterns.basePaths) { visitDirectory(basePath, combinePaths(currentDirectory, basePath), depth); } @@ -2293,7 +2442,7 @@ namespace ts { function visitDirectory(path: string, absolutePath: string, depth: number | undefined) { let { files, directories } = getFileSystemEntries(path); - files = files.slice().sort(comparer); + files = files.slice().sort(collator.compare); for (const current of files) { const name = combinePaths(path, current); @@ -2318,7 +2467,7 @@ namespace ts { } } - directories = directories.slice().sort(comparer); + directories = directories.slice().sort(collator.compare); for (const current of directories) { const name = combinePaths(path, current); const absoluteName = combinePaths(absolutePath, current); @@ -2349,7 +2498,8 @@ namespace ts { } // Sort the offsets array using either the literal or canonical path representations. - includeBasePaths.sort(useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive); + const collator = StringCollator.getPathCollator(!useCaseSensitiveFileNames); + includeBasePaths.sort(collator.compare); // Iterate over each include base path and include unique base paths that are not a // subpath of an existing base path diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index ef93dfe7d4f..bda31d83d86 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6069,7 +6069,7 @@ namespace ts { const checkJsDirectiveMatchResult = checkJsDirectiveRegEx.exec(comment); if (checkJsDirectiveMatchResult) { checkJsDirective = { - enabled: equateStrings(checkJsDirectiveMatchResult[1], "@ts-check", /*ignoreCase*/ true), + enabled: StringCollator.ordinalCaseInsensitive.equate(checkJsDirectiveMatchResult[1], "@ts-check"), end: range.end, pos: range.pos }; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index bca10eceb67..ff3143f3d96 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1101,12 +1101,14 @@ namespace ts { // If '--lib' is not specified, include default library file according to '--target' // otherwise, using options specified in '--lib' instead of '--target' default library file + + // File-system ordering should use a predictable order + const collator = StringCollator.getPathCollator(!host.useCaseSensitiveFileNames()); if (!options.lib) { - return equateStrings(file.fileName, getDefaultLibraryFileName(), /*ignoreCase*/ !host.useCaseSensitiveFileNames()); + return collator.equate(file.fileName, getDefaultLibraryFileName()); } else { - const equalityComparer = host.useCaseSensitiveFileNames() ? equateStringsCaseSensitive : equateStringsCaseInsensitive; - return forEach(options.lib, libFileName => equalityComparer(file.fileName, combinePaths(defaultLibraryPath, libFileName))); + return forEach(options.lib, libFileName => collator.equate(file.fileName, combinePaths(defaultLibraryPath, libFileName))); } } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 01bb36e9065..7ae7e84ad18 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3949,6 +3949,9 @@ namespace ts { trySetLanguageAndTerritory(language, /*territory*/ undefined, errors); } + // Set the locale for UI collation + StringCollator.uiLocale = locale; + function trySetLanguageAndTerritory(language: string, territory: string, errors?: Push): boolean { const compilerFilePath = normalizePath(sys.getExecutingFilePath()); const containingDirectoryPath = getDirectoryPath(compilerFilePath); diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 9622a6df332..8029c3672af 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1698,7 +1698,9 @@ namespace Harness { export function *iterateOutputs(outputFiles: Harness.Compiler.GeneratedFile[]): IterableIterator<[string, string]> { // Collect, test, and sort the fileNames - outputFiles.sort((a, b) => ts.compareStrings(cleanName(a.fileName), cleanName(b.fileName))); + // As this uses the file system, use a predictable order + const collator = ts.StringCollator.getPathCollator(/*ignoreCase*/ false); + outputFiles.sort((a, b) => collator.compare(cleanName(a.fileName), cleanName(b.fileName))); const dupeCase = ts.createMap(); // Yield them for (const outputFile of outputFiles) { diff --git a/src/harness/unittests/compileOnSave.ts b/src/harness/unittests/compileOnSave.ts index 7be6ab5b323..8c7ae507991 100644 --- a/src/harness/unittests/compileOnSave.ts +++ b/src/harness/unittests/compileOnSave.ts @@ -13,8 +13,10 @@ namespace ts.projectSystem { describe("CompileOnSave affected list", () => { function sendAffectedFileRequestAndCheckResult(session: server.Session, request: server.protocol.Request, expectedFileList: { projectFileName: string, files: FileOrFolder[] }[]) { const response = session.executeCommand(request).response as server.protocol.CompileOnSaveAffectedFileListSingleProject[]; - const actualResult = response.sort((list1, list2) => compareStrings(list1.projectFileName, list2.projectFileName)); - expectedFileList = expectedFileList.sort((list1, list2) => compareStrings(list1.projectFileName, list2.projectFileName)); + // File-system ordering should use a predictable order + const collator = StringCollator.getPathCollator(/*ignoreCase*/ false); + const actualResult = response.sort((list1, list2) => collator.compare(list1.projectFileName, list2.projectFileName)); + expectedFileList = expectedFileList.sort((list1, list2) => collator.compare(list1.projectFileName, list2.projectFileName)); assert.equal(actualResult.length, expectedFileList.length, `Actual result project number is different from the expected project number`); diff --git a/src/server/session.ts b/src/server/session.ts index e8ce752745e..ea09a9720f8 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1186,6 +1186,7 @@ namespace ts.server { const completions = project.getLanguageService().getCompletionsAtPosition(file, position); if (simplifiedResult) { + const comparer = StringCollator.uiCaseSensitive.compare; return mapDefined(completions && completions.entries, entry => { if (completions.isMemberCompletion || (entry.name.toLowerCase().indexOf(prefix.toLowerCase()) === 0)) { const { name, kind, kindModifiers, sortText, replacementSpan, hasAction } = entry; @@ -1193,7 +1194,7 @@ namespace ts.server { // Use `hasAction || undefined` to avoid serializing `false`. return { name, kind, kindModifiers, sortText, replacementSpan: convertedSpan, hasAction: hasAction || undefined }; } - }).sort((a, b) => compareStrings(a.name, b.name)); + }).sort((a, b) => comparer(a.name, b.name)); } else { return completions; diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index 2647a87ada7..3988a88fe78 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -175,12 +175,8 @@ namespace ts.NavigateTo { function compareNavigateToItems(i1: RawNavigateToItem, i2: RawNavigateToItem): number { // TODO(cyrusn): get the gamut of comparisons that VS already uses here. - // Right now we just sort by kind first, and then by name of the item. - // We first sort case insensitively. So "Aaa" will come before "bar". - // Then we sort case sensitively, so "aaa" will come before "Aaa". return i1.matchKind - i2.matchKind || - compareStringsCaseInsensitive(i1.name, i2.name) || - compareStringsCaseSensitive(i1.name, i2.name); + StringCollator.uiCaseSensitive.compare(i1.name, i2.name); } function createNavigateToItem(rawItem: RawNavigateToItem): NavigateToItem { diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index bf34f28fed6..91b7ec78a89 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -368,13 +368,8 @@ namespace ts.NavigationBar { function compareChildren(child1: NavigationBarNode, child2: NavigationBarNode): number { const name1 = tryGetName(child1.node), name2 = tryGetName(child2.node); - if (name1 && name2) { - const cmp = ts.compareStringsCaseInsensitive(name1, name2); - return cmp !== 0 ? cmp : navigationBarNodeKind(child1) - navigationBarNodeKind(child2); - } - else { - return name1 ? 1 : name2 ? -1 : navigationBarNodeKind(child1) - navigationBarNodeKind(child2); - } + return StringCollator.uiCaseInsensitive.compare(name1, name2) + || navigationBarNodeKind(child1) - navigationBarNodeKind(child2); } /** diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 84f6ffb0815..2a5ea4ec53b 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -1154,7 +1154,9 @@ namespace ts.refactor.extractSymbol { const name1 = type1.symbol ? type1.symbol.getName() : ""; const name2 = type2.symbol ? type2.symbol.getName() : ""; - const nameDiff = compareStrings(name1, name2); + + // This is for code generation, use a predictable comparer. + const nameDiff = StringCollator.invariantCaseSensitive.compare(name1, name2); if (nameDiff !== 0) { return nameDiff; } From c0ed26e6058fe7a3c5ab1b86166da13ed4d6b998 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 25 Oct 2017 17:46:39 -0700 Subject: [PATCH 016/138] Simplify comparers --- src/compiler/core.ts | 394 +++++++++--------------- src/compiler/parser.ts | 2 +- src/compiler/program.ts | 6 +- src/compiler/utilities.ts | 2 +- src/harness/harness.ts | 4 +- src/harness/unittests/compileOnSave.ts | 6 +- src/server/session.ts | 3 +- src/services/navigateTo.ts | 2 +- src/services/navigationBar.ts | 2 +- src/services/refactors/extractSymbol.ts | 2 +- 10 files changed, 165 insertions(+), 258 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 3a706a9119d..94ab45a6f6a 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1483,6 +1483,38 @@ namespace ts { return headChain; } + /** + * Compare two values for their equality. + */ + export function equateValues(a: T, b: T) { + return a === b; + } + + export function equateStringsCaseInsensitive(a: string, b: string) { + return a === b + || a !== undefined + && b !== undefined + && a.toUpperCase() === b.toUpperCase(); + } + + export function equateStringsCaseSensitive(a: string, b: string) { + return equateValues(a, b); + } + + /** + * Compare equality between two strings using an ordinal comparison. + * + * Case-insensitive comparisons compare both strings after applying `toUpperCase` to + * each string. + */ + export function equateStrings(a: string, b: string, ignoreCase: boolean) { + return ignoreCase ? equateStringsCaseInsensitive(a, b) : equateStringsCaseSensitive(a, b); + } + + export function getStringEqualityComparer(ignoreCase: boolean) { + return ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive; + } + /** * Compare two values for their order relative to each other. */ @@ -1495,280 +1527,157 @@ namespace ts { } /** - * Compare two values for their equality. + * Compare two strings using an ordinal comparison. + * + * Ordinal comparisons are based on the difference between the unicode code points of + * both strings. Characters with multiple unicode representations are considered + * unequal. Ordinal comparisons provide predictable ordering, but place "a" after "B". + * + * Case-insensitive comparisons compare both strings after applying `toUpperCase` to + * each string. */ - export function equateValues(a: T, b: T) { - return a === b; + export function compareStrings(a: string, b: string, ignoreCase: boolean) { + return ignoreCase ? compareStringsCaseInsensitive(a, b) : compareStringsCaseSensitive(a, b); } - export interface StringCollator { - compare(a: string | undefined, b: string | undefined): number; - equate(a: string | undefined, b: string | undefined): boolean; + export function compareStringsCaseInsensitive(a: string, b: string) { + if (a === b) return Comparison.EqualTo; + if (a === undefined) return Comparison.LessThan; + if (b === undefined) return Comparison.GreaterThan; + a = a.toUpperCase(); + b = b.toUpperCase(); + return a < b ? Comparison.LessThan : a > b ? Comparison.GreaterThan : Comparison.EqualTo; } - export interface StringCollators { - /** - * Gets a string collator for case-insensitive ordinal comparisons of strings. - * - * Ordinal comparisons are based on the difference between the unicode code points of - * both strings. Characters with multiple unicode representations are considered - * unequal. - * - * Case-insensitive comparisons compare both strings after applying `toUpperCase` to - * each string. - */ - readonly ordinalCaseInsensitive: StringCollator; - - /** - * Gets a string collator for case-sensitive ordinal comparisons of strings. - * - * Ordinal comparisons are based on the difference between the unicode code points of - * both strings. Characters with multiple unicode representations are considered - * unequal. They provide predictable ordering, but place "a" after "B". - */ - readonly ordinalCaseSensitive: StringCollator; - - /** - * Gets or sets a string collator for case-insensitive comparisons of strings in the host default locale. - * - * UI comparisons are based on the sort order of the host default locale. Ordering is not - * predictable between different host locales, but is best for displaying ordered data - * for UI presentation. Characters with multiple unicode representations may be considered - * equal. - * - * Case-insensitive comparisons compare strings that differ in only base characters or - * accents/diacritic marks as unequal. - */ - readonly uiCaseInsensitive: StringCollator; - - /** - * Gets a string collator for case-sensitive comparisons of strings in the host default locale. - * - * UI comparisons are based on the sort order of the host default locale. Ordering is not - * predictable between different host locales, but is best for displaying ordered data - * for UI presentation. Characters with multiple unicode representations may be considered - * equal. - */ - readonly uiCaseSensitive: StringCollator; - - /** - * Gets a string collator for case-insensitive comparisons of strings in an invariant locale. - * - * Invariant comparisons are based on the sort order of an invariant locale ('en-US'). - * They provide predictable ordering, placing "a" before "B". Characters with multiple - * unicode representations may be considered equal. Invariant comparisons are best used - * when interacting with the file system. - * - * Case-insensitive comparisons compare strings that differ in only base characters or - * accents/diacritic marks as unequal. - */ - readonly invariantCaseInsensitive: StringCollator; - - /** - * Gets a string collator for case-sensitive comparisons of strings in an invariant locale. - * - * Invariant comparisons are based on the sort order of an invariant locale ('en-US'). - * They provide predictable ordering, placing "a" before "B". Characters with multiple - * unicode representations may be considered equal. Invariant comparisons are best used - * when interacting with the file system. - */ - readonly invariantCaseSensitive: StringCollator; - - /** - * Gets or sets the locale for UI collators - */ - uiLocale: string | undefined; - - /** - * Creates a `StringCollator` for a specific locale and case sensitivity. - */ - create(locale: string | undefined, caseSensitive: boolean): StringCollator; - - /** - * Gets the ordinal `StringCollator` for the provided case sensitivity. - */ - getOrdinalCollator(caseSensitive: boolean): StringCollator; - - /** - * Gets the UI `StringCollator` for the provided case sensitivity. - */ - getUICollator(caseSensitive: boolean): StringCollator; - - /** - * Gets the invariant `StringCollator` for the provided case sensitivity. - */ - getInvariantCollator(caseSensitive: boolean): StringCollator; - - /** - * Gets a `StringCollator` for comparing code fragments for code generation. - */ - getCodeCollator(caseSensitive: boolean): StringCollator; - - /** - * Gets a `StringCollator` for comparing paths. - */ - getPathCollator(caseSensitive: boolean): StringCollator; + export function compareStringsCaseSensitive(a: string, b: string) { + return compareValues(a, b); } - export const StringCollator: StringCollators = (function () { - const invariantLocaleName = "en-US"; // we use en-US for the invariant locale - const create = getStringCollatorFactory(); - const ordinalCS: StringCollator = { - compare: compareValues, - equate: equateValues - }; - const ordinalCI: StringCollator = { - compare: (a, b) => compareValues(toUpperCase(a), toUpperCase(b)), - equate: (a, b) => toUpperCase(a) === toUpperCase(b) - }; - let invariantCI: StringCollator | undefined; - let invariantCS: StringCollator | undefined; - let uiCI: StringCollator | undefined; - let uiCS: StringCollator | undefined; - let uiLocale: string | undefined; + export function getStringComparer(ignoreCase: boolean) { + return ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive; + } - return { - get ordinalCaseInsensitive() { return ordinalCI; }, - get ordinalCaseSensitive() { return ordinalCS; }, - get uiCaseInsensitive() { return uiCI || (uiCI = create(uiLocale, /*caseInsensitive*/ true)); }, - get uiCaseSensitive() { return uiCS || (uiCS = create(uiLocale, /*caseInsensitive*/ false)); }, - get invariantCaseInsensitive() { return invariantCI || (invariantCI = create(invariantLocaleName, /*caseInsensitive*/ true)); }, - get invariantCaseSensitive() { return invariantCS || (invariantCS = create(invariantLocaleName, /*caseInsensitive*/ false)); }, - get uiLocale() { return uiLocale; }, - set uiLocale(value) { - if (uiLocale !== value) { - uiLocale = value; - uiCI = undefined; - uiCS = undefined; - } - }, - create, - getOrdinalCollator, - getUICollator, - getInvariantCollator, - getCodeCollator: getInvariantCollator, - getPathCollator: getInvariantCollator - }; - - function getOrdinalCollator(caseInsensitive: boolean) { - return caseInsensitive ? StringCollator.ordinalCaseInsensitive : StringCollator.ordinalCaseSensitive; + /** + * Creates a string comparer for use with string collation in the UI. + */ + const createStringComparer = (function () { + // If the host supports Intl, we use it for comparisons using the default locale. + if (typeof Intl === "object" && typeof Intl.Collator === "function") { + return createIntlCollatorStringComparer; } - function getUICollator(caseInsensitive: boolean) { - return caseInsensitive ? StringCollator.uiCaseInsensitive : StringCollator.uiCaseSensitive; + // If the host does not support Intl, we fall back to localeCompare. + // localeCompare in Node v0.10 is just an ordinal comparison, so don't use it. + if (typeof String.prototype.localeCompare === "function" && + typeof String.prototype.toLocaleUpperCase === "function" && + "a".localeCompare("B") < 0) { + return createLocaleCompareStringComparer; } - function getInvariantCollator(caseInsensitive: boolean) { - return caseInsensitive ? StringCollator.invariantCaseInsensitive : StringCollator.invariantCaseSensitive; - } - - function toUpperCase(value: string | undefined): string | undefined { - return value === undefined ? undefined : value.toUpperCase(); - } - - function compareDefined(a: string, b: string) { - return a < b ? Comparison.LessThan : a > b ? Comparison.GreaterThan : Comparison.EqualTo; - } + // Otherwise, fall back to ordinal comparison: + return createFallbackStringComparer; function compareWithCallback(a: string | undefined, b: string | undefined, comparer: (a: string, b: string) => number) { - return a === b ? Comparison.EqualTo : - a === undefined ? Comparison.LessThan : - b === undefined ? Comparison.GreaterThan : - toComparison(comparer(a, b)); - } - - function toComparison(value: number) { + if (a === b) return Comparison.EqualTo; + if (a === undefined) return Comparison.LessThan; + if (b === undefined) return Comparison.GreaterThan; + const value = comparer(a, b); return value < 0 ? Comparison.LessThan : value > 0 ? Comparison.GreaterThan : Comparison.EqualTo; } - function createIntlStringCollator(locale: string | undefined, caseInsensitive: boolean): StringCollator { + function createIntlCollatorStringComparer(locale: string | undefined, caseInsensitive: boolean): Comparer { // Initialize the sort collator on first use - let sortComparer: Comparer = (a, b) => { + let comparer: Comparer = (a, b) => { // Intl.Collator.prototype.compare is bound to the collator. See NOTE in // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare - sortComparer = new Intl.Collator(locale, { usage: "sort", sensitivity: caseInsensitive ? "accent" : "variant" }).compare; - return sortComparer(a, b); - }; - - // Initialize the search collator on first use - let searchComparer: Comparer = (a, b) => { - // Intl.Collator.prototype.compare is bound to the collator. See NOTE in - // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare - searchComparer = new Intl.Collator(locale, { usage: "search", sensitivity: caseInsensitive ? "accent" : "variant" }).compare; - return searchComparer(a, b); - }; - - return { - compare: (a, b) => compareWithCallback(a, b, sortComparer), - equate: (a, b) => compareWithCallback(a, b, searchComparer) === 0 + comparer = new Intl.Collator(locale, { usage: "sort", sensitivity: caseInsensitive ? "accent" : "variant" }).compare; + return comparer(a, b); }; + return (a, b) => compareWithCallback(a, b, comparer); } - function createLocaleCompareStringCollator(locale: string | undefined, caseInsensitive: boolean): StringCollator { - if (locale !== undefined) return getFallbackStringCollator(/*locale*/ undefined, caseInsensitive); - if (caseInsensitive) { + function createLocaleCompareStringComparer(locale: string | undefined, caseInsensitive: boolean): Comparer { + // if the locale is not the default locale (`undefined`), use the fallback comparer. + return locale !== undefined ? createFallbackStringComparer(locale, caseInsensitive) : + caseInsensitive ? (a, b) => compareWithCallback(a, b, compareCaseInsensitive) : + (a, b) => compareWithCallback(a, b, compareCaseSensitive); + + function compareCaseInsensitive(a: string, b: string) { // for case-insensitive comparisons we always map both strings to their // upper-case form as some unicode characters do not properly round-trip to // lowercase (such as `ẞ` (German sharp capital s)). - return { - compare: (a, b) => compareWithCallback(a, b, localeCompareCaseInsensitive), - equate: (a, b) => compareWithCallback(a, b, localeCompareCaseInsensitive) === 0 - }; - } - else { - return { - compare: (a, b) => compareWithCallback(a, b, localeCompare), - equate: (a, b) => compareWithCallback(a, b, localeCompare) === 0 - }; + return compareCaseSensitive(a.toLocaleUpperCase(), b.toLocaleUpperCase()); } - function localeCompareCaseInsensitive(a: string, b: string) { - return a.toLocaleUpperCase().localeCompare(b.toLocaleUpperCase()); - } - - function localeCompare(a: string, b: string) { + function compareCaseSensitive(a: string, b: string) { return a.localeCompare(b); } } - function getFallbackStringCollator(_locale: string | undefined, caseInsensitive: boolean): StringCollator { - if (caseInsensitive) return ordinalCI; + function createFallbackStringComparer(_locale: string | undefined, caseInsensitive: boolean): Comparer { + return caseInsensitive ? (a, b) => compareWithCallback(a, b, compareCaseInsensitive) : + (a, b) => compareWithCallback(a, b, compareCaseSensitiveDictionaryOrder); - function compareLowerCaseFirst(a: string, b: string) { + function compareCaseInsensitive(a: string, b: string) { + // for case-insensitive comparisons we always map both strings to their + // upper-case form as some unicode characters do not properly round-trip to + // lowercase (such as `ẞ` (German sharp capital s)). + return compareCaseSensitive(a.toUpperCase(), b.toUpperCase()); + } + + function compareCaseSensitive(a: string, b: string) { + return a < b ? Comparison.LessThan : a > b ? Comparison.GreaterThan : Comparison.EqualTo; + } + + function compareCaseSensitiveDictionaryOrder(a: string, b: string) { // An ordinal comparison puts "A" after "b", but for the UI we want "A" before "b". // We first sort case insensitively. So "Aaa" will come before "baa". // Then we sort case sensitively, so "aaa" will come before "Aaa". - return compareDefined(a.toUpperCase(), b.toUpperCase()) || compareDefined(a, b); + return compareCaseInsensitive(a, b) || compareCaseSensitive(a, b); } - - return { - compare: (a, b) => compareWithCallback(a, b, compareLowerCaseFirst), - equate: ordinalCS.equate - }; - } - - function getStringCollatorFactory() { - // If the host supports Intl (ECMA-402), we use Intl for comparisons using the default - // locale: - if (typeof Intl === "object" && typeof Intl.Collator === "function") { - return createIntlStringCollator; - } - - // If the host does not support Intl, we fall back to localeCompare: - // - // Node v0.10 provides incorrect results for comparisons using localeCompare, so we must - // verify the implementation. - if (typeof String.prototype.localeCompare === "function" && - typeof String.prototype.toLocaleUpperCase === "function" && - "a".localeCompare("B") < 0) { - return createLocaleCompareStringCollator; - } - - // Otherwise, fall back to ordinal comparison: - return getFallbackStringCollator; } })(); + let uiCS: Comparer | undefined; + let uiCI: Comparer | undefined; + let uiLocale: string | undefined; + + export function setUILocale(value: string) { + if (uiLocale !== value) { + uiLocale = value; + uiCS = undefined; + uiCI = undefined; + } + } + + export function compareStringsCaseInsensitiveUI(a: string, b: string) { + const comparer = uiCS || (uiCS = createStringComparer(uiLocale, /*caseInsensitive*/ false)); + return comparer(a, b); + } + + export function compareStringsCaseSensitiveUI(a: string, b: string) { + const comparer = uiCI || (uiCI = createStringComparer(uiLocale, /*caseInsensitive*/ true)); + return comparer(a, b); + } + + /** + * Compare two strings using the sort behavior of the UI locale. + * + * Ordering is not predictable between different host locales, but is best for displaying + * ordered data for UI presentation. Characters with multiple unicode representations may + * be considered equal. + * + * Case-insensitive comparisons compare strings that differ in only base characters or + * accents/diacritic marks as unequal. + */ + export function compareStringsUI(a: string, b: string, ignoreCase: boolean) { + return ignoreCase ? compareStringsCaseInsensitiveUI(a, b) : compareStringsCaseSensitiveUI(a, b); + } + + export function getStringComparerUI(ignoreCase: boolean) { + return ignoreCase ? compareStringsCaseInsensitiveUI : compareStringsCaseSensitiveUI; + } + function getDiagnosticFileName(diagnostic: Diagnostic): string { return diagnostic.file ? diagnostic.file.fileName : undefined; } @@ -2151,9 +2060,9 @@ namespace ts { const aComponents = getNormalizedPathComponents(a, currentDirectory); const bComponents = getNormalizedPathComponents(b, currentDirectory); const sharedLength = Math.min(aComponents.length, bComponents.length); - const collator = StringCollator.getPathCollator(ignoreCase); + const comparer = getStringComparer(ignoreCase); for (let i = 0; i < sharedLength; i++) { - const result = collator.compare(aComponents[i], bComponents[i]); + const result = comparer(aComponents[i], bComponents[i]); if (result !== Comparison.EqualTo) { return result; } @@ -2175,9 +2084,9 @@ namespace ts { } // File-system comparisons should use predictable ordering - const collator = StringCollator.getPathCollator(ignoreCase); + const equalityComparer = getStringEqualityComparer(ignoreCase); for (let i = 0; i < parentComponents.length; i++) { - if (!collator.equate(parentComponents[i], childComponents[i])) { + if (!equalityComparer(parentComponents[i], childComponents[i])) { return false; } } @@ -2433,7 +2342,7 @@ namespace ts { // If there are no "includes", then just put everything in results[0]. const results: string[][] = includeFileRegexes ? includeFileRegexes.map(() => []) : [[]]; - const collator = StringCollator.getPathCollator(!useCaseSensitiveFileNames); + const comparer = getStringComparer(!useCaseSensitiveFileNames); for (const basePath of patterns.basePaths) { visitDirectory(basePath, combinePaths(currentDirectory, basePath), depth); } @@ -2442,7 +2351,7 @@ namespace ts { function visitDirectory(path: string, absolutePath: string, depth: number | undefined) { let { files, directories } = getFileSystemEntries(path); - files = files.slice().sort(collator.compare); + files = files.slice().sort(comparer); for (const current of files) { const name = combinePaths(path, current); @@ -2467,7 +2376,7 @@ namespace ts { } } - directories = directories.slice().sort(collator.compare); + directories = directories.slice().sort(comparer); for (const current of directories) { const name = combinePaths(path, current); const absoluteName = combinePaths(absolutePath, current); @@ -2498,8 +2407,7 @@ namespace ts { } // Sort the offsets array using either the literal or canonical path representations. - const collator = StringCollator.getPathCollator(!useCaseSensitiveFileNames); - includeBasePaths.sort(collator.compare); + includeBasePaths.sort(getStringComparer(!useCaseSensitiveFileNames)); // Iterate over each include base path and include unique base paths that are not a // subpath of an existing base path diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index bda31d83d86..11eabb32b43 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6069,7 +6069,7 @@ namespace ts { const checkJsDirectiveMatchResult = checkJsDirectiveRegEx.exec(comment); if (checkJsDirectiveMatchResult) { checkJsDirective = { - enabled: StringCollator.ordinalCaseInsensitive.equate(checkJsDirectiveMatchResult[1], "@ts-check"), + enabled: equateStringsCaseInsensitive(checkJsDirectiveMatchResult[1], "@ts-check"), end: range.end, pos: range.pos }; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index ff3143f3d96..76d3ce4f58d 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1103,12 +1103,12 @@ namespace ts { // otherwise, using options specified in '--lib' instead of '--target' default library file // File-system ordering should use a predictable order - const collator = StringCollator.getPathCollator(!host.useCaseSensitiveFileNames()); + const equalityComparer = getStringEqualityComparer(!host.useCaseSensitiveFileNames()); if (!options.lib) { - return collator.equate(file.fileName, getDefaultLibraryFileName()); + return equalityComparer(file.fileName, getDefaultLibraryFileName()); } else { - return forEach(options.lib, libFileName => collator.equate(file.fileName, combinePaths(defaultLibraryPath, libFileName))); + return forEach(options.lib, libFileName => equalityComparer(file.fileName, combinePaths(defaultLibraryPath, libFileName))); } } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 7ae7e84ad18..4c75215acb5 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3950,7 +3950,7 @@ namespace ts { } // Set the locale for UI collation - StringCollator.uiLocale = locale; + setUILocale(locale); function trySetLanguageAndTerritory(language: string, territory: string, errors?: Push): boolean { const compilerFilePath = normalizePath(sys.getExecutingFilePath()); diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 8029c3672af..1529b19b47a 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1699,8 +1699,8 @@ namespace Harness { export function *iterateOutputs(outputFiles: Harness.Compiler.GeneratedFile[]): IterableIterator<[string, string]> { // Collect, test, and sort the fileNames // As this uses the file system, use a predictable order - const collator = ts.StringCollator.getPathCollator(/*ignoreCase*/ false); - outputFiles.sort((a, b) => collator.compare(cleanName(a.fileName), cleanName(b.fileName))); + const comparer = ts.getStringComparer(/*ignoreCase*/ false); + outputFiles.sort((a, b) => comparer(cleanName(a.fileName), cleanName(b.fileName))); const dupeCase = ts.createMap(); // Yield them for (const outputFile of outputFiles) { diff --git a/src/harness/unittests/compileOnSave.ts b/src/harness/unittests/compileOnSave.ts index 8c7ae507991..43becc3fdb1 100644 --- a/src/harness/unittests/compileOnSave.ts +++ b/src/harness/unittests/compileOnSave.ts @@ -14,9 +14,9 @@ namespace ts.projectSystem { function sendAffectedFileRequestAndCheckResult(session: server.Session, request: server.protocol.Request, expectedFileList: { projectFileName: string, files: FileOrFolder[] }[]) { const response = session.executeCommand(request).response as server.protocol.CompileOnSaveAffectedFileListSingleProject[]; // File-system ordering should use a predictable order - const collator = StringCollator.getPathCollator(/*ignoreCase*/ false); - const actualResult = response.sort((list1, list2) => collator.compare(list1.projectFileName, list2.projectFileName)); - expectedFileList = expectedFileList.sort((list1, list2) => collator.compare(list1.projectFileName, list2.projectFileName)); + const comparer = getStringComparer(/*ignoreCase*/ false); + const actualResult = response.sort((list1, list2) => comparer(list1.projectFileName, list2.projectFileName)); + expectedFileList = expectedFileList.sort((list1, list2) => comparer(list1.projectFileName, list2.projectFileName)); assert.equal(actualResult.length, expectedFileList.length, `Actual result project number is different from the expected project number`); diff --git a/src/server/session.ts b/src/server/session.ts index ea09a9720f8..d40becbbd16 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1186,7 +1186,6 @@ namespace ts.server { const completions = project.getLanguageService().getCompletionsAtPosition(file, position); if (simplifiedResult) { - const comparer = StringCollator.uiCaseSensitive.compare; return mapDefined(completions && completions.entries, entry => { if (completions.isMemberCompletion || (entry.name.toLowerCase().indexOf(prefix.toLowerCase()) === 0)) { const { name, kind, kindModifiers, sortText, replacementSpan, hasAction } = entry; @@ -1194,7 +1193,7 @@ namespace ts.server { // Use `hasAction || undefined` to avoid serializing `false`. return { name, kind, kindModifiers, sortText, replacementSpan: convertedSpan, hasAction: hasAction || undefined }; } - }).sort((a, b) => comparer(a.name, b.name)); + }).sort((a, b) => compareStringsCaseSensitiveUI(a.name, b.name)); } else { return completions; diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index 3988a88fe78..603342df7a8 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -176,7 +176,7 @@ namespace ts.NavigateTo { function compareNavigateToItems(i1: RawNavigateToItem, i2: RawNavigateToItem): number { // TODO(cyrusn): get the gamut of comparisons that VS already uses here. return i1.matchKind - i2.matchKind || - StringCollator.uiCaseSensitive.compare(i1.name, i2.name); + compareStringsCaseSensitiveUI(i1.name, i2.name); } function createNavigateToItem(rawItem: RawNavigateToItem): NavigateToItem { diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 91b7ec78a89..9f4d37407eb 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -368,7 +368,7 @@ namespace ts.NavigationBar { function compareChildren(child1: NavigationBarNode, child2: NavigationBarNode): number { const name1 = tryGetName(child1.node), name2 = tryGetName(child2.node); - return StringCollator.uiCaseInsensitive.compare(name1, name2) + return compareStringsCaseInsensitiveUI(name1, name2) || navigationBarNodeKind(child1) - navigationBarNodeKind(child2); } diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 2a5ea4ec53b..41b922c2003 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -1156,7 +1156,7 @@ namespace ts.refactor.extractSymbol { const name2 = type2.symbol ? type2.symbol.getName() : ""; // This is for code generation, use a predictable comparer. - const nameDiff = StringCollator.invariantCaseSensitive.compare(name1, name2); + const nameDiff = compareStringsCaseSensitive(name1, name2); if (nameDiff !== 0) { return nameDiff; } From dfa1ffe6500881c74d71a109902478ee5a37a52f Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 25 Oct 2017 18:00:59 -0700 Subject: [PATCH 017/138] Cleanup and reordering --- src/compiler/core.ts | 55 ++++++++++++++----------- src/compiler/utilities.ts | 2 +- src/harness/unittests/compileOnSave.ts | 1 - src/services/navigateTo.ts | 6 +-- src/services/navigationBar.ts | 7 ++-- src/services/refactors/extractSymbol.ts | 31 +++----------- 6 files changed, 43 insertions(+), 59 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 94ab45a6f6a..3457af9d174 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1490,6 +1490,16 @@ namespace ts { return a === b; } + /** + * Compare equality between two strings using an ordinal comparison. + * + * Case-insensitive comparisons compare both strings after applying `toUpperCase` to + * each string. + */ + export function equateStrings(a: string, b: string, ignoreCase: boolean) { + return ignoreCase ? equateStringsCaseInsensitive(a, b) : equateStringsCaseSensitive(a, b); + } + export function equateStringsCaseInsensitive(a: string, b: string) { return a === b || a !== undefined @@ -1501,16 +1511,6 @@ namespace ts { return equateValues(a, b); } - /** - * Compare equality between two strings using an ordinal comparison. - * - * Case-insensitive comparisons compare both strings after applying `toUpperCase` to - * each string. - */ - export function equateStrings(a: string, b: string, ignoreCase: boolean) { - return ignoreCase ? equateStringsCaseInsensitive(a, b) : equateStringsCaseSensitive(a, b); - } - export function getStringEqualityComparer(ignoreCase: boolean) { return ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive; } @@ -1557,6 +1557,20 @@ namespace ts { return ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive; } + /** + * Compare two strings using the sort behavior of the UI locale. + * + * Ordering is not predictable between different host locales, but is best for displaying + * ordered data for UI presentation. Characters with multiple unicode representations may + * be considered equal. + * + * Case-insensitive comparisons compare strings that differ in only base characters or + * accents/diacritic marks as unequal. + */ + export function compareStringsUI(a: string, b: string, ignoreCase: boolean) { + return ignoreCase ? compareStringsCaseInsensitiveUI(a, b) : compareStringsCaseSensitiveUI(a, b); + } + /** * Creates a string comparer for use with string collation in the UI. */ @@ -1660,24 +1674,17 @@ namespace ts { return comparer(a, b); } - /** - * Compare two strings using the sort behavior of the UI locale. - * - * Ordering is not predictable between different host locales, but is best for displaying - * ordered data for UI presentation. Characters with multiple unicode representations may - * be considered equal. - * - * Case-insensitive comparisons compare strings that differ in only base characters or - * accents/diacritic marks as unequal. - */ - export function compareStringsUI(a: string, b: string, ignoreCase: boolean) { - return ignoreCase ? compareStringsCaseInsensitiveUI(a, b) : compareStringsCaseSensitiveUI(a, b); - } - export function getStringComparerUI(ignoreCase: boolean) { return ignoreCase ? compareStringsCaseInsensitiveUI : compareStringsCaseSensitiveUI; } + export function compareProperties(a: T, b: T, key: keyof T) { + return a === b ? Comparison.EqualTo : + a === undefined ? Comparison.LessThan : + b === undefined ? Comparison.GreaterThan : + compareValues(a[key], b[key]); + } + function getDiagnosticFileName(diagnostic: Diagnostic): string { return diagnostic.file ? diagnostic.file.fileName : undefined; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 4c75215acb5..a3a8ca3afc7 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3949,7 +3949,7 @@ namespace ts { trySetLanguageAndTerritory(language, /*territory*/ undefined, errors); } - // Set the locale for UI collation + // Set the UI locale for string collation setUILocale(locale); function trySetLanguageAndTerritory(language: string, territory: string, errors?: Push): boolean { diff --git a/src/harness/unittests/compileOnSave.ts b/src/harness/unittests/compileOnSave.ts index 43becc3fdb1..d6d22b162bf 100644 --- a/src/harness/unittests/compileOnSave.ts +++ b/src/harness/unittests/compileOnSave.ts @@ -13,7 +13,6 @@ namespace ts.projectSystem { describe("CompileOnSave affected list", () => { function sendAffectedFileRequestAndCheckResult(session: server.Session, request: server.protocol.Request, expectedFileList: { projectFileName: string, files: FileOrFolder[] }[]) { const response = session.executeCommand(request).response as server.protocol.CompileOnSaveAffectedFileListSingleProject[]; - // File-system ordering should use a predictable order const comparer = getStringComparer(/*ignoreCase*/ false); const actualResult = response.sort((list1, list2) => comparer(list1.projectFileName, list2.projectFileName)); expectedFileList = expectedFileList.sort((list1, list2) => comparer(list1.projectFileName, list2.projectFileName)); diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index 603342df7a8..762726adb77 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -173,10 +173,10 @@ namespace ts.NavigateTo { return bestMatchKind; } - function compareNavigateToItems(i1: RawNavigateToItem, i2: RawNavigateToItem): number { + function compareNavigateToItems(i1: RawNavigateToItem, i2: RawNavigateToItem) { // TODO(cyrusn): get the gamut of comparisons that VS already uses here. - return i1.matchKind - i2.matchKind || - compareStringsCaseSensitiveUI(i1.name, i2.name); + return compareValues(i1.matchKind, i2.matchKind) + || compareStringsCaseSensitiveUI(i1.name, i2.name); } function createNavigateToItem(rawItem: RawNavigateToItem): NavigateToItem { diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 9f4d37407eb..712a315bb41 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -366,10 +366,9 @@ namespace ts.NavigationBar { children.sort(compareChildren); } - function compareChildren(child1: NavigationBarNode, child2: NavigationBarNode): number { - const name1 = tryGetName(child1.node), name2 = tryGetName(child2.node); - return compareStringsCaseInsensitiveUI(name1, name2) - || navigationBarNodeKind(child1) - navigationBarNodeKind(child2); + function compareChildren(child1: NavigationBarNode, child2: NavigationBarNode) { + return compareStringsCaseInsensitiveUI(tryGetName(child1.node), tryGetName(child2.node)) + || compareValues(navigationBarNodeKind(child1), navigationBarNodeKind(child2)); } /** diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 41b922c2003..e26cdd0f74f 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -1137,32 +1137,11 @@ namespace ts.refactor.extractSymbol { {type: type1, declaration: declaration1}: {type: Type, declaration?: Declaration}, {type: type2, declaration: declaration2}: {type: Type, declaration?: Declaration}) { - if (declaration1) { - if (declaration2) { - const positionDiff = declaration1.pos - declaration2.pos; - if (positionDiff !== 0) { - return positionDiff; - } - } - else { - return 1; // Sort undeclared type parameters to the front. - } - } - else if (declaration2) { - return -1; // Sort undeclared type parameters to the front. - } - - const name1 = type1.symbol ? type1.symbol.getName() : ""; - const name2 = type2.symbol ? type2.symbol.getName() : ""; - - // This is for code generation, use a predictable comparer. - const nameDiff = compareStringsCaseSensitive(name1, name2); - if (nameDiff !== 0) { - return nameDiff; - } - - // IDs are guaranteed to be unique, so this ensures a total ordering. - return type1.id - type2.id; + return compareProperties(declaration1, declaration2, "pos") + || compareStringsCaseSensitive( + type1.symbol ? type1.symbol.getName() : "", + type2.symbol ? type2.symbol.getName() : "") + || compareValues(type1.id, type2.id); } function getCalledExpression(scope: Node, range: TargetRange, functionNameText: string): Expression { From 3605e4ef696173fd260a8f5749cd89b34e995f0a Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 25 Oct 2017 18:04:31 -0700 Subject: [PATCH 018/138] Remove unnecessary comment --- src/compiler/program.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 76d3ce4f58d..6a60327371c 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1101,8 +1101,6 @@ namespace ts { // If '--lib' is not specified, include default library file according to '--target' // otherwise, using options specified in '--lib' instead of '--target' default library file - - // File-system ordering should use a predictable order const equalityComparer = getStringEqualityComparer(!host.useCaseSensitiveFileNames()); if (!options.lib) { return equalityComparer(file.fileName, getDefaultLibraryFileName()); From e08f8d263f6f2e715dfe4af58b7b3afd528fb58c Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 25 Oct 2017 18:05:50 -0700 Subject: [PATCH 019/138] Remove unnecessary comment --- src/harness/harness.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 1529b19b47a..d8e12c8e8f7 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1698,7 +1698,6 @@ namespace Harness { export function *iterateOutputs(outputFiles: Harness.Compiler.GeneratedFile[]): IterableIterator<[string, string]> { // Collect, test, and sort the fileNames - // As this uses the file system, use a predictable order const comparer = ts.getStringComparer(/*ignoreCase*/ false); outputFiles.sort((a, b) => comparer(cleanName(a.fileName), cleanName(b.fileName))); const dupeCase = ts.createMap(); From 24437774a8dfdffe7fd49c064e491acd99ace38c Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 26 Oct 2017 11:56:29 -0700 Subject: [PATCH 020/138] Further simplification --- src/compiler/core.ts | 123 +++++++++++++----------- src/compiler/program.ts | 2 +- src/compiler/tsc.ts | 2 +- src/harness/fourslash.ts | 6 ++ src/harness/harness.ts | 3 +- src/harness/unittests/compileOnSave.ts | 5 +- src/services/refactors/extractSymbol.ts | 2 +- 7 files changed, 77 insertions(+), 66 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 3457af9d174..64ab5af67c2 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1483,23 +1483,18 @@ namespace ts { return headChain; } - /** - * Compare two values for their equality. - */ - export function equateValues(a: T, b: T) { + function equateValues(a: T, b: T) { return a === b; } /** - * Compare equality between two strings using an ordinal comparison. + * Compare the equality of two strings using a case-sensitive ordinal comparison. * - * Case-insensitive comparisons compare both strings after applying `toUpperCase` to - * each string. + * Case-sensitive comparisons compare both strings one code-point at a time using the integer + * value of each code-point after applying `toUpperCase` to each string. We always map both + * strings to their upper-case form as some unicode characters do not properly round-trip to + * lowercase (such as `ẞ` (German sharp capital s)). */ - export function equateStrings(a: string, b: string, ignoreCase: boolean) { - return ignoreCase ? equateStringsCaseInsensitive(a, b) : equateStringsCaseSensitive(a, b); - } - export function equateStringsCaseInsensitive(a: string, b: string) { return a === b || a !== undefined @@ -1507,14 +1502,16 @@ namespace ts { && a.toUpperCase() === b.toUpperCase(); } + /** + * Compare the equality of two strings using a case-sensitive ordinal comparison. + * + * Case-sensitive comparisons compare both strings one code-point at a time using the + * integer value of each code-point. + */ export function equateStringsCaseSensitive(a: string, b: string) { return equateValues(a, b); } - export function getStringEqualityComparer(ignoreCase: boolean) { - return ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive; - } - /** * Compare two values for their order relative to each other. */ @@ -1527,19 +1524,17 @@ namespace ts { } /** - * Compare two strings using an ordinal comparison. + * Compare two strings using a case-insensitive ordinal comparison. * - * Ordinal comparisons are based on the difference between the unicode code points of - * both strings. Characters with multiple unicode representations are considered - * unequal. Ordinal comparisons provide predictable ordering, but place "a" after "B". + * Ordinal comparisons are based on the difference between the unicode code points of both + * strings. Characters with multiple unicode representations are considered unequal. Ordinal + * comparisons provide predictable ordering, but place "a" after "B". * - * Case-insensitive comparisons compare both strings after applying `toUpperCase` to - * each string. + * Case-insensitive comparisons compare both strings one code-point at a time using the integer + * value of each code-point after applying `toUpperCase` to each string. We always map both + * strings to their upper-case form as some unicode characters do not properly round-trip to + * lowercase (such as `ẞ` (German sharp capital s)). */ - export function compareStrings(a: string, b: string, ignoreCase: boolean) { - return ignoreCase ? compareStringsCaseInsensitive(a, b) : compareStringsCaseSensitive(a, b); - } - export function compareStringsCaseInsensitive(a: string, b: string) { if (a === b) return Comparison.EqualTo; if (a === undefined) return Comparison.LessThan; @@ -1549,28 +1544,20 @@ namespace ts { return a < b ? Comparison.LessThan : a > b ? Comparison.GreaterThan : Comparison.EqualTo; } + /** + * Compare two strings using a case-sensitive ordinal comparison. + * + * Ordinal comparisons are based on the difference between the unicode code points of both + * strings. Characters with multiple unicode representations are considered unequal. Ordinal + * comparisons provide predictable ordering, but place "a" after "B". + * + * Case-sensitive comparisons compare both strings one code-point at a time using the integer + * value of each code-point. + */ export function compareStringsCaseSensitive(a: string, b: string) { return compareValues(a, b); } - export function getStringComparer(ignoreCase: boolean) { - return ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive; - } - - /** - * Compare two strings using the sort behavior of the UI locale. - * - * Ordering is not predictable between different host locales, but is best for displaying - * ordered data for UI presentation. Characters with multiple unicode representations may - * be considered equal. - * - * Case-insensitive comparisons compare strings that differ in only base characters or - * accents/diacritic marks as unequal. - */ - export function compareStringsUI(a: string, b: string, ignoreCase: boolean) { - return ignoreCase ? compareStringsCaseInsensitiveUI(a, b) : compareStringsCaseSensitiveUI(a, b); - } - /** * Creates a string comparer for use with string collation in the UI. */ @@ -1656,6 +1643,10 @@ namespace ts { let uiCI: Comparer | undefined; let uiLocale: string | undefined; + export function getUILocale() { + return uiLocale; + } + export function setUILocale(value: string) { if (uiLocale !== value) { uiLocale = value; @@ -1664,25 +1655,41 @@ namespace ts { } } + /** + * Compare two strings using the case-insensitive sort behavior of the UI locale. + * + * Ordering is not predictable between different host locales, but is best for displaying + * ordered data for UI presentation. Characters with multiple unicode representations may + * be considered equal. + * + * Case-insensitive comparisons compare strings that differ in only base characters or + * accents/diacritic marks as unequal. + */ export function compareStringsCaseInsensitiveUI(a: string, b: string) { - const comparer = uiCS || (uiCS = createStringComparer(uiLocale, /*caseInsensitive*/ false)); - return comparer(a, b); - } - - export function compareStringsCaseSensitiveUI(a: string, b: string) { const comparer = uiCI || (uiCI = createStringComparer(uiLocale, /*caseInsensitive*/ true)); return comparer(a, b); } - export function getStringComparerUI(ignoreCase: boolean) { - return ignoreCase ? compareStringsCaseInsensitiveUI : compareStringsCaseSensitiveUI; + /** + * Compare two strings in a using the case-sensitive sort behavior of the UI locale. + * + * Ordering is not predictable between different host locales, but is best for displaying + * ordered data for UI presentation. Characters with multiple unicode representations may + * be considered equal. + * + * Case-sensitive comparisons compare strings that differ in base characters, or + * accents/diacritic marks, or case as unequal. + */ + export function compareStringsCaseSensitiveUI(a: string, b: string) { + const comparer = uiCS || (uiCS = createStringComparer(uiLocale, /*caseInsensitive*/ false)); + return comparer(a, b); } - export function compareProperties(a: T, b: T, key: keyof T) { + export function compareProperties(a: T, b: T, key: K, comparer: Comparer) { return a === b ? Comparison.EqualTo : a === undefined ? Comparison.LessThan : b === undefined ? Comparison.GreaterThan : - compareValues(a[key], b[key]); + comparer(a[key], b[key]); } function getDiagnosticFileName(diagnostic: Diagnostic): string { @@ -1690,7 +1697,7 @@ namespace ts { } export function compareDiagnostics(d1: Diagnostic, d2: Diagnostic): Comparison { - return compareValues(getDiagnosticFileName(d1), getDiagnosticFileName(d2)) || + return compareStringsCaseSensitive(getDiagnosticFileName(d1), getDiagnosticFileName(d2)) || compareValues(d1.start, d2.start) || compareValues(d1.length, d2.length) || compareValues(d1.code, d2.code) || @@ -1704,7 +1711,7 @@ namespace ts { const string1 = isString(text1) ? text1 : text1.messageText; const string2 = isString(text2) ? text2 : text2.messageText; - const res = compareValues(string1, string2); + const res = compareStringsCaseSensitive(string1, string2); if (res) { return res; } @@ -2067,7 +2074,7 @@ namespace ts { const aComponents = getNormalizedPathComponents(a, currentDirectory); const bComponents = getNormalizedPathComponents(b, currentDirectory); const sharedLength = Math.min(aComponents.length, bComponents.length); - const comparer = getStringComparer(ignoreCase); + const comparer = ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive; for (let i = 0; i < sharedLength; i++) { const result = comparer(aComponents[i], bComponents[i]); if (result !== Comparison.EqualTo) { @@ -2091,7 +2098,7 @@ namespace ts { } // File-system comparisons should use predictable ordering - const equalityComparer = getStringEqualityComparer(ignoreCase); + const equalityComparer = ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive; for (let i = 0; i < parentComponents.length; i++) { if (!equalityComparer(parentComponents[i], childComponents[i])) { return false; @@ -2338,6 +2345,7 @@ namespace ts { path = normalizePath(path); currentDirectory = normalizePath(currentDirectory); + const comparer = useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive; const patterns = getFileMatcherPatterns(path, excludes, includes, useCaseSensitiveFileNames, currentDirectory); const regexFlag = useCaseSensitiveFileNames ? "" : "i"; @@ -2349,7 +2357,6 @@ namespace ts { // If there are no "includes", then just put everything in results[0]. const results: string[][] = includeFileRegexes ? includeFileRegexes.map(() => []) : [[]]; - const comparer = getStringComparer(!useCaseSensitiveFileNames); for (const basePath of patterns.basePaths) { visitDirectory(basePath, combinePaths(currentDirectory, basePath), depth); } @@ -2414,7 +2421,7 @@ namespace ts { } // Sort the offsets array using either the literal or canonical path representations. - includeBasePaths.sort(getStringComparer(!useCaseSensitiveFileNames)); + includeBasePaths.sort(useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive); // Iterate over each include base path and include unique base paths that are not a // subpath of an existing base path diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 6a60327371c..eb2ac9babe5 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1101,7 +1101,7 @@ namespace ts { // If '--lib' is not specified, include default library file according to '--target' // otherwise, using options specified in '--lib' instead of '--target' default library file - const equalityComparer = getStringEqualityComparer(!host.useCaseSensitiveFileNames()); + const equalityComparer = host.useCaseSensitiveFileNames() ? equateStringsCaseSensitive : equateStringsCaseInsensitive; if (!options.lib) { return equalityComparer(file.fileName, getDefaultLibraryFileName()); } diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 680daeeb485..cc3c256827a 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -306,7 +306,7 @@ namespace ts { // Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch") const optsList = showAllOptions ? - optionDeclarations.slice().sort((a, b) => compareValues(a.name.toLowerCase(), b.name.toLowerCase())) : + optionDeclarations.slice().sort((a, b) => compareStringsCaseInsensitive(a.name, b.name)) : filter(optionDeclarations.slice(), v => v.showInSimplifiedHelpView); // We want our descriptions to align at the same column in our output, diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index d88f0e0854e..105501196b0 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -3128,7 +3128,10 @@ Actual: ${stringify(fullActual)}`); `(function(test, goTo, verify, edit, debug, format, cancellation, classification, verifyOperationIsCancelled) { ${code} })`; + const savedUILocale = ts.getUILocale(); + ts.setUILocale("en-US"); // run tests in en-US by default. try { + const test = new FourSlashInterface.Test(state); const goTo = new FourSlashInterface.GoTo(state); const verify = new FourSlashInterface.Verify(state); @@ -3142,6 +3145,9 @@ ${code} catch (err) { throw err; } + finally { + ts.setUILocale(savedUILocale); + } } function chompLeadingSpace(content: string) { diff --git a/src/harness/harness.ts b/src/harness/harness.ts index d8e12c8e8f7..728d18c59cc 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1698,8 +1698,7 @@ namespace Harness { export function *iterateOutputs(outputFiles: Harness.Compiler.GeneratedFile[]): IterableIterator<[string, string]> { // Collect, test, and sort the fileNames - const comparer = ts.getStringComparer(/*ignoreCase*/ false); - outputFiles.sort((a, b) => comparer(cleanName(a.fileName), cleanName(b.fileName))); + outputFiles.sort((a, b) => ts.compareStringsCaseSensitive(cleanName(a.fileName), cleanName(b.fileName))); const dupeCase = ts.createMap(); // Yield them for (const outputFile of outputFiles) { diff --git a/src/harness/unittests/compileOnSave.ts b/src/harness/unittests/compileOnSave.ts index d6d22b162bf..540c94b9f6d 100644 --- a/src/harness/unittests/compileOnSave.ts +++ b/src/harness/unittests/compileOnSave.ts @@ -13,9 +13,8 @@ namespace ts.projectSystem { describe("CompileOnSave affected list", () => { function sendAffectedFileRequestAndCheckResult(session: server.Session, request: server.protocol.Request, expectedFileList: { projectFileName: string, files: FileOrFolder[] }[]) { const response = session.executeCommand(request).response as server.protocol.CompileOnSaveAffectedFileListSingleProject[]; - const comparer = getStringComparer(/*ignoreCase*/ false); - const actualResult = response.sort((list1, list2) => comparer(list1.projectFileName, list2.projectFileName)); - expectedFileList = expectedFileList.sort((list1, list2) => comparer(list1.projectFileName, list2.projectFileName)); + const actualResult = response.sort((list1, list2) => ts.compareStringsCaseSensitive(list1.projectFileName, list2.projectFileName)); + expectedFileList = expectedFileList.sort((list1, list2) => ts.compareStringsCaseSensitive(list1.projectFileName, list2.projectFileName)); assert.equal(actualResult.length, expectedFileList.length, `Actual result project number is different from the expected project number`); diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index e26cdd0f74f..a790db44ea3 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -1137,7 +1137,7 @@ namespace ts.refactor.extractSymbol { {type: type1, declaration: declaration1}: {type: Type, declaration?: Declaration}, {type: type2, declaration: declaration2}: {type: Type, declaration?: Declaration}) { - return compareProperties(declaration1, declaration2, "pos") + return compareProperties(declaration1, declaration2, "pos", compareValues) || compareStringsCaseSensitive( type1.symbol ? type1.symbol.getName() : "", type2.symbol ? type2.symbol.getName() : "") From bfba32b71df825279a4408756fb7b5dddd1170b1 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 26 Oct 2017 13:49:32 -0700 Subject: [PATCH 021/138] Cleanup, merge #19475 --- src/compiler/core.ts | 147 ++++++++++++++++++++++---------- src/compiler/types.ts | 16 ++++ src/server/project.ts | 3 +- src/server/session.ts | 2 +- src/server/utilities.ts | 5 +- src/services/jsTyping.ts | 5 +- src/services/pathCompletions.ts | 7 +- src/services/services.ts | 2 +- 8 files changed, 132 insertions(+), 55 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 64ab5af67c2..9c52a4481f9 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -159,12 +159,6 @@ namespace ts { return getCanonicalFileName(nonCanonicalizedPath); } - export const enum Comparison { - LessThan = -1, - EqualTo = 0, - GreaterThan = 1 - } - export function length(array: ReadonlyArray) { return array ? array.length : 0; } @@ -301,17 +295,33 @@ namespace ts { Debug.fail(); } - export function contains(array: ReadonlyArray, value: T): boolean { - if (array) { - for (const v of array) { - if (v === value) { - return true; - } + function containsWithoutEqualityComparer(array: ReadonlyArray, value: T) { + for (const v of array) { + if (v === value) { + return true; } } return false; } + function containsWithEqualityComparer(array: ReadonlyArray, value: T, equalityComparer: EqualityComparer) { + for (const v of array) { + if (equalityComparer(v, value)) { + return true; + } + } + return false; + } + + export function contains(array: ReadonlyArray, value: T, equalityComparer?: EqualityComparer): boolean { + if (array) { + return equalityComparer + ? containsWithEqualityComparer(array, value, equalityComparer) + : containsWithoutEqualityComparer(array, value); + } + return false; + } + export function indexOf(array: ReadonlyArray, value: T): number { if (array) { for (let i = 0; i < array.length; i++) { @@ -649,21 +659,36 @@ namespace ts { return [...array1, ...array2]; } - // TODO: fixme (N^2) - add optional comparer so collection can be sorted before deduplication. - export function deduplicate(array: ReadonlyArray, equalityComparer: (a: T, b: T) => boolean = equateValues): T[] { - let result: T[]; - if (array) { - result = []; - loop: for (const item of array) { - for (const res of result) { - if (equalityComparer(res, item)) { - continue loop; - } + /** + * Creates a new array with duplicate entries removed. + * @param equalityComparer An optional `EqualityComparer` used to determine if two values are duplicates. + * @param comparer An optional `Comparer` used to sort entries before comparison. If supplied, + * results are returned in the original order found in `array`. + */ + export function deduplicate(array: ReadonlyArray, equalityComparer?: EqualityComparer, comparer?: Comparer): T[] { + if (!array) return undefined; + if (!comparer) return addRangeIfUnique([], array, equalityComparer); + return deduplicateWorker(array, equalityComparer, comparer); + } + + function deduplicateWorker(array: ReadonlyArray, equalityComparer: EqualityComparer = equateValues, comparer: Comparer) { + // Perform a stable sort of the array. This ensures the first entry in a list of + // duplicates remains the first entry in the result. + const indices = sequence(0, array.length); + stableSortIndices(array, indices, comparer); + + const deduplicated: number[] = []; + loop: for (const sourceIndex of indices) { + for (const targetIndex of deduplicated) { + if (equalityComparer(array[sourceIndex], array[targetIndex])) { + continue loop; } - result.push(item); } + deduplicated.push(sourceIndex); } - return result; + + // return deduplicated items in original order + return deduplicated.sort().map(i => array[i]); } export function arrayIsEqualTo(array1: ReadonlyArray, array2: ReadonlyArray, equalityComparer: (a: T, b: T) => boolean = equateValues): boolean { @@ -731,7 +756,7 @@ namespace ts { * are not present in `arrayA` but are present in `arrayB`. Assumes both arrays are sorted * based on the provided comparer. */ - export function relativeComplement(arrayA: T[] | undefined, arrayB: T[] | undefined, comparer: Comparer = compareValues, offsetA = 0, offsetB = 0): T[] | undefined { + export function relativeComplement(arrayA: T[] | undefined, arrayB: T[] | undefined, comparer: Comparer, offsetA = 0, offsetB = 0): T[] | undefined { if (!arrayB || !arrayA || arrayB.length === 0 || arrayA.length === 0) return arrayB; const result: T[] = []; outer: for (; offsetB < arrayB.length; offsetB++) { @@ -795,19 +820,27 @@ namespace ts { start = start === undefined ? 0 : toOffset(from, start); end = end === undefined ? from.length : toOffset(from, end); for (let i = start; i < end && i < from.length; i++) { - const v = from[i]; - if (v !== undefined) { + if (from[i] !== undefined) { to.push(from[i]); } } return to; } + function addRangeIfUnique(to: T[], from: ReadonlyArray, equalityComparer?: EqualityComparer): T[] | undefined { + for (let i = 0; i < from.length; i++) { + if (from[i] !== undefined) { + pushIfUnique(to, from[i], equalityComparer); + } + } + return to; + } + /** * @return Whether the value was added. */ - export function pushIfUnique(array: T[], toAdd: T): boolean { - if (contains(array, toAdd)) { + export function pushIfUnique(array: T[], toAdd: T, equalityComparer?: EqualityComparer): boolean { + if (contains(array, toAdd, equalityComparer)) { return false; } else { @@ -819,9 +852,9 @@ namespace ts { /** * Unlike `pushIfUnique`, this can take `undefined` as an input, and returns a new array. */ - export function appendIfUnique(array: T[] | undefined, toAdd: T): T[] { + export function appendIfUnique(array: T[] | undefined, toAdd: T, equalityComparer?: EqualityComparer): T[] { if (array) { - pushIfUnique(array, toAdd); + pushIfUnique(array, toAdd, equalityComparer); return array; } else { @@ -829,14 +862,29 @@ namespace ts { } } + /** + * Creates an array of integers starting at `from` (inclusive) and ending at `to` (exclusive). + */ + function sequence(from: number, to: number) { + const numbers: number[] = []; + for (let i = from; i < to; i++) { + numbers.push(i); + } + return numbers; + } + + function stableSortIndices(array: ReadonlyArray, indices: number[], comparer: Comparer) { + // sort indices by value then position + indices.sort((x, y) => comparer(array[x], array[y]) || compareValues(x, y)); + } + /** * Stable sort of an array. Elements equal to each other maintain their relative position in the array. */ - export function stableSort(array: ReadonlyArray, comparer: Comparer = compareValues) { - return array - .map((_, i) => i) // create array of indices - .sort((x, y) => comparer(array[x], array[y]) || compareValues(x, y)) // sort indices by value then position - .map(i => array[i]); // get sorted array + export function stableSort(array: ReadonlyArray, comparer: Comparer) { + const indices = sequence(0, array.length); + stableSortIndices(array, indices, comparer); + return indices.map(i => array[i]); } export function rangeEquals(array1: ReadonlyArray, array2: ReadonlyArray, pos: number, end: number) { @@ -914,9 +962,6 @@ namespace ts { return result; } - export type Comparer = (a: T, b: T) => Comparison; - export type EqualityComparer = (a: T, b: T) => boolean; - /** * Performs a binary search, finding the index at which 'value' occurs in 'array'. * If no such index is found, returns the 2's-complement of first index at which @@ -1483,7 +1528,7 @@ namespace ts { return headChain; } - function equateValues(a: T, b: T) { + export function equateValues(a: T, b: T) { return a === b; } @@ -1512,10 +1557,9 @@ namespace ts { return equateValues(a, b); } - /** - * Compare two values for their order relative to each other. - */ - export function compareValues(a: T, b: T) { + function compareComparableValues(a: string, b: string): Comparison; + function compareComparableValues(a: number, b: number): Comparison; + function compareComparableValues(a: string | number, b: string | number) { return a === b ? Comparison.EqualTo : a === undefined ? Comparison.LessThan : b === undefined ? Comparison.GreaterThan : @@ -1523,6 +1567,13 @@ namespace ts { Comparison.GreaterThan; } + /** + * Compare two values for their order relative to each other. + */ + export function compareValues(a: number, b: number) { + return compareComparableValues(a, b); + } + /** * Compare two strings using a case-insensitive ordinal comparison. * @@ -1555,7 +1606,7 @@ namespace ts { * value of each code-point. */ export function compareStringsCaseSensitive(a: string, b: string) { - return compareValues(a, b); + return compareComparableValues(a, b); } /** @@ -2488,7 +2539,11 @@ namespace ts { if (!extraFileExtensions || extraFileExtensions.length === 0 || !needAllExtensions) { return needAllExtensions ? allSupportedExtensions : supportedTypeScriptExtensions; } - return deduplicate([...allSupportedExtensions, ...extraFileExtensions.map(e => e.extension)]); + return deduplicate( + [...allSupportedExtensions, ...extraFileExtensions.map(e => e.extension)], + equateStringsCaseSensitive, + compareStringsCaseSensitive + ); } export function hasJavaScriptFileExtension(fileName: string) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ff2a33266ed..2f861f2c371 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -36,6 +36,22 @@ namespace ts { push(...values: T[]): void; } + /* @internal */ + export type EqualityComparer = (a: T, b: T) => boolean; + + /* @internal */ + export type Comparer = (a: T, b: T) => Comparison; + + /* @internal */ + export const enum Comparison { + LessThan = -1, + EqualTo = 0, + GreaterThan = 1 + } + + /* @internal */ + export type Selector = (v: T) => U; + // branded string type used to store absolute, normalized and canonicalized paths // arbitrary file name can be converted to Path via toPath function export type Path = string & { __pathBrand: any }; diff --git a/src/server/project.ts b/src/server/project.ts index 7542b30df00..bda4b644e9c 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -860,7 +860,8 @@ namespace ts.server { const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(inserted, this.directoryStructureHost); scriptInfo.attachToProject(this); }, - removed => this.detachScriptInfoFromProject(removed) + removed => this.detachScriptInfoFromProject(removed), + compareStringsCaseSensitive ); const elapsed = timestamp() - start; this.writeLog(`Finishing updateGraphWorker: Project: ${this.getProjectName()} structureChanged: ${hasChanges} Elapsed: ${elapsed}ms`); diff --git a/src/server/session.ts b/src/server/session.ts index d40becbbd16..c8ce00f303c 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -958,7 +958,7 @@ namespace ts.server { projects, project => project.getLanguageService().findReferences(file, position), /*comparer*/ undefined, - /*areEqual (TODO: fixme)*/ undefined + equateValues ); } diff --git a/src/server/utilities.ts b/src/server/utilities.ts index 69399b672b3..0976d3dd1e5 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -288,8 +288,7 @@ namespace ts.server { return index === 0 || value !== array[index - 1]; } - export function enumerateInsertsAndDeletes(newItems: SortedReadonlyArray, oldItems: SortedReadonlyArray, inserted: (newItem: T) => void, deleted: (oldItem: T) => void, compare?: Comparer) { - compare = compare || compareValues; + export function enumerateInsertsAndDeletes(newItems: SortedReadonlyArray, oldItems: SortedReadonlyArray, inserted: (newItem: T) => void, deleted: (oldItem: T) => void, comparer: Comparer) { let newIndex = 0; let oldIndex = 0; const newLen = newItems.length; @@ -297,7 +296,7 @@ namespace ts.server { while (newIndex < newLen && oldIndex < oldLen) { const newItem = newItems[newIndex]; const oldItem = oldItems[oldIndex]; - const compareResult = compare(newItem, oldItem); + const compareResult = comparer(newItem, oldItem); if (compareResult === Comparison.LessThan) { inserted(newItem); newIndex++; diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index 572858dd2fd..6579e21fb27 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -115,7 +115,10 @@ namespace ts.JsTyping { // add typings for unresolved imports if (unresolvedImports) { - const module = deduplicate(unresolvedImports.map(moduleId => nodeCoreModules.has(moduleId) ? "node" : moduleId)); + const module = deduplicate( + unresolvedImports.map(moduleId => nodeCoreModules.has(moduleId) ? "node" : moduleId), + equateStringsCaseSensitive, + compareStringsCaseSensitive); addInferredTypings(module, "Inferred typings from unresolved imports"); } // Add the cached typing locations for inferred typings that are already installed diff --git a/src/services/pathCompletions.ts b/src/services/pathCompletions.ts index 780b14db719..79a38c70d3a 100644 --- a/src/services/pathCompletions.ts +++ b/src/services/pathCompletions.ts @@ -44,7 +44,10 @@ namespace ts.Completions.PathCompletions { containsPath(rootDirectory, scriptPath, basePath, ignoreCase) ? scriptPath.substr(rootDirectory.length) : undefined); // Now find a path for each potential directory that is to be merged with the one containing the script - return deduplicate(map(rootDirs, rootDirectory => combinePaths(rootDirectory, relativeDirectory))); + return deduplicate( + map(rootDirs, rootDirectory => combinePaths(rootDirectory, relativeDirectory)), + equateStringsCaseSensitive, + compareStringsCaseSensitive); } function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs: string[], fragment: string, scriptPath: string, extensions: ReadonlyArray, includeExtensions: boolean, span: TextSpan, compilerOptions: CompilerOptions, host: LanguageServiceHost, exclude?: string): CompletionEntry[] { @@ -271,7 +274,7 @@ namespace ts.Completions.PathCompletions { } } - return deduplicate(nonRelativeModuleNames); + return deduplicate(nonRelativeModuleNames, equateStringsCaseSensitive, compareStringsCaseSensitive); } export function getTripleSlashReferenceCompletion(sourceFile: SourceFile, position: number, compilerOptions: CompilerOptions, host: LanguageServiceHost): CompletionInfo { diff --git a/src/services/services.ts b/src/services/services.ts index 3b90a80a387..a5f81edf79d 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1757,7 +1757,7 @@ namespace ts { const newLineCharacter = getNewLineOrDefaultFromHost(host); const rulesProvider = getRuleProvider(formatOptions); - return flatMap(deduplicate(errorCodes), errorCode => { + return flatMap(deduplicate(errorCodes, equateValues, compareValues), errorCode => { cancellationToken.throwIfCancellationRequested(); return codefix.getFixes({ errorCode, sourceFile, span, program, newLineCharacter, host, cancellationToken, rulesProvider }); }); From d9775cd8229ffcecff7cfb194bbcc98945f7554f Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 26 Oct 2017 14:29:03 -0700 Subject: [PATCH 022/138] Ensure explicit default locale before each test --- src/compiler/core.ts | 63 +++++++++++++++++++++++++++++++--------- src/harness/fourslash.ts | 5 ---- src/harness/runner.ts | 5 ++++ 3 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 9c52a4481f9..bb0aca3e700 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1613,21 +1613,17 @@ namespace ts { * Creates a string comparer for use with string collation in the UI. */ const createStringComparer = (function () { - // If the host supports Intl, we use it for comparisons using the default locale. - if (typeof Intl === "object" && typeof Intl.Collator === "function") { - return createIntlCollatorStringComparer; + type CachedLocale = "en-US" | undefined; + + interface StringComparerCache { + default?: Comparer; + "en-US"?: Comparer; } - // If the host does not support Intl, we fall back to localeCompare. - // localeCompare in Node v0.10 is just an ordinal comparison, so don't use it. - if (typeof String.prototype.localeCompare === "function" && - typeof String.prototype.toLocaleUpperCase === "function" && - "a".localeCompare("B") < 0) { - return createLocaleCompareStringComparer; - } - - // Otherwise, fall back to ordinal comparison: - return createFallbackStringComparer; + let caseInsensitiveCache: StringComparerCache | undefined; + let caseSensitiveCache: StringComparerCache | undefined; + const createStringComparerNoCache = getStringComparerFactory(); + return createStringComparer; function compareWithCallback(a: string | undefined, b: string | undefined, comparer: (a: string, b: string) => number) { if (a === b) return Comparison.EqualTo; @@ -1688,6 +1684,47 @@ namespace ts { return compareCaseInsensitive(a, b) || compareCaseSensitive(a, b); } } + + function getStringComparerFactory() { + // If the host supports Intl, we use it for comparisons using the default locale. + if (typeof Intl === "object" && typeof Intl.Collator === "function") { + return createIntlCollatorStringComparer; + } + + // If the host does not support Intl, we fall back to localeCompare. + // localeCompare in Node v0.10 is just an ordinal comparison, so don't use it. + if (typeof String.prototype.localeCompare === "function" && + typeof String.prototype.toLocaleUpperCase === "function" && + "a".localeCompare("B") < 0) { + return createLocaleCompareStringComparer; + } + + // Otherwise, fall back to ordinal comparison: + return createFallbackStringComparer; + } + + // Hold onto common string comparers. This avoids constantly reallocating comparers during + // tests. + function createStringComparerCached(locale: CachedLocale, caseInsensitive: boolean) { + const cacheKey = locale || "default"; + const cache = caseInsensitive + ? caseInsensitiveCache || (caseInsensitiveCache = {}) + : caseSensitiveCache || (caseSensitiveCache = {}); + + let comparer = cache[cacheKey]; + if (!comparer) { + comparer = createStringComparerNoCache(locale, caseInsensitive); + cache[cacheKey] = comparer; + } + + return comparer; + } + + function createStringComparer(locale: string | undefined, caseInsensitive: boolean) { + return locale === undefined || locale === "en-US" + ? createStringComparerCached(locale as CachedLocale, caseInsensitive) + : createStringComparerNoCache(locale, caseInsensitive); + } })(); let uiCS: Comparer | undefined; diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 105501196b0..b52dbd6932a 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -3128,8 +3128,6 @@ Actual: ${stringify(fullActual)}`); `(function(test, goTo, verify, edit, debug, format, cancellation, classification, verifyOperationIsCancelled) { ${code} })`; - const savedUILocale = ts.getUILocale(); - ts.setUILocale("en-US"); // run tests in en-US by default. try { const test = new FourSlashInterface.Test(state); @@ -3145,9 +3143,6 @@ ${code} catch (err) { throw err; } - finally { - ts.setUILocale(savedUILocale); - } } function chompLeadingSpace(content: string) { diff --git a/src/harness/runner.ts b/src/harness/runner.ts index db807b976bb..57955c9ab43 100644 --- a/src/harness/runner.ts +++ b/src/harness/runner.ts @@ -207,6 +207,11 @@ function beginTests() { ts.Debug.enableDebugInfo(); } + // run tests in en-US by default. + const savedUILocale = ts.getUILocale(); + beforeEach(() => ts.setUILocale("en-US")); + afterEach(() => ts.setUILocale(savedUILocale)); + runTests(runners); if (!runUnitTests) { From 3cb15378d7db79454d7b2dcc1963e3d3badb7ecb Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 26 Oct 2017 17:51:09 -0700 Subject: [PATCH 023/138] Improve performance of deduplication of sorted arrays --- src/compiler/checker.ts | 22 ++----- src/compiler/core.ts | 109 +++++++++++++++++++++++------------ src/compiler/scanner.ts | 2 +- src/compiler/tsc.ts | 2 +- src/compiler/types.ts | 5 ++ src/compiler/utilities.ts | 10 ++-- src/harness/harness.ts | 2 +- src/server/editorServices.ts | 6 +- src/server/utilities.ts | 4 +- src/services/textChanges.ts | 2 +- 10 files changed, 98 insertions(+), 66 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index aaaa0ed50b8..abedf405cde 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7341,24 +7341,12 @@ namespace ts { unionIndex?: number; } + function getTypeId(type: Type) { + return type.id; + } + function binarySearchTypes(types: Type[], type: Type): number { - let low = 0; - let high = types.length - 1; - const typeId = type.id; - while (low <= high) { - const middle = low + ((high - low) >> 1); - const id = types[middle].id; - if (id === typeId) { - return middle; - } - else if (id > typeId) { - high = middle - 1; - } - else { - low = middle + 1; - } - } - return ~low; + return binarySearch(types, type, getTypeId, compareValues); } function containsType(types: Type[], type: Type): boolean { diff --git a/src/compiler/core.ts b/src/compiler/core.ts index bb0aca3e700..605cde05178 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -660,35 +660,77 @@ namespace ts { } /** - * Creates a new array with duplicate entries removed. + * Deduplicates an array that has already been sorted. + */ + export function deduplicateSorted(array: SortedReadonlyArray, comparer: EqualityComparer | Comparer) { + if (!array) return undefined; + if (array.length === 0) return []; + + let last = array[0]; + const deduplicated: T[] = [last]; + for (let i = 1; i < array.length; i++) { + switch (comparer(last, array[i])) { + // equality comparison + case true: + + // relational comparison + case Comparison.LessThan: + case Comparison.EqualTo: + continue; + } + + deduplicated.push(last = array[i]); + } + + return deduplicated; + } + + /** + * Deduplicates an unsorted array. * @param equalityComparer An optional `EqualityComparer` used to determine if two values are duplicates. * @param comparer An optional `Comparer` used to sort entries before comparison. If supplied, * results are returned in the original order found in `array`. */ - export function deduplicate(array: ReadonlyArray, equalityComparer?: EqualityComparer, comparer?: Comparer): T[] { - if (!array) return undefined; - if (!comparer) return addRangeIfUnique([], array, equalityComparer); - return deduplicateWorker(array, equalityComparer, comparer); + export function deduplicate(array: ReadonlyArray, equalityComparer: EqualityComparer, comparer?: Comparer): T[] { + return !array ? undefined : + array.length === 0 ? [] : + array.length === 1 ? array.slice() : + comparer ? deduplicateRelational(array, equalityComparer, comparer) : + deduplicateEquality(array, equalityComparer); } - function deduplicateWorker(array: ReadonlyArray, equalityComparer: EqualityComparer = equateValues, comparer: Comparer) { + function deduplicateRelational(array: ReadonlyArray, equalityComparer: EqualityComparer, comparer: Comparer) { // Perform a stable sort of the array. This ensures the first entry in a list of // duplicates remains the first entry in the result. const indices = sequence(0, array.length); stableSortIndices(array, indices, comparer); - const deduplicated: number[] = []; - loop: for (const sourceIndex of indices) { - for (const targetIndex of deduplicated) { - if (equalityComparer(array[sourceIndex], array[targetIndex])) { - continue loop; - } + let last = array[indices[0]]; + const deduplicated: number[] = [indices[0]]; + for (let i = 1; i < indices.length; i++) { + const index = indices[i]; + const item = array[index]; + if (!equalityComparer(last, item)) { + deduplicated.push(index); + last = item; } - deduplicated.push(sourceIndex); } - // return deduplicated items in original order - return deduplicated.sort().map(i => array[i]); + // restore original order + deduplicated.sort(); + return deduplicated.map(i => array[i]); + } + + function deduplicateEquality(array: ReadonlyArray, equalityComparer: EqualityComparer) { + const result: T[] = []; + for (const item of array) { + pushIfUnique(result, item, equalityComparer); + } + return result; + } + + export function sortAndDeduplicate(array: ReadonlyArray, comparer: Comparer, equalityComparer?: EqualityComparer) { + return deduplicateSorted(sort(array, comparer), equalityComparer || comparer); } export function arrayIsEqualTo(array1: ReadonlyArray, array2: ReadonlyArray, equalityComparer: (a: T, b: T) => boolean = equateValues): boolean { @@ -827,15 +869,6 @@ namespace ts { return to; } - function addRangeIfUnique(to: T[], from: ReadonlyArray, equalityComparer?: EqualityComparer): T[] | undefined { - for (let i = 0; i < from.length; i++) { - if (from[i] !== undefined) { - pushIfUnique(to, from[i], equalityComparer); - } - } - return to; - } - /** * @return Whether the value was added. */ @@ -878,13 +911,20 @@ namespace ts { indices.sort((x, y) => comparer(array[x], array[y]) || compareValues(x, y)); } + /** + * Returns a new sorted array. + */ + export function sort(array: ReadonlyArray, comparer: Comparer) { + return array.slice().sort(comparer) as ReadonlyArray as SortedReadonlyArray; + } + /** * Stable sort of an array. Elements equal to each other maintain their relative position in the array. */ export function stableSort(array: ReadonlyArray, comparer: Comparer) { const indices = sequence(0, array.length); stableSortIndices(array, indices, comparer); - return indices.map(i => array[i]); + return indices.map(i => array[i]) as ReadonlyArray as SortedReadonlyArray; } export function rangeEquals(array1: ReadonlyArray, array2: ReadonlyArray, pos: number, end: number) { @@ -969,25 +1009,22 @@ namespace ts { * @param array A sorted array whose first element must be no larger than number * @param number The value to be searched for in the array. */ - export function binarySearch(array: ReadonlyArray, value: T, comparer?: Comparer, offset?: number): number { + export function binarySearch(array: ReadonlyArray, value: T, keySelector: Selector, keyComparer: Comparer, offset?: number): number { if (!array || array.length === 0) { return -1; } let low = offset || 0; let high = array.length - 1; - comparer = comparer !== undefined - ? comparer - : (v1, v2) => (v1 < v2 ? -1 : (v1 > v2 ? 1 : 0)); - + const key = keySelector(value); while (low <= high) { const middle = low + ((high - low) >> 1); - const midValue = array[middle]; + const midKey = keySelector(array[middle]); - if (comparer(midValue, value) === 0) { + if (keyComparer(midKey, key) === 0) { return middle; } - else if (comparer(midValue, value) > 0) { + else if (keyComparer(midKey, key) > 0) { high = middle - 1; } else { @@ -2452,8 +2489,8 @@ namespace ts { return flatten(results); function visitDirectory(path: string, absolutePath: string, depth: number | undefined) { - let { files, directories } = getFileSystemEntries(path); - files = files.slice().sort(comparer); + const entries = getFileSystemEntries(path); + const files = sort(entries.files, comparer); for (const current of files) { const name = combinePaths(path, current); @@ -2478,7 +2515,7 @@ namespace ts { } } - directories = directories.slice().sort(comparer); + const directories = sort(entries.directories, comparer); for (const current of directories) { const name = combinePaths(path, current); const absoluteName = combinePaths(absolutePath, current); diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 6dab127ca33..5a11cccc8b6 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -352,7 +352,7 @@ namespace ts { * We assume the first line starts at position 0 and 'position' is non-negative. */ export function computeLineAndCharacterOfPosition(lineStarts: ReadonlyArray, position: number): LineAndCharacter { - let lineNumber = binarySearch(lineStarts, position); + let lineNumber = binarySearch(lineStarts, position, identity, compareValues); if (lineNumber < 0) { // If the actual position was not found, // the binary search returns the 2's-complement of the next line start diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index cc3c256827a..e7a73b6d09c 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -306,7 +306,7 @@ namespace ts { // Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch") const optsList = showAllOptions ? - optionDeclarations.slice().sort((a, b) => compareStringsCaseInsensitive(a.name, b.name)) : + sort(optionDeclarations, (a, b) => compareStringsCaseInsensitive(a.name, b.name)) : filter(optionDeclarations.slice(), v => v.showInSimplifiedHelpView); // We want our descriptions to align at the same column in our output, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 2f861f2c371..3af3b6e022a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -36,6 +36,11 @@ namespace ts { push(...values: T[]): void; } + /* @internal */ + export interface SortedReadonlyArray extends ReadonlyArray { + " __sortedArrayBrand": any; + } + /* @internal */ export type EqualityComparer = (a: T, b: T) => boolean; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index a3a8ca3afc7..1ade3cc6374 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -321,16 +321,16 @@ namespace ts { return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node, includeTrivia); } + function getPos(range: Node) { + return range.pos; + } + /** * Note: it is expected that the `nodeArray` and the `node` are within the same file. * For example, searching for a `SourceFile` in a `SourceFile[]` wouldn't work. */ export function indexOfNode(nodeArray: ReadonlyArray, node: Node) { - return binarySearch(nodeArray, node, compareNodePos); - } - - function compareNodePos({ pos: aPos }: Node, { pos: bPos}: Node) { - return aPos < bPos ? Comparison.LessThan : bPos < aPos ? Comparison.GreaterThan : Comparison.EqualTo; + return binarySearch(nodeArray, node, getPos, compareValues); } /** diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 728d18c59cc..4826c30bbfb 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1313,7 +1313,7 @@ namespace Harness { export const diagnosticSummaryMarker = "__diagnosticSummary"; export const globalErrorsMarker = "__globalErrors"; export function *iterateErrorBaseline(inputFiles: ReadonlyArray, diagnostics: ReadonlyArray, pretty?: boolean): IterableIterator<[string, string, number]> { - diagnostics = diagnostics.slice().sort(ts.compareDiagnostics); + diagnostics = ts.sort(diagnostics, ts.compareDiagnostics); let outputLines = ""; // Count up all errors that were found in files other than lib.d.ts so we don't miss any let totalErrorsReportedInNonLibraryFiles = 0; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index f749c27cbbc..1e3104b08d1 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -203,8 +203,10 @@ namespace ts.server { * This helper function processes a list of projects and return the concatenated, sortd and deduplicated output of processing each project. */ export function combineProjectOutput(projects: ReadonlyArray, action: (project: Project) => ReadonlyArray, comparer?: (a: T, b: T) => number, areEqual?: (a: T, b: T) => boolean) { - const result = flatMap(projects, action).sort(comparer); - return projects.length > 1 ? deduplicate(result, areEqual) : result; + const outputs = flatMap(projects, action); + return comparer + ? sortAndDeduplicate(outputs, comparer, areEqual) + : deduplicate(outputs, areEqual); } export interface HostConfiguration { diff --git a/src/server/utilities.ts b/src/server/utilities.ts index 0976d3dd1e5..2d458c09b82 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -250,7 +250,7 @@ namespace ts.server { return; } - const insertIndex = binarySearch(array, insert, compare); + const insertIndex = binarySearch(array, insert, identity, compare); if (insertIndex < 0) { array.splice(~insertIndex, 0, insert); } @@ -266,7 +266,7 @@ namespace ts.server { return; } - const removeIndex = binarySearch(array, remove, compare); + const removeIndex = binarySearch(array, remove, identity, compare); if (removeIndex >= 0) { array.splice(removeIndex, 1); } diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index bc3a8e27ef0..f84292c5faf 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -581,7 +581,7 @@ namespace ts.textChanges { return applyFormatting(nonformattedText, sourceFile, initialIndentation, delta, this.rulesProvider); } - private static normalize(changes: Change[]): Change[] { + private static normalize(changes: Change[]) { // order changes by start position const normalized = stableSort(changes, (a, b) => a.range.pos - b.range.pos); // verify that change intervals do not overlap, except possibly at end points. From da63c2c57977840cf0b349c84ab139a92e6f4787 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 27 Oct 2017 16:24:12 -0700 Subject: [PATCH 024/138] 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 025/138] 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 e6cdd6334b0419bd4c3c9a6b4e924989e448f015 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Sun, 29 Oct 2017 12:35:48 -0700 Subject: [PATCH 026/138] PR Feedback --- src/compiler/core.ts | 29 +++++++++-------------------- src/compiler/types.ts | 3 --- src/harness/fourslash.ts | 1 - src/harness/runner.ts | 7 +++++-- 4 files changed, 14 insertions(+), 26 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 605cde05178..a3910334286 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -702,7 +702,7 @@ namespace ts { function deduplicateRelational(array: ReadonlyArray, equalityComparer: EqualityComparer, comparer: Comparer) { // Perform a stable sort of the array. This ensures the first entry in a list of // duplicates remains the first entry in the result. - const indices = sequence(0, array.length); + const indices = array.map((_, i) => i); stableSortIndices(array, indices, comparer); let last = array[indices[0]]; @@ -895,17 +895,6 @@ namespace ts { } } - /** - * Creates an array of integers starting at `from` (inclusive) and ending at `to` (exclusive). - */ - function sequence(from: number, to: number) { - const numbers: number[] = []; - for (let i = from; i < to; i++) { - numbers.push(i); - } - return numbers; - } - function stableSortIndices(array: ReadonlyArray, indices: number[], comparer: Comparer) { // sort indices by value then position indices.sort((x, y) => comparer(array[x], array[y]) || compareValues(x, y)); @@ -922,7 +911,7 @@ namespace ts { * Stable sort of an array. Elements equal to each other maintain their relative position in the array. */ export function stableSort(array: ReadonlyArray, comparer: Comparer) { - const indices = sequence(0, array.length); + const indices = array.map((_, i) => i); stableSortIndices(array, indices, comparer); return indices.map(i => array[i]) as ReadonlyArray as SortedReadonlyArray; } @@ -1009,7 +998,7 @@ namespace ts { * @param array A sorted array whose first element must be no larger than number * @param number The value to be searched for in the array. */ - export function binarySearch(array: ReadonlyArray, value: T, keySelector: Selector, keyComparer: Comparer, offset?: number): number { + export function binarySearch(array: ReadonlyArray, value: T, keySelector: (v: T) => U, keyComparer: Comparer, offset?: number): number { if (!array || array.length === 0) { return -1; } @@ -1764,8 +1753,8 @@ namespace ts { } })(); - let uiCS: Comparer | undefined; - let uiCI: Comparer | undefined; + let uiComparerCaseSensitive: Comparer | undefined; + let uiComparerCaseInsensitive: Comparer | undefined; let uiLocale: string | undefined; export function getUILocale() { @@ -1775,8 +1764,8 @@ namespace ts { export function setUILocale(value: string) { if (uiLocale !== value) { uiLocale = value; - uiCS = undefined; - uiCI = undefined; + uiComparerCaseSensitive = undefined; + uiComparerCaseInsensitive = undefined; } } @@ -1791,7 +1780,7 @@ namespace ts { * accents/diacritic marks as unequal. */ export function compareStringsCaseInsensitiveUI(a: string, b: string) { - const comparer = uiCI || (uiCI = createStringComparer(uiLocale, /*caseInsensitive*/ true)); + const comparer = uiComparerCaseInsensitive || (uiComparerCaseInsensitive = createStringComparer(uiLocale, /*caseInsensitive*/ true)); return comparer(a, b); } @@ -1806,7 +1795,7 @@ namespace ts { * accents/diacritic marks, or case as unequal. */ export function compareStringsCaseSensitiveUI(a: string, b: string) { - const comparer = uiCS || (uiCS = createStringComparer(uiLocale, /*caseInsensitive*/ false)); + const comparer = uiComparerCaseSensitive || (uiComparerCaseSensitive = createStringComparer(uiLocale, /*caseInsensitive*/ false)); return comparer(a, b); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3af3b6e022a..84028a23b0a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -54,9 +54,6 @@ namespace ts { GreaterThan = 1 } - /* @internal */ - export type Selector = (v: T) => U; - // branded string type used to store absolute, normalized and canonicalized paths // arbitrary file name can be converted to Path via toPath function export type Path = string & { __pathBrand: any }; diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index b52dbd6932a..d88f0e0854e 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -3129,7 +3129,6 @@ Actual: ${stringify(fullActual)}`); ${code} })`; try { - const test = new FourSlashInterface.Test(state); const goTo = new FourSlashInterface.GoTo(state); const verify = new FourSlashInterface.Verify(state); diff --git a/src/harness/runner.ts b/src/harness/runner.ts index 57955c9ab43..6ae94790e1b 100644 --- a/src/harness/runner.ts +++ b/src/harness/runner.ts @@ -208,8 +208,11 @@ function beginTests() { } // run tests in en-US by default. - const savedUILocale = ts.getUILocale(); - beforeEach(() => ts.setUILocale("en-US")); + let savedUILocale: string | undefined; + beforeEach(() => { + savedUILocale = ts.getUILocale(); + ts.setUILocale("en-US"); + }); afterEach(() => ts.setUILocale(savedUILocale)); runTests(runners); From fcb8296a05b687cfb9f5a30139bca037e6c2a175 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Sun, 29 Oct 2017 12:40:40 -0700 Subject: [PATCH 027/138] Updated comments --- src/compiler/core.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index a3910334286..7f165a171f8 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -992,11 +992,15 @@ namespace ts { } /** - * Performs a binary search, finding the index at which 'value' occurs in 'array'. + * Performs a binary search, finding the index at which `value` occurs in `array`. * If no such index is found, returns the 2's-complement of first index at which - * number[index] exceeds number. + * `array[index]` exceeds `value`. * @param array A sorted array whose first element must be no larger than number - * @param number The value to be searched for in the array. + * @param value The value to be searched for in the array. + * @param keySelector A callback used to select the search key from `value` and each element of + * `array`. + * @param keyComparer A callback used to compare two keys in a sorted array. + * @param offset An offset into `array` at which to start the search. */ export function binarySearch(array: ReadonlyArray, value: T, keySelector: (v: T) => U, keyComparer: Comparer, offset?: number): number { if (!array || array.length === 0) { From 1f961cda11bcc96ccd01f3fe88cd6e17b8b9c000 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Sun, 29 Oct 2017 13:24:22 -0700 Subject: [PATCH 028/138] PR Feedback, cleanup --- src/compiler/core.ts | 89 ++++++++++++++++++++++--------------------- src/compiler/types.ts | 5 --- 2 files changed, 46 insertions(+), 48 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 7f165a171f8..e66a43e0aeb 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -659,46 +659,6 @@ namespace ts { return [...array1, ...array2]; } - /** - * Deduplicates an array that has already been sorted. - */ - export function deduplicateSorted(array: SortedReadonlyArray, comparer: EqualityComparer | Comparer) { - if (!array) return undefined; - if (array.length === 0) return []; - - let last = array[0]; - const deduplicated: T[] = [last]; - for (let i = 1; i < array.length; i++) { - switch (comparer(last, array[i])) { - // equality comparison - case true: - - // relational comparison - case Comparison.LessThan: - case Comparison.EqualTo: - continue; - } - - deduplicated.push(last = array[i]); - } - - return deduplicated; - } - - /** - * Deduplicates an unsorted array. - * @param equalityComparer An optional `EqualityComparer` used to determine if two values are duplicates. - * @param comparer An optional `Comparer` used to sort entries before comparison. If supplied, - * results are returned in the original order found in `array`. - */ - export function deduplicate(array: ReadonlyArray, equalityComparer: EqualityComparer, comparer?: Comparer): T[] { - return !array ? undefined : - array.length === 0 ? [] : - array.length === 1 ? array.slice() : - comparer ? deduplicateRelational(array, equalityComparer, comparer) : - deduplicateEquality(array, equalityComparer); - } - function deduplicateRelational(array: ReadonlyArray, equalityComparer: EqualityComparer, comparer: Comparer) { // Perform a stable sort of the array. This ensures the first entry in a list of // duplicates remains the first entry in the result. @@ -729,6 +689,50 @@ namespace ts { return result; } + /** + * Deduplicates an unsorted array. + * @param equalityComparer An optional `EqualityComparer` used to determine if two values are duplicates. + * @param comparer An optional `Comparer` used to sort entries before comparison. If supplied, + * results are returned in the original order found in `array`. + */ + export function deduplicate(array: ReadonlyArray, equalityComparer: EqualityComparer, comparer?: Comparer): T[] { + return !array ? undefined : + array.length === 0 ? [] : + array.length === 1 ? array.slice() : + comparer ? deduplicateRelational(array, equalityComparer, comparer) : + deduplicateEquality(array, equalityComparer); + } + + /** + * Deduplicates an array that has already been sorted. + */ + function deduplicateSorted(array: ReadonlyArray, comparer: EqualityComparer | Comparer) { + if (!array) return undefined; + if (array.length === 0) return []; + + let last = array[0]; + const deduplicated: T[] = [last]; + for (let i = 1; i < array.length; i++) { + const next = array[i]; + switch (comparer(next, last)) { + // equality comparison + case true: + + // relational comparison + case Comparison.EqualTo: + continue; + + case Comparison.LessThan: + // If `array` is sorted, `next` should **never** be less than `last`. + return Debug.fail("Array is unsorted."); + } + + deduplicated.push(last = next); + } + + return deduplicated; + } + export function sortAndDeduplicate(array: ReadonlyArray, comparer: Comparer, equalityComparer?: EqualityComparer) { return deduplicateSorted(sort(array, comparer), equalityComparer || comparer); } @@ -904,7 +908,7 @@ namespace ts { * Returns a new sorted array. */ export function sort(array: ReadonlyArray, comparer: Comparer) { - return array.slice().sort(comparer) as ReadonlyArray as SortedReadonlyArray; + return array.slice().sort(comparer); } /** @@ -913,7 +917,7 @@ namespace ts { export function stableSort(array: ReadonlyArray, comparer: Comparer) { const indices = array.map((_, i) => i); stableSortIndices(array, indices, comparer); - return indices.map(i => array[i]) as ReadonlyArray as SortedReadonlyArray; + return indices.map(i => array[i]); } export function rangeEquals(array1: ReadonlyArray, array2: ReadonlyArray, pos: number, end: number) { @@ -2215,7 +2219,6 @@ namespace ts { return false; } - // File-system comparisons should use predictable ordering const equalityComparer = ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive; for (let i = 0; i < parentComponents.length; i++) { if (!equalityComparer(parentComponents[i], childComponents[i])) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 84028a23b0a..43ed345e220 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -36,11 +36,6 @@ namespace ts { push(...values: T[]): void; } - /* @internal */ - export interface SortedReadonlyArray extends ReadonlyArray { - " __sortedArrayBrand": any; - } - /* @internal */ export type EqualityComparer = (a: T, b: T) => boolean; From c83eeaaac7cc2e1988ea663471e40e33dd22ef32 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Sun, 29 Oct 2017 13:26:51 -0700 Subject: [PATCH 029/138] Added comment --- src/compiler/core.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index e66a43e0aeb..0ccb7253331 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1602,7 +1602,8 @@ namespace ts { } /** - * Compare two values for their order relative to each other. + * Compare two numeric values for their order relative to each other. + * To compare strings, use any of the `compareStrings` functions. */ export function compareValues(a: number, b: number) { return compareComparableValues(a, b); From 5395d0ddb872acb83c2cca3ec31240572082db05 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 30 Oct 2017 10:44:51 -0700 Subject: [PATCH 030/138] 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 967a426fe1d175a3cbfa0211df96e020a593507e Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 30 Oct 2017 17:19:27 -0700 Subject: [PATCH 031/138] Unify deduplication, fix deferred global diagnostics --- src/compiler/checker.ts | 8 +--- src/compiler/core.ts | 41 +++++-------------- src/compiler/utilities.ts | 8 ++++ src/harness/fourslash.ts | 24 +++++++++-- .../incrementalParsingDynamicImport1.ts | 6 +-- .../incrementalParsingDynamicImport3.ts | 2 +- 6 files changed, 45 insertions(+), 44 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index abedf405cde..39abb68de70 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7345,12 +7345,8 @@ namespace ts { return type.id; } - function binarySearchTypes(types: Type[], type: Type): number { - return binarySearch(types, type, getTypeId, compareValues); - } - function containsType(types: Type[], type: Type): boolean { - return binarySearchTypes(types, type) >= 0; + return binarySearch(types, type, getTypeId, compareValues) >= 0; } // Return true if the given intersection type contains (a) more than one unit type or (b) an object @@ -7391,7 +7387,7 @@ namespace ts { if (flags & TypeFlags.Number) typeSet.containsNumber = true; if (flags & TypeFlags.StringOrNumberLiteral) typeSet.containsStringOrNumberLiteral = true; const len = typeSet.length; - const index = len && type.id > typeSet[len - 1].id ? ~len : binarySearchTypes(typeSet, type); + const index = len && type.id > typeSet[len - 1].id ? ~len : binarySearch(typeSet, type, getTypeId, compareValues); if (index < 0) { if (!(flags & TypeFlags.Object && (type).objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && containsIdenticalType(typeSet, type))) { diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 0ccb7253331..dd30b36470f 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1017,15 +1017,15 @@ namespace ts { while (low <= high) { const middle = low + ((high - low) >> 1); const midKey = keySelector(array[middle]); - - if (keyComparer(midKey, key) === 0) { - return middle; - } - else if (keyComparer(midKey, key) > 0) { - high = middle - 1; - } - else { - low = middle + 1; + switch (keyComparer(midKey, key)) { + case Comparison.LessThan: + low = middle + 1; + break; + case Comparison.EqualTo: + return middle; + case Comparison.GreaterThan: + high = middle - 1; + break; } } @@ -1852,27 +1852,8 @@ namespace ts { return text1 ? Comparison.GreaterThan : Comparison.LessThan; } - export function sortAndDeduplicateDiagnostics(diagnostics: Diagnostic[]): Diagnostic[] { - return deduplicateSortedDiagnostics(diagnostics.sort(compareDiagnostics)); - } - - export function deduplicateSortedDiagnostics(diagnostics: Diagnostic[]): Diagnostic[] { - if (diagnostics.length < 2) { - return diagnostics; - } - - const newDiagnostics = [diagnostics[0]]; - let previousDiagnostic = diagnostics[0]; - for (let i = 1; i < diagnostics.length; i++) { - const currentDiagnostic = diagnostics[i]; - const isDupe = compareDiagnostics(currentDiagnostic, previousDiagnostic) === Comparison.EqualTo; - if (!isDupe) { - newDiagnostics.push(currentDiagnostic); - previousDiagnostic = currentDiagnostic; - } - } - - return newDiagnostics; + export function sortAndDeduplicateDiagnostics(diagnostics: ReadonlyArray): Diagnostic[] { + return sortAndDeduplicate(diagnostics, compareDiagnostics); } export function normalizeSlashes(path: string): string { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 1ade3cc6374..4e55ae04d03 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2291,6 +2291,7 @@ namespace ts { let nonFileDiagnostics: Diagnostic[] = []; const fileDiagnostics = createMap(); + let hasReadNonFileDiagnostics = false; let diagnosticsModified = false; let modificationCount = 0; @@ -2320,6 +2321,12 @@ namespace ts { } } else { + // If we've already read the non-file diagnostics, do not modify the existing array. + if (hasReadNonFileDiagnostics) { + hasReadNonFileDiagnostics = false; + nonFileDiagnostics = nonFileDiagnostics.slice(); + } + diagnostics = nonFileDiagnostics; } @@ -2330,6 +2337,7 @@ namespace ts { function getGlobalDiagnostics(): Diagnostic[] { sortAndDeduplicate(); + hasReadNonFileDiagnostics = true; return nonFileDiagnostics; } diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index d88f0e0854e..7ecf783aee6 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -531,15 +531,31 @@ namespace FourSlash { } for (const { start, length, messageText, file } of errors) { - Harness.IO.log(" from: " + showPosition(file, start) + - ", to: " + showPosition(file, start + length) + + Harness.IO.log(" " + this.formatRange(file, start, length) + ", message: " + ts.flattenDiagnosticMessageText(messageText, Harness.IO.newLine()) + "\n"); } + } - function showPosition(file: ts.SourceFile, pos: number) { + private formatRange(file: ts.SourceFile, start: number, length: number) { + if (file) { + return `from: ${this.formatLineAndCharacterOfPosition(file, start)}, to: ${this.formatLineAndCharacterOfPosition(file, start + length)}`; + } + return "global"; + } + + private formatLineAndCharacterOfPosition(file: ts.SourceFile, pos: number) { + if (file) { const { line, character } = ts.getLineAndCharacterOfPosition(file, pos); return `${line}:${character}`; } + return "global"; + } + + private formatPosition(file: ts.SourceFile, pos: number) { + if (file) { + return file.fileName + "@" + pos; + } + return "global"; } public verifyNoErrors() { @@ -549,7 +565,7 @@ namespace FourSlash { if (errors.length) { this.printErrorLog(/*expectErrors*/ false, errors); const error = errors[0]; - this.raiseError(`Found an error: ${error.file.fileName}@${error.start}: ${error.messageText}`); + this.raiseError(`Found an error: ${this.formatPosition(error.file, error.start)}: ${error.messageText}`); } }); } diff --git a/tests/cases/fourslash/incrementalParsingDynamicImport1.ts b/tests/cases/fourslash/incrementalParsingDynamicImport1.ts index 0f15dcb3b1b..511f3835f5b 100644 --- a/tests/cases/fourslash/incrementalParsingDynamicImport1.ts +++ b/tests/cases/fourslash/incrementalParsingDynamicImport1.ts @@ -7,11 +7,11 @@ //// var x1 = import("./foo"); //// x1.then(foo => { -//// var s: string = foo.bar(); +//// var s: string = foo.bar(); //// }) //// /*1*/ -verify.numberOfErrorsInCurrentFile(1); +verify.numberOfErrorsInCurrentFile(2); goTo.marker("1"); edit.insert(" "); -verify.numberOfErrorsInCurrentFile(1); \ No newline at end of file +verify.numberOfErrorsInCurrentFile(2); \ No newline at end of file diff --git a/tests/cases/fourslash/incrementalParsingDynamicImport3.ts b/tests/cases/fourslash/incrementalParsingDynamicImport3.ts index b3da4c5b538..64aca403ad9 100644 --- a/tests/cases/fourslash/incrementalParsingDynamicImport3.ts +++ b/tests/cases/fourslash/incrementalParsingDynamicImport3.ts @@ -11,4 +11,4 @@ verify.numberOfErrorsInCurrentFile(0); goTo.marker("1"); edit.insert("("); -verify.numberOfErrorsInCurrentFile(2); \ No newline at end of file +verify.numberOfErrorsInCurrentFile(3); \ No newline at end of file From 1d0a9ee453c476b6f8f19041085b23e0af1c3abf Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 31 Oct 2017 10:49:08 -0700 Subject: [PATCH 032/138] PR feedback --- src/compiler/core.ts | 46 +++++++++++-------------------------- src/services/textChanges.ts | 2 +- 2 files changed, 15 insertions(+), 33 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index dd30b36470f..e2e8a0096f5 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -295,29 +295,13 @@ namespace ts { Debug.fail(); } - function containsWithoutEqualityComparer(array: ReadonlyArray, value: T) { - for (const v of array) { - if (v === value) { - return true; - } - } - return false; - } - - function containsWithEqualityComparer(array: ReadonlyArray, value: T, equalityComparer: EqualityComparer) { - for (const v of array) { - if (equalityComparer(v, value)) { - return true; - } - } - return false; - } - - export function contains(array: ReadonlyArray, value: T, equalityComparer?: EqualityComparer): boolean { + export function contains(array: ReadonlyArray, value: T, equalityComparer: EqualityComparer = equateValues): boolean { if (array) { - return equalityComparer - ? containsWithEqualityComparer(array, value, equalityComparer) - : containsWithoutEqualityComparer(array, value); + for (const v of array) { + if (equalityComparer(v, value)) { + return true; + } + } } return false; } @@ -692,8 +676,8 @@ namespace ts { /** * Deduplicates an unsorted array. * @param equalityComparer An optional `EqualityComparer` used to determine if two values are duplicates. - * @param comparer An optional `Comparer` used to sort entries before comparison. If supplied, - * results are returned in the original order found in `array`. + * @param comparer An optional `Comparer` used to sort entries before comparison, though the + * result will remain in the original order in `array`. */ export function deduplicate(array: ReadonlyArray, equalityComparer: EqualityComparer, comparer?: Comparer): T[] { return !array ? undefined : @@ -798,14 +782,14 @@ namespace ts { } /** - * Gets the relative complement of `arrayA` with respect to `b`, returning the elements that + * Gets the relative complement of `arrayA` with respect to `arrayB`, returning the elements that * are not present in `arrayA` but are present in `arrayB`. Assumes both arrays are sorted * based on the provided comparer. */ - export function relativeComplement(arrayA: T[] | undefined, arrayB: T[] | undefined, comparer: Comparer, offsetA = 0, offsetB = 0): T[] | undefined { + export function relativeComplement(arrayA: T[] | undefined, arrayB: T[] | undefined, comparer: Comparer): T[] | undefined { if (!arrayB || !arrayA || arrayB.length === 0 || arrayA.length === 0) return arrayB; const result: T[] = []; - outer: for (; offsetB < arrayB.length; offsetB++) { + outer: for (let offsetA = 0, offsetB = 0; offsetB < arrayB.length; offsetB++) { inner: for (; offsetA < arrayA.length; offsetA++) { switch (comparer(arrayB[offsetB], arrayA[offsetA])) { case Comparison.LessThan: break inner; @@ -2467,10 +2451,9 @@ namespace ts { return flatten(results); function visitDirectory(path: string, absolutePath: string, depth: number | undefined) { - const entries = getFileSystemEntries(path); - const files = sort(entries.files, comparer); + const { files, directories } = getFileSystemEntries(path); - for (const current of files) { + for (const current of sort(files, comparer)) { const name = combinePaths(path, current); const absoluteName = combinePaths(absolutePath, current); if (extensions && !fileExtensionIsOneOf(name, extensions)) continue; @@ -2493,8 +2476,7 @@ namespace ts { } } - const directories = sort(entries.directories, comparer); - for (const current of directories) { + for (const current of sort(directories, comparer)) { const name = combinePaths(path, current); const absoluteName = combinePaths(absolutePath, current); if ((!includeDirectoryRegex || includeDirectoryRegex.test(absoluteName)) && diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index f84292c5faf..bc3a8e27ef0 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -581,7 +581,7 @@ namespace ts.textChanges { return applyFormatting(nonformattedText, sourceFile, initialIndentation, delta, this.rulesProvider); } - private static normalize(changes: Change[]) { + private static normalize(changes: Change[]): Change[] { // order changes by start position const normalized = stableSort(changes, (a, b) => a.range.pos - b.range.pos); // verify that change intervals do not overlap, except possibly at end points. From 88e56f39569196bafa55cddebd884dc256ef582b Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 31 Oct 2017 11:49:52 -0700 Subject: [PATCH 033/138] Assert arrays passed to relativeComplement are sorted --- src/compiler/core.ts | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index e2e8a0096f5..3907231a525 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -789,15 +789,37 @@ namespace ts { export function relativeComplement(arrayA: T[] | undefined, arrayB: T[] | undefined, comparer: Comparer): T[] | undefined { if (!arrayB || !arrayA || arrayB.length === 0 || arrayA.length === 0) return arrayB; const result: T[] = []; - outer: for (let offsetA = 0, offsetB = 0; offsetB < arrayB.length; offsetB++) { - inner: for (; offsetA < arrayA.length; offsetA++) { + loopB: for (let offsetA = 0, offsetB = 0; offsetB < arrayB.length; offsetB++) { + if (offsetB > 0) { + // Ensure `arrayB` is properly sorted. + Debug.assertGreaterThanOrEqual(comparer(arrayB[offsetB], arrayB[offsetB - 1]), Comparison.EqualTo); + } + + loopA: for (const startA = offsetA; offsetA < arrayA.length; offsetA++) { + if (offsetA > startA) { + // Ensure `arrayA` is properly sorted. We only need to perform this check if + // `offsetA` has changed since we entered the loop. + Debug.assertGreaterThanOrEqual(comparer(arrayA[offsetA], arrayA[offsetA - 1]), Comparison.EqualTo); + } + switch (comparer(arrayB[offsetB], arrayA[offsetA])) { - case Comparison.LessThan: break inner; - case Comparison.EqualTo: continue outer; - case Comparison.GreaterThan: continue inner; + case Comparison.LessThan: + // If B is less than A, B does not exist in arrayA. Add B to the result and + // move to the next element in arrayB without changing the current position + // in arrayA. + result.push(arrayB[offsetB]); + continue loopB; + case Comparison.EqualTo: + // If B is equal to A, B exists in arrayA. Move to the next element in + // arrayB without adding B to the result or changing the current position + // in arrayA. + continue loopB; + case Comparison.GreaterThan: + // If B is greater than A, we need to keep looking for B in arrayA. Move to + // the next element in arrayA and recheck. + continue loopA; } } - result.push(arrayB[offsetB]); } return result; } From 542a060875d1913ffa2117a43abec593cba86943 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 31 Oct 2017 12:33:35 -0700 Subject: [PATCH 034/138] Remove case-insensitive UI comparisons for now --- src/compiler/core.ts | 119 ++++++++++------------------------ src/services/navigationBar.ts | 2 +- 2 files changed, 37 insertions(+), 84 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 3907231a525..093653b8fec 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1653,17 +1653,11 @@ namespace ts { /** * Creates a string comparer for use with string collation in the UI. */ - const createStringComparer = (function () { - type CachedLocale = "en-US" | undefined; + const createUIStringComparer = (function () { + let defaultComparer: Comparer | undefined; + let enUSComparer: Comparer | undefined; - interface StringComparerCache { - default?: Comparer; - "en-US"?: Comparer; - } - - let caseInsensitiveCache: StringComparerCache | undefined; - let caseSensitiveCache: StringComparerCache | undefined; - const createStringComparerNoCache = getStringComparerFactory(); + const stringComparerFactory = getStringComparerFactory(); return createStringComparer; function compareWithCallback(a: string | undefined, b: string | undefined, comparer: (a: string, b: string) => number) { @@ -1674,56 +1668,41 @@ namespace ts { return value < 0 ? Comparison.LessThan : value > 0 ? Comparison.GreaterThan : Comparison.EqualTo; } - function createIntlCollatorStringComparer(locale: string | undefined, caseInsensitive: boolean): Comparer { - // Initialize the sort collator on first use - let comparer: Comparer = (a, b) => { - // Intl.Collator.prototype.compare is bound to the collator. See NOTE in - // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare - comparer = new Intl.Collator(locale, { usage: "sort", sensitivity: caseInsensitive ? "accent" : "variant" }).compare; - return comparer(a, b); - }; + function createIntlCollatorStringComparer(locale: string | undefined): Comparer { + // Intl.Collator.prototype.compare is bound to the collator. See NOTE in + // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare + const comparer = new Intl.Collator(locale, { usage: "sort", sensitivity: "variant" }).compare; return (a, b) => compareWithCallback(a, b, comparer); } - function createLocaleCompareStringComparer(locale: string | undefined, caseInsensitive: boolean): Comparer { + function createLocaleCompareStringComparer(locale: string | undefined): Comparer { // if the locale is not the default locale (`undefined`), use the fallback comparer. - return locale !== undefined ? createFallbackStringComparer(locale, caseInsensitive) : - caseInsensitive ? (a, b) => compareWithCallback(a, b, compareCaseInsensitive) : - (a, b) => compareWithCallback(a, b, compareCaseSensitive); + if (locale !== undefined) return createFallbackStringComparer(); - function compareCaseInsensitive(a: string, b: string) { - // for case-insensitive comparisons we always map both strings to their - // upper-case form as some unicode characters do not properly round-trip to - // lowercase (such as `ẞ` (German sharp capital s)). - return compareCaseSensitive(a.toLocaleUpperCase(), b.toLocaleUpperCase()); - } + return (a, b) => compareWithCallback(a, b, compareStrings); - function compareCaseSensitive(a: string, b: string) { + function compareStrings(a: string, b: string) { return a.localeCompare(b); } } - function createFallbackStringComparer(_locale: string | undefined, caseInsensitive: boolean): Comparer { - return caseInsensitive ? (a, b) => compareWithCallback(a, b, compareCaseInsensitive) : - (a, b) => compareWithCallback(a, b, compareCaseSensitiveDictionaryOrder); + function createFallbackStringComparer(): Comparer { + // An ordinal comparison puts "A" after "b", but for the UI we want "A" before "b". + // We first sort case insensitively. So "Aaa" will come before "baa". + // Then we sort case sensitively, so "aaa" will come before "Aaa". + // + // For case insensitive comparisons we always map both strings to their + // upper-case form as some unicode characters do not properly round-trip to + // lowercase (such as `ẞ` (German sharp capital s)). + return (a, b) => compareWithCallback(a, b, compareDictionaryOrder); - function compareCaseInsensitive(a: string, b: string) { - // for case-insensitive comparisons we always map both strings to their - // upper-case form as some unicode characters do not properly round-trip to - // lowercase (such as `ẞ` (German sharp capital s)). - return compareCaseSensitive(a.toUpperCase(), b.toUpperCase()); + function compareDictionaryOrder(a: string, b: string) { + return compareStrings(a.toUpperCase(), b.toUpperCase()) || compareStrings(a, b); } - function compareCaseSensitive(a: string, b: string) { + function compareStrings(a: string, b: string) { return a < b ? Comparison.LessThan : a > b ? Comparison.GreaterThan : Comparison.EqualTo; } - - function compareCaseSensitiveDictionaryOrder(a: string, b: string) { - // An ordinal comparison puts "A" after "b", but for the UI we want "A" before "b". - // We first sort case insensitively. So "Aaa" will come before "baa". - // Then we sort case sensitively, so "aaa" will come before "Aaa". - return compareCaseInsensitive(a, b) || compareCaseSensitive(a, b); - } } function getStringComparerFactory() { @@ -1744,32 +1723,22 @@ namespace ts { return createFallbackStringComparer; } - // Hold onto common string comparers. This avoids constantly reallocating comparers during - // tests. - function createStringComparerCached(locale: CachedLocale, caseInsensitive: boolean) { - const cacheKey = locale || "default"; - const cache = caseInsensitive - ? caseInsensitiveCache || (caseInsensitiveCache = {}) - : caseSensitiveCache || (caseSensitiveCache = {}); - - let comparer = cache[cacheKey]; - if (!comparer) { - comparer = createStringComparerNoCache(locale, caseInsensitive); - cache[cacheKey] = comparer; + function createStringComparer(locale: string | undefined) { + // Hold onto common string comparers. This avoids constantly reallocating comparers during + // tests. + if (locale === undefined) { + return defaultComparer || (defaultComparer = stringComparerFactory(locale)); + } + else if (locale === "en-US") { + return enUSComparer || (enUSComparer = stringComparerFactory(locale)); + } + else { + return stringComparerFactory(locale); } - - return comparer; - } - - function createStringComparer(locale: string | undefined, caseInsensitive: boolean) { - return locale === undefined || locale === "en-US" - ? createStringComparerCached(locale as CachedLocale, caseInsensitive) - : createStringComparerNoCache(locale, caseInsensitive); } })(); let uiComparerCaseSensitive: Comparer | undefined; - let uiComparerCaseInsensitive: Comparer | undefined; let uiLocale: string | undefined; export function getUILocale() { @@ -1780,25 +1749,9 @@ namespace ts { if (uiLocale !== value) { uiLocale = value; uiComparerCaseSensitive = undefined; - uiComparerCaseInsensitive = undefined; } } - /** - * Compare two strings using the case-insensitive sort behavior of the UI locale. - * - * Ordering is not predictable between different host locales, but is best for displaying - * ordered data for UI presentation. Characters with multiple unicode representations may - * be considered equal. - * - * Case-insensitive comparisons compare strings that differ in only base characters or - * accents/diacritic marks as unequal. - */ - export function compareStringsCaseInsensitiveUI(a: string, b: string) { - const comparer = uiComparerCaseInsensitive || (uiComparerCaseInsensitive = createStringComparer(uiLocale, /*caseInsensitive*/ true)); - return comparer(a, b); - } - /** * Compare two strings in a using the case-sensitive sort behavior of the UI locale. * @@ -1810,7 +1763,7 @@ namespace ts { * accents/diacritic marks, or case as unequal. */ export function compareStringsCaseSensitiveUI(a: string, b: string) { - const comparer = uiComparerCaseSensitive || (uiComparerCaseSensitive = createStringComparer(uiLocale, /*caseInsensitive*/ false)); + const comparer = uiComparerCaseSensitive || (uiComparerCaseSensitive = createUIStringComparer(uiLocale)); return comparer(a, b); } diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 712a315bb41..7d3b8e1845a 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -367,7 +367,7 @@ namespace ts.NavigationBar { } function compareChildren(child1: NavigationBarNode, child2: NavigationBarNode) { - return compareStringsCaseInsensitiveUI(tryGetName(child1.node), tryGetName(child2.node)) + return compareStringsCaseSensitiveUI(tryGetName(child1.node), tryGetName(child2.node)) || compareValues(navigationBarNodeKind(child1), navigationBarNodeKind(child2)); } From 5dc02ef5ccf267c0f4a07f4571d0b8d603a9eefa Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 31 Oct 2017 18:38:00 -0700 Subject: [PATCH 035/138] 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 a6a5b85b522b89d061aaf0baaaaf39103ba0c346 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 1 Nov 2017 10:33:24 -0700 Subject: [PATCH 036/138] Switch from undefined guard to asserts In both fixSpelling and getSuggestionForNonexistentSymbol --- src/compiler/checker.ts | 9 +++------ src/services/codefixes/fixSpelling.ts | 4 +++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 738a484d254..b28ecb082a1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15062,12 +15062,9 @@ namespace ts { return suggestion && symbolName(suggestion); } - function getSuggestionForNonexistentSymbol(location: Node, name: __String, meaning: SymbolFlags): string { - const result = resolveNameHelper(location, name, meaning, /*nameNotFoundMessage*/ undefined, name, /*isUse*/ false, (symbols, name, meaning) => { - // NOTE: `name` from the callback is supposed to === the outer `name`, but is undefined in some cases - if (name === undefined) { - return undefined; - } + function getSuggestionForNonexistentSymbol(location: Node, outerName: __String, meaning: SymbolFlags): string { + const result = resolveNameHelper(location, outerName, meaning, /*nameNotFoundMessage*/ undefined, outerName, /*isUse*/ false, (symbols, name, meaning) => { + Debug.assert(name !== undefined, "name should always be defined, and equal to " + outerName); const symbol = getSymbol(symbols, name, meaning); // Sometimes the symbol is found when location is a return type of a function: `typeof x` and `x` is declared in the body of the function // So the table *contains* `x` but `x` isn't actually in scope. diff --git a/src/services/codefixes/fixSpelling.ts b/src/services/codefixes/fixSpelling.ts index ff3bd455291..e5c15ade5a2 100644 --- a/src/services/codefixes/fixSpelling.ts +++ b/src/services/codefixes/fixSpelling.ts @@ -22,7 +22,9 @@ namespace ts.codefix { } else { const meaning = getMeaningFromLocation(node); - suggestion = checker.getSuggestionForNonexistentSymbol(node, getTextOfNode(node), convertSemanticMeaningToSymbolFlags(meaning)); + const name = getTextOfNode(node); + Debug.assert(!!name, "name should be defined"); + suggestion = checker.getSuggestionForNonexistentSymbol(node, name, convertSemanticMeaningToSymbolFlags(meaning)); } if (suggestion) { return [{ From 146addc4d54b4146da359e69d643ea85f39abb55 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 1 Nov 2017 10:35:54 -0700 Subject: [PATCH 037/138] Use explicit undefined checkk --- src/services/codefixes/fixSpelling.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/codefixes/fixSpelling.ts b/src/services/codefixes/fixSpelling.ts index e5c15ade5a2..2546a92a32f 100644 --- a/src/services/codefixes/fixSpelling.ts +++ b/src/services/codefixes/fixSpelling.ts @@ -23,7 +23,7 @@ namespace ts.codefix { else { const meaning = getMeaningFromLocation(node); const name = getTextOfNode(node); - Debug.assert(!!name, "name should be defined"); + Debug.assert(name !== undefined, "name should be defined"); suggestion = checker.getSuggestionForNonexistentSymbol(node, name, convertSemanticMeaningToSymbolFlags(meaning)); } if (suggestion) { From 5d7e87a9c21df96a31925b3bafab2e0267ffe02a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 1 Nov 2017 11:52:52 -0700 Subject: [PATCH 038/138] 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 039/138] 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 040/138] 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 041/138] 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 ed914a8d4755d8152040648faf25f8c65e01f1b9 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 3 Nov 2017 23:53:13 -0700 Subject: [PATCH 042/138] Fix new lint error --- 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 296a203a704..2113256346d 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1627,7 +1627,7 @@ namespace ts { /** * Creates a string comparer for use with string collation in the UI. */ - const createUIStringComparer = (function () { + const createUIStringComparer = (() => { let defaultComparer: Comparer | undefined; let enUSComparer: Comparer | undefined; 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 043/138] 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 044/138] 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 57be7ff3f646391d0d3f825d2705100d86a17101 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 6 Nov 2017 12:21:45 -0800 Subject: [PATCH 045/138] Add test case when inside wild card watched directory folder is renamed --- .../unittests/tsserverProjectSystem.ts | 53 +++++++++++++++++++ src/harness/virtualFileSystemWithWatch.ts | 37 ++++++++++++- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index c09a1bcb5da..b281f8763a0 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -2767,6 +2767,7 @@ namespace ts.projectSystem { watchedRecursiveDirectories.push(`${root}/a/b/src`, `${root}/a/b/node_modules`); checkWatchedDirectories(host, watchedRecursiveDirectories, /*recursive*/ true); }); + }); describe("Proper errors", () => { @@ -2869,6 +2870,58 @@ namespace ts.projectSystem { verifyNonExistentFile(/*useProjectRoot*/ false); }); }); + + it("folder rename updates project structure and reports no errors", () => { + const projectDir = "/a/b/projects/myproject"; + const app: FileOrFolder = { + path: `${projectDir}/bar/app.ts`, + content: "class Bar implements foo.Foo { getFoo() { return ''; } get2() { return 1; } }" + }; + const foo: FileOrFolder = { + path: `${projectDir}/foo/foo.ts`, + content: "declare namespace foo { interface Foo { get2(): number; getFoo(): string; } }" + }; + const configFile: FileOrFolder = { + path: `${projectDir}/tsconfig.json`, + content: JSON.stringify({ compilerOptions: { module: "none", targer: "es5" }, exclude: ["node_modules"] }) + }; + const host = createServerHost([app, foo, configFile]); + const session = createSession(host, { canUseEvents: true, }); + const projectService = session.getProjectService(); + + session.executeCommandSeq({ + command: server.CommandNames.Open, + arguments: { file: app.path, } + }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + assert.isDefined(projectService.configuredProjects.get(configFile.path)); + verifyErrorsInApp(); + + host.renameFolder(`${projectDir}/foo`, `${projectDir}/foo2`); + host.runQueuedTimeoutCallbacks(); + host.runQueuedTimeoutCallbacks(); + verifyErrorsInApp(); + + function verifyErrorsInApp() { + host.clearOutput(); + const expectedSequenceId = session.getNextSeq(); + session.executeCommandSeq({ + command: server.CommandNames.Geterr, + arguments: { + delay: 0, + files: [app.path] + } + }); + host.checkTimeoutQueueLengthAndRun(1); + checkErrorMessage(host, "syntaxDiag", { file: app.path, diagnostics: [] }); + host.clearOutput(); + + host.runQueuedImmediateCallbacks(); + checkErrorMessage(host, "semanticDiag", { file: app.path, diagnostics: [] }); + checkCompleteEvent(host, 2, expectedSequenceId); + host.clearOutput(); + } + }); }); describe("autoDiscovery", () => { diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 6c3bd8a635a..25581093f3d 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -346,6 +346,39 @@ interface Array {}` } } + renameFolder(folderName: string, newFolderName: string) { + const fullPath = getNormalizedAbsolutePath(folderName, this.currentDirectory); + const path = this.toPath(fullPath); + const folder = this.fs.get(path) as Folder; + Debug.assert(!!folder); + + // Only remove the folder + this.removeFileOrFolder(folder, returnFalse, /*isRenaming*/ true); + + // Add updated folder with new folder name + const newFullPath = getNormalizedAbsolutePath(newFolderName, this.currentDirectory); + const newFolder = this.toFolder(newFullPath); + const newPath = newFolder.path; + const basePath = getDirectoryPath(path); + Debug.assert(basePath !== path); + Debug.assert(basePath === getDirectoryPath(newPath)); + const baseFolder = this.fs.get(basePath) as Folder; + this.addFileOrFolderInFolder(baseFolder, newFolder); + + // Invoke watches for files in the folder as deleted (from old path) + for (const entry of folder.entries) { + Debug.assert(isFile(entry)); + this.fs.delete(entry.path); + this.invokeFileWatcher(entry.fullPath, FileWatcherEventKind.Deleted); + + entry.fullPath = combinePaths(newFullPath, getBaseFileName(entry.fullPath)); + entry.path = this.toPath(entry.fullPath); + newFolder.entries.push(entry); + this.fs.set(entry.path, entry); + this.invokeFileWatcher(entry.fullPath, FileWatcherEventKind.Created); + } + } + ensureFileOrFolder(fileOrDirectory: FileOrFolder, ignoreWatchInvokedWithTriggerAsFileCreate?: boolean) { if (isString(fileOrDirectory.content)) { const file = this.toFile(fileOrDirectory); @@ -393,7 +426,7 @@ interface Array {}` this.invokeDirectoryWatcher(folder.fullPath, fileOrDirectory.fullPath); } - private removeFileOrFolder(fileOrDirectory: File | Folder, isRemovableLeafFolder: (folder: Folder) => boolean) { + private removeFileOrFolder(fileOrDirectory: File | Folder, isRemovableLeafFolder: (folder: Folder) => boolean, isRenaming?: boolean) { const basePath = getDirectoryPath(fileOrDirectory.path); const baseFolder = this.fs.get(basePath) as Folder; if (basePath !== fileOrDirectory.path) { @@ -406,7 +439,7 @@ interface Array {}` this.invokeFileWatcher(fileOrDirectory.fullPath, FileWatcherEventKind.Deleted); } else { - Debug.assert(fileOrDirectory.entries.length === 0); + Debug.assert(fileOrDirectory.entries.length === 0 || isRenaming); const relativePath = this.getRelativePathToDirectory(fileOrDirectory.fullPath, fileOrDirectory.fullPath); // Invoke directory and recursive directory watcher for the folder // Here we arent invoking recursive directory watchers for the base folders 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 046/138] 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 047/138] 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 3f34525c81143e9b3d8fe728afa30eeaf0eb5bc4 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 6 Nov 2017 14:39:23 -0800 Subject: [PATCH 048/138] Handle the folder create/delete in the configured project --- src/compiler/core.ts | 17 ++++++--- src/compiler/watch.ts | 37 ++++++++++++------- src/compiler/watchUtilities.ts | 8 ++++ .../unittests/tsserverProjectSystem.ts | 6 +-- src/server/editorServices.ts | 26 +++++++++---- src/server/project.ts | 17 ++++++--- 6 files changed, 74 insertions(+), 37 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index f2249641ff4..8709d39aa8c 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2855,10 +2855,9 @@ namespace ts { function addOrDeleteFileOrDirectory(fileOrDirectory: string, fileOrDirectoryPath: Path) { const existingResult = getCachedFileSystemEntries(fileOrDirectoryPath); if (existingResult) { - // This was a folder already present, remove it if this doesnt exist any more - if (!host.directoryExists(fileOrDirectory)) { - cachedReadDirectoryResult.delete(fileOrDirectoryPath); - } + // Just clear the cache for now + // For now just clear the cache, since this could mean that multiple level entries might need to be re-evaluated + clearCache(); } else { // This was earlier a file (hence not in cached directory contents) @@ -2871,8 +2870,14 @@ namespace ts { fileExists: host.fileExists(fileOrDirectoryPath), directoryExists: host.directoryExists(fileOrDirectoryPath) }; - updateFilesOfFileSystemEntry(parentResult, baseName, fsQueryResult.fileExists); - updateFileSystemEntry(parentResult.directories, baseName, fsQueryResult.directoryExists); + if (fsQueryResult.directoryExists || hasEntry(parentResult.directories, baseName)) { + // Folder added or removed, clear the cache instead of updating the folder and its structure + clearCache(); + } + else { + // No need to update the directory structure, just files + updateFilesOfFileSystemEntry(parentResult, baseName, fsQueryResult.fileExists); + } return fsQueryResult; } } diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index 53692fe1e04..8e49bb71a15 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -230,7 +230,7 @@ namespace ts { function createWatchMode(rootFileNames: string[], compilerOptions: CompilerOptions, watchingHost?: WatchingSystemHost, configFileName?: string, configFileSpecs?: ConfigFileSpecs, configFileWildCardDirectories?: MapLike, optionsToExtendForConfigFile?: CompilerOptions) { let program: Program; - let needsReload: boolean; // true if the config file changed and needs to reload it from the disk + let reloadLevel: ConfigFileProgramReloadLevel; // level to indicate if the program needs to be reloaded from config file/just filenames etc let missingFilesMap: Map; // Map of file watchers for the missing files let watchedWildcardDirectories: Map; // map of watchers for the wild card directories in the config file let timerToUpdateProgram: any; // timer callback to recompile the program @@ -488,7 +488,7 @@ namespace ts { function scheduleProgramReload() { Debug.assert(!!configFileName); - needsReload = true; + reloadLevel = ConfigFileProgramReloadLevel.Full; scheduleProgramUpdate(); } @@ -496,17 +496,30 @@ namespace ts { timerToUpdateProgram = undefined; reportWatchDiagnostic(createCompilerDiagnostic(Diagnostics.File_change_detected_Starting_incremental_compilation)); - if (needsReload) { - reloadConfigFile(); + switch (reloadLevel) { + case ConfigFileProgramReloadLevel.Partial: + return reloadFileNamesFromConfigFile(); + case ConfigFileProgramReloadLevel.Full: + return reloadConfigFile(); + default: + return synchronizeProgram(); } - else { - synchronizeProgram(); + } + + function reloadFileNamesFromConfigFile() { + const result = getFileNamesFromConfigSpecs(configFileSpecs, getDirectoryPath(configFileName), compilerOptions, directoryStructureHost); + if (!configFileSpecs.filesSpecs && result.fileNames.length === 0) { + reportDiagnostic(getErrorForNoInputFiles(configFileSpecs, configFileName)); } + rootFileNames = result.fileNames; + + // Update the program + synchronizeProgram(); } function reloadConfigFile() { writeLog(`Reloading config file: ${configFileName}`); - needsReload = false; + reloadLevel = ConfigFileProgramReloadLevel.None; const cachedHost = directoryStructureHost as CachedDirectoryStructureHost; cachedHost.clearCache(); @@ -611,18 +624,14 @@ namespace ts { // If the the added or created file or directory is not supported file name, ignore the file // But when watched directory is added/removed, we need to reload the file list - if (fileOrDirectoryPath !== directory && !isSupportedSourceFileName(fileOrDirectory, compilerOptions)) { + if (fileOrDirectoryPath !== directory && hasExtension(fileOrDirectoryPath) && !isSupportedSourceFileName(fileOrDirectory, compilerOptions)) { writeLog(`Project: ${configFileName} Detected file add/remove of non supported extension: ${fileOrDirectory}`); return; } // Reload is pending, do the reload - if (!needsReload) { - const result = getFileNamesFromConfigSpecs(configFileSpecs, getDirectoryPath(configFileName), compilerOptions, directoryStructureHost); - if (!configFileSpecs.filesSpecs && result.fileNames.length === 0) { - reportDiagnostic(getErrorForNoInputFiles(configFileSpecs, configFileName)); - } - rootFileNames = result.fileNames; + if (reloadLevel !== ConfigFileProgramReloadLevel.Full) { + reloadLevel = ConfigFileProgramReloadLevel.Partial; // Schedule Update the program scheduleProgramUpdate(); diff --git a/src/compiler/watchUtilities.ts b/src/compiler/watchUtilities.ts index f39024d5a7c..0cf38f372d9 100644 --- a/src/compiler/watchUtilities.ts +++ b/src/compiler/watchUtilities.ts @@ -2,6 +2,14 @@ /* @internal */ namespace ts { + export enum ConfigFileProgramReloadLevel { + None, + /** Update the file name list from the disk */ + Partial, + /** Reload completely by re-reading contents of config file from disk and updating program */ + Full + } + /** * Updates the existing missing file watches with the new set of missing files after new program is created */ diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index b281f8763a0..fc38b2d7870 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -5710,8 +5710,8 @@ namespace ts.projectSystem { { "path": "/a/b/node_modules/.staging/lodash-b0733faa/index.js", "content": "module.exports = require('./lodash');" }, { "path": "/a/b/node_modules/.staging/typescript-8493ea5d/package.json.3017591594" } ].map(getRootedFileOrFolder)); - // Since we didnt add any supported extension file, there wont be any timeout scheduled - verifyAfterPartialOrCompleteNpmInstall(0); + // Since we added/removed folder, scheduled project update + verifyAfterPartialOrCompleteNpmInstall(2); // Remove file "/a/b/node_modules/.staging/typescript-8493ea5d/package.json.3017591594" filesAndFoldersToAdd.length--; @@ -5732,7 +5732,7 @@ namespace ts.projectSystem { { "path": "/a/b/node_modules/.staging/rxjs-22375c61/testing" }, { "path": "/a/b/node_modules/.staging/rxjs-22375c61/package.json.2252192041", "content": "{\n \"_args\": [\n [\n {\n \"raw\": \"rxjs@^5.4.2\",\n \"scope\": null,\n \"escapedName\": \"rxjs\",\n \"name\": \"rxjs\",\n \"rawSpec\": \"^5.4.2\",\n \"spec\": \">=5.4.2 <6.0.0\",\n \"type\": \"range\"\n },\n \"C:\\\\Users\\\\shkamat\\\\Desktop\\\\app\"\n ]\n ],\n \"_from\": \"rxjs@>=5.4.2 <6.0.0\",\n \"_id\": \"rxjs@5.4.3\",\n \"_inCache\": true,\n \"_location\": \"/rxjs\",\n \"_nodeVersion\": \"7.7.2\",\n \"_npmOperationalInternal\": {\n \"host\": \"s3://npm-registry-packages\",\n \"tmp\": \"tmp/rxjs-5.4.3.tgz_1502407898166_0.6800217325799167\"\n },\n \"_npmUser\": {\n \"name\": \"blesh\",\n \"email\": \"ben@benlesh.com\"\n },\n \"_npmVersion\": \"5.3.0\",\n \"_phantomChildren\": {},\n \"_requested\": {\n \"raw\": \"rxjs@^5.4.2\",\n \"scope\": null,\n \"escapedName\": \"rxjs\",\n \"name\": \"rxjs\",\n \"rawSpec\": \"^5.4.2\",\n \"spec\": \">=5.4.2 <6.0.0\",\n \"type\": \"range\"\n },\n \"_requiredBy\": [\n \"/\"\n ],\n \"_resolved\": \"https://registry.npmjs.org/rxjs/-/rxjs-5.4.3.tgz\",\n \"_shasum\": \"0758cddee6033d68e0fd53676f0f3596ce3d483f\",\n \"_shrinkwrap\": null,\n \"_spec\": \"rxjs@^5.4.2\",\n \"_where\": \"C:\\\\Users\\\\shkamat\\\\Desktop\\\\app\",\n \"author\": {\n \"name\": \"Ben Lesh\",\n \"email\": \"ben@benlesh.com\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/ReactiveX/RxJS/issues\"\n },\n \"config\": {\n \"commitizen\": {\n \"path\": \"cz-conventional-changelog\"\n }\n },\n \"contributors\": [\n {\n \"name\": \"Ben Lesh\",\n \"email\": \"ben@benlesh.com\"\n },\n {\n \"name\": \"Paul Taylor\",\n \"email\": \"paul.e.taylor@me.com\"\n },\n {\n \"name\": \"Jeff Cross\",\n \"email\": \"crossj@google.com\"\n },\n {\n \"name\": \"Matthew Podwysocki\",\n \"email\": \"matthewp@microsoft.com\"\n },\n {\n \"name\": \"OJ Kwon\",\n \"email\": \"kwon.ohjoong@gmail.com\"\n },\n {\n \"name\": \"Andre Staltz\",\n \"email\": \"andre@staltz.com\"\n }\n ],\n \"dependencies\": {\n \"symbol-observable\": \"^1.0.1\"\n },\n \"description\": \"Reactive Extensions for modern JavaScript\",\n \"devDependencies\": {\n \"babel-polyfill\": \"^6.23.0\",\n \"benchmark\": \"^2.1.0\",\n \"benchpress\": \"2.0.0-beta.1\",\n \"chai\": \"^3.5.0\",\n \"color\": \"^0.11.1\",\n \"colors\": \"1.1.2\",\n \"commitizen\": \"^2.8.6\",\n \"coveralls\": \"^2.11.13\",\n \"cz-conventional-changelog\": \"^1.2.0\",\n \"danger\": \"^1.1.0\",\n \"doctoc\": \"^1.0.0\",\n \"escape-string-regexp\": \"^1.0.5 \",\n \"esdoc\": \"^0.4.7\",\n \"eslint\": \"^3.8.0\",\n \"fs-extra\": \"^2.1.2\",\n \"get-folder-size\": \"^1.0.0\",\n \"glob\": \"^7.0.3\",\n \"gm\": \"^1.22.0\",\n \"google-closure-compiler-js\": \"^20170218.0.0\",\n \"gzip-size\": \"^3.0.0\",\n \"http-server\": \"^0.9.0\",\n \"husky\": \"^0.13.3\",\n \"lint-staged\": \"3.2.5\",\n \"lodash\": \"^4.15.0\",\n \"madge\": \"^1.4.3\",\n \"markdown-doctest\": \"^0.9.1\",\n \"minimist\": \"^1.2.0\",\n \"mkdirp\": \"^0.5.1\",\n \"mocha\": \"^3.0.2\",\n \"mocha-in-sauce\": \"0.0.1\",\n \"npm-run-all\": \"^4.0.2\",\n \"npm-scripts-info\": \"^0.3.4\",\n \"nyc\": \"^10.2.0\",\n \"opn-cli\": \"^3.1.0\",\n \"platform\": \"^1.3.1\",\n \"promise\": \"^7.1.1\",\n \"protractor\": \"^3.1.1\",\n \"rollup\": \"0.36.3\",\n \"rollup-plugin-inject\": \"^2.0.0\",\n \"rollup-plugin-node-resolve\": \"^2.0.0\",\n \"rx\": \"latest\",\n \"rxjs\": \"latest\",\n \"shx\": \"^0.2.2\",\n \"sinon\": \"^2.1.0\",\n \"sinon-chai\": \"^2.9.0\",\n \"source-map-support\": \"^0.4.0\",\n \"tslib\": \"^1.5.0\",\n \"tslint\": \"^4.4.2\",\n \"typescript\": \"~2.0.6\",\n \"typings\": \"^2.0.0\",\n \"validate-commit-msg\": \"^2.14.0\",\n \"watch\": \"^1.0.1\",\n \"webpack\": \"^1.13.1\",\n \"xmlhttprequest\": \"1.8.0\"\n },\n \"directories\": {},\n \"dist\": {\n \"integrity\": \"sha512-fSNi+y+P9ss+EZuV0GcIIqPUK07DEaMRUtLJvdcvMyFjc9dizuDjere+A4V7JrLGnm9iCc+nagV/4QdMTkqC4A==\",\n \"shasum\": \"0758cddee6033d68e0fd53676f0f3596ce3d483f\",\n \"tarball\": \"https://registry.npmjs.org/rxjs/-/rxjs-5.4.3.tgz\"\n },\n \"engines\": {\n \"npm\": \">=2.0.0\"\n },\n \"homepage\": \"https://github.com/ReactiveX/RxJS\",\n \"keywords\": [\n \"Rx\",\n \"RxJS\",\n \"ReactiveX\",\n \"ReactiveExtensions\",\n \"Streams\",\n \"Observables\",\n \"Observable\",\n \"Stream\",\n \"ES6\",\n \"ES2015\"\n ],\n \"license\": \"Apache-2.0\",\n \"lint-staged\": {\n \"*.@(js)\": [\n \"eslint --fix\",\n \"git add\"\n ],\n \"*.@(ts)\": [\n \"tslint --fix\",\n \"git add\"\n ]\n },\n \"main\": \"Rx.js\",\n \"maintainers\": [\n {\n \"name\": \"blesh\",\n \"email\": \"ben@benlesh.com\"\n }\n ],\n \"name\": \"rxjs\",\n \"optionalDependencies\": {},\n \"readme\": \"ERROR: No README data found!\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+ssh://git@github.com/ReactiveX/RxJS.git\"\n },\n \"scripts-info\": {\n \"info\": \"List available script\",\n \"build_all\": \"Build all packages (ES6, CJS, UMD) and generate packages\",\n \"build_cjs\": \"Build CJS package with clean up existing build, copy source into dist\",\n \"build_es6\": \"Build ES6 package with clean up existing build, copy source into dist\",\n \"build_closure_core\": \"Minify Global core build using closure compiler\",\n \"build_global\": \"Build Global package, then minify build\",\n \"build_perf\": \"Build CJS & Global build, run macro performance test\",\n \"build_test\": \"Build CJS package & test spec, execute mocha test runner\",\n \"build_cover\": \"Run lint to current code, build CJS & test spec, execute test coverage\",\n \"build_docs\": \"Build ES6 & global package, create documentation using it\",\n \"build_spec\": \"Build test specs\",\n \"check_circular_dependencies\": \"Check codebase has circular dependencies\",\n \"clean_spec\": \"Clean up existing test spec build output\",\n \"clean_dist_cjs\": \"Clean up existing CJS package output\",\n \"clean_dist_es6\": \"Clean up existing ES6 package output\",\n \"clean_dist_global\": \"Clean up existing Global package output\",\n \"commit\": \"Run git commit wizard\",\n \"compile_dist_cjs\": \"Compile codebase into CJS module\",\n \"compile_module_es6\": \"Compile codebase into ES6\",\n \"cover\": \"Execute test coverage\",\n \"lint_perf\": \"Run lint against performance test suite\",\n \"lint_spec\": \"Run lint against test spec\",\n \"lint_src\": \"Run lint against source\",\n \"lint\": \"Run lint against everything\",\n \"perf\": \"Run macro performance benchmark\",\n \"perf_micro\": \"Run micro performance benchmark\",\n \"test_mocha\": \"Execute mocha test runner against existing test spec build\",\n \"test_browser\": \"Execute mocha test runner on browser against existing test spec build\",\n \"test\": \"Clean up existing test spec build, build test spec and execute mocha test runner\",\n \"tests2png\": \"Generate marble diagram image from test spec\",\n \"watch\": \"Watch codebase, trigger compile when source code changes\"\n },\n \"typings\": \"Rx.d.ts\",\n \"version\": \"5.4.3\"\n}\n" } ].map(getRootedFileOrFolder)); - verifyAfterPartialOrCompleteNpmInstall(0); + verifyAfterPartialOrCompleteNpmInstall(2); // remove /a/b/node_modules/.staging/rxjs-22375c61/package.json.2252192041 filesAndFoldersToAdd.length--; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 086bb6b38d8..b7c0ba2bc21 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -799,17 +799,14 @@ namespace ts.server { // If the the added or created file or directory is not supported file name, ignore the file // But when watched directory is added/removed, we need to reload the file list - if (fileOrDirectoryPath !== directory && !isSupportedSourceFileName(fileOrDirectory, project.getCompilationSettings(), this.hostConfiguration.extraFileExtensions)) { + if (fileOrDirectoryPath !== directory && hasExtension(fileOrDirectoryPath) && !isSupportedSourceFileName(fileOrDirectory, project.getCompilationSettings(), this.hostConfiguration.extraFileExtensions)) { this.logger.info(`Project: ${configFilename} Detected file add/remove of non supported extension: ${fileOrDirectory}`); return; } // Reload is pending, do the reload - if (!project.pendingReload) { - const configFileSpecs = project.configFileSpecs; - const result = getFileNamesFromConfigSpecs(configFileSpecs, getDirectoryPath(configFilename), project.getCompilationSettings(), project.getCachedDirectoryStructureHost(), this.hostConfiguration.extraFileExtensions); - project.updateErrorOnNoInputFiles(result.fileNames.length !== 0); - this.updateNonInferredProjectFiles(project, result.fileNames, fileNamePropertyReader); + if (project.pendingReload !== ConfigFileProgramReloadLevel.Full) { + project.pendingReload = ConfigFileProgramReloadLevel.Partial; this.delayUpdateProjectGraphAndInferredProjectsRefresh(project); } }, @@ -842,7 +839,7 @@ namespace ts.server { } else { this.logConfigFileWatchUpdate(project.getConfigFilePath(), project.canonicalConfigFilePath, configFileExistenceInfo, ConfigFileWatcherStatus.ReloadingInferredRootFiles); - project.pendingReload = true; + project.pendingReload = ConfigFileProgramReloadLevel.Full; this.delayUpdateProjectGraph(project); // As we scheduled the update on configured project graph, // we would need to schedule the project reload for only the root of inferred projects @@ -1590,6 +1587,19 @@ namespace ts.server { this.addFilesToNonInferredProjectAndUpdateGraph(project, newUncheckedFiles, propertyReader, newTypeAcquisition); } + /** + * Reload the file names from config file specs and update the project graph + */ + /*@internal*/ + reloadFileNamesOfConfiguredProject(project: ConfiguredProject): boolean { + const configFileSpecs = project.configFileSpecs; + const configFileName = project.getConfigFilePath(); + const fileNamesResult = getFileNamesFromConfigSpecs(configFileSpecs, getDirectoryPath(configFileName), project.getCompilationSettings(), project.getCachedDirectoryStructureHost(), this.hostConfiguration.extraFileExtensions); + project.updateErrorOnNoInputFiles(fileNamesResult.fileNames.length !== 0); + this.updateNonInferredProjectFiles(project, fileNamesResult.fileNames, fileNamePropertyReader); + return project.updateGraph(); + } + /** * Read the config file of the project again and update the project */ @@ -1884,7 +1894,7 @@ namespace ts.server { } else if (!updatedProjects.has(configFileName)) { if (delayReload) { - project.pendingReload = true; + project.pendingReload = ConfigFileProgramReloadLevel.Full; this.delayUpdateProjectGraph(project); } else { diff --git a/src/server/project.ts b/src/server/project.ts index edb1d6730e9..edb05205df3 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -1121,7 +1121,7 @@ namespace ts.server { readonly canonicalConfigFilePath: NormalizedPath; /* @internal */ - pendingReload: boolean; + pendingReload: ConfigFileProgramReloadLevel; /*@internal*/ configFileSpecs: ConfigFileSpecs; @@ -1161,12 +1161,17 @@ namespace ts.server { * @returns: true if set of files in the project stays the same and false - otherwise. */ updateGraph(): boolean { - if (this.pendingReload) { - this.pendingReload = false; - this.projectService.reloadConfiguredProject(this); - return true; + const reloadLevel = this.pendingReload; + this.pendingReload = ConfigFileProgramReloadLevel.None; + switch (reloadLevel) { + case ConfigFileProgramReloadLevel.Partial: + return this.projectService.reloadFileNamesOfConfiguredProject(this); + case ConfigFileProgramReloadLevel.Full: + this.projectService.reloadConfiguredProject(this); + return true; + default: + return super.updateGraph(); } - return super.updateGraph(); } /*@internal*/ 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 049/138] 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 050/138] 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 051/138] 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 381ca45787a5fc65c5655537251c5dce7a156fe0 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 6 Nov 2017 18:10:02 -0800 Subject: [PATCH 052/138] Use an enum for Msg (#19773) --- src/server/server.ts | 2 +- src/server/utilities.ts | 19 +++++++++---------- .../reference/api/tsserverlibrary.d.ts | 16 ++++++++-------- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/server/server.ts b/src/server/server.ts index 457be4a9b9a..4902983ad45 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -200,7 +200,7 @@ namespace ts.server { return this.loggingEnabled() && this.level >= level; } - msg(s: string, type: Msg.Types = Msg.Err) { + msg(s: string, type: Msg = Msg.Err) { if (!this.canWrite) return; s = `[${nowString()}] ${s}\n`; diff --git a/src/server/utilities.ts b/src/server/utilities.ts index 096d4484154..72aae2f714b 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -19,20 +19,19 @@ namespace ts.server { info(s: string): void; startGroup(): void; endGroup(): void; - msg(s: string, type?: Msg.Types): void; + msg(s: string, type?: Msg): void; getLogFileName(): string; } + // TODO: Use a const enum (https://github.com/Microsoft/TypeScript/issues/16804) + export enum Msg { + Err = "Err", + Info = "Info", + Perf = "Perf", + } export namespace Msg { - // tslint:disable variable-name - export type Err = "Err"; - export const Err: Err = "Err"; - export type Info = "Info"; - export const Info: Info = "Info"; - export type Perf = "Perf"; - export const Perf: Perf = "Perf"; - export type Types = Err | Info | Perf; - // tslint:enable variable-name + /** @deprecated Only here for backwards-compatibility. Prefer just `Msg`. */ + export type Types = Msg; } function getProjectRootPath(project: Project): Path { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 85895ffbce4..415565a6fa1 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4779,17 +4779,17 @@ declare namespace ts.server { info(s: string): void; startGroup(): void; endGroup(): void; - msg(s: string, type?: Msg.Types): void; + msg(s: string, type?: Msg): void; getLogFileName(): string; } + enum Msg { + Err = "Err", + Info = "Info", + Perf = "Perf", + } namespace Msg { - type Err = "Err"; - const Err: Err; - type Info = "Info"; - const Info: Info; - type Perf = "Perf"; - const Perf: Perf; - type Types = Err | Info | Perf; + /** @deprecated Only here for backwards-compatibility. Prefer just `Msg`. */ + type Types = Msg; } function createInstallTypingsRequest(project: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray, cachePath?: string): DiscoverTypings; namespace Errors { From 3e7af1cf1240894f6232b5b9e0f30837177f3f64 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 6 Nov 2017 18:10:14 -0800 Subject: [PATCH 053/138] Move "ban-comma-operator" to tslint rules that we won't use (#19780) --- tslint.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tslint.json b/tslint.json index 497bd5e787a..98033b92265 100644 --- a/tslint.json +++ b/tslint.json @@ -79,7 +79,6 @@ // TODO "arrow-parens": false, // [true, "ban-single-arg-parens"] "arrow-return-shorthand": false, - "ban-comma-operator": false, "ban-types": false, "forin": false, "member-access": false, // [true, "no-public"] @@ -110,6 +109,7 @@ "no-consecutive-blank-lines": false, // Not doing + "ban-comma-operator": false, "max-classes-per-file": false, "member-ordering": false, "no-angle-bracket-type-assertion": false, From 40efd1b3bd14e7e15b98053e30e2e317e2344458 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 6 Nov 2017 18:13:20 -0800 Subject: [PATCH 054/138] Apply 'object-literal-key-quotes' tslint rule (#19737) * Apply 'object-literal-key-quotes' tslint rule * Convert to "consistent-as-needed" --- Gulpfile.ts | 20 +- src/compiler/checker.ts | 38 +- src/compiler/commandLineParser.ts | 38 +- src/compiler/transformers/jsx.ts | 506 +++++++++--------- src/compiler/visitor.ts | 18 +- .../unittests/configurationExtension.ts | 8 +- .../convertCompilerOptionsFromJson.ts | 174 +++--- .../convertTypeAcquisitionFromJson.ts | 40 +- src/harness/unittests/moduleResolution.ts | 6 +- .../unittests/reuseProgramStructure.ts | 12 +- .../unittests/services/preProcessFile.ts | 32 +- src/harness/unittests/transpile.ts | 6 +- src/harness/unittests/tscWatchMode.ts | 34 +- .../unittests/tsserverProjectSystem.ts | 130 ++--- src/harness/unittests/typingsInstaller.ts | 14 +- src/server/editorServices.ts | 32 +- src/server/server.ts | 2 +- tslint.json | 2 +- 18 files changed, 556 insertions(+), 556 deletions(-) diff --git a/Gulpfile.ts b/Gulpfile.ts index a75882c5f46..84770f7edbc 100644 --- a/Gulpfile.ts +++ b/Gulpfile.ts @@ -46,15 +46,15 @@ const cmdLineOptions = minimist(process.argv.slice(2), { boolean: ["debug", "inspect", "light", "colors", "lint", "soft"], string: ["browser", "tests", "host", "reporter", "stackTraceLimit", "timeout"], alias: { - b: "browser", - d: "debug", "debug-brk": "debug", - i: "inspect", "inspect-brk": "inspect", - t: "tests", test: "tests", - ru: "runners", runner: "runners", - r: "reporter", - c: "colors", color: "colors", - f: "files", file: "files", - w: "workers", + "b": "browser", + "d": "debug", "debug-brk": "debug", + "i": "inspect", "inspect-brk": "inspect", + "t": "tests", "test": "tests", + "ru": "runners", "runner": "runners", + "r": "reporter", + "c": "colors", "color": "colors", + "f": "files", "file": "files", + "w": "workers", }, default: { soft: false, @@ -1034,7 +1034,7 @@ gulp.task("update-sublime", "Updates the sublime plugin's tsserver", ["local", s }); gulp.task("build-rules", "Compiles tslint rules to js", () => { - const settings: tsc.Settings = getCompilerSettings({ module: "commonjs", "lib": ["es6"] }, /*useBuiltCompiler*/ false); + const settings: tsc.Settings = getCompilerSettings({ module: "commonjs", lib: ["es6"] }, /*useBuiltCompiler*/ false); const dest = path.join(builtLocalDirectory, "tslint"); return gulp.src("scripts/tslint/**/*.ts") .pipe(newer({ diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7d9a32a8f92..545f38461cb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -455,29 +455,29 @@ namespace ts { } const typeofEQFacts = createMapFromTemplate({ - "string": TypeFacts.TypeofEQString, - "number": TypeFacts.TypeofEQNumber, - "boolean": TypeFacts.TypeofEQBoolean, - "symbol": TypeFacts.TypeofEQSymbol, - "undefined": TypeFacts.EQUndefined, - "object": TypeFacts.TypeofEQObject, - "function": TypeFacts.TypeofEQFunction + string: TypeFacts.TypeofEQString, + number: TypeFacts.TypeofEQNumber, + boolean: TypeFacts.TypeofEQBoolean, + symbol: TypeFacts.TypeofEQSymbol, + undefined: TypeFacts.EQUndefined, + object: TypeFacts.TypeofEQObject, + function: TypeFacts.TypeofEQFunction }); const typeofNEFacts = createMapFromTemplate({ - "string": TypeFacts.TypeofNEString, - "number": TypeFacts.TypeofNENumber, - "boolean": TypeFacts.TypeofNEBoolean, - "symbol": TypeFacts.TypeofNESymbol, - "undefined": TypeFacts.NEUndefined, - "object": TypeFacts.TypeofNEObject, - "function": TypeFacts.TypeofNEFunction + string: TypeFacts.TypeofNEString, + number: TypeFacts.TypeofNENumber, + boolean: TypeFacts.TypeofNEBoolean, + symbol: TypeFacts.TypeofNESymbol, + undefined: TypeFacts.NEUndefined, + object: TypeFacts.TypeofNEObject, + function: TypeFacts.TypeofNEFunction }); const typeofTypesByName = createMapFromTemplate({ - "string": stringType, - "number": numberType, - "boolean": booleanType, - "symbol": esSymbolType, - "undefined": undefinedType + string: stringType, + number: numberType, + boolean: booleanType, + symbol: esSymbolType, + undefined: undefinedType }); const typeofType = createTypeofType(); diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 7ba9bd80843..43ea77c8020 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -76,13 +76,13 @@ namespace ts { name: "target", shortName: "t", type: createMapFromTemplate({ - "es3": ScriptTarget.ES3, - "es5": ScriptTarget.ES5, - "es6": ScriptTarget.ES2015, - "es2015": ScriptTarget.ES2015, - "es2016": ScriptTarget.ES2016, - "es2017": ScriptTarget.ES2017, - "esnext": ScriptTarget.ESNext, + es3: ScriptTarget.ES3, + es5: ScriptTarget.ES5, + es6: ScriptTarget.ES2015, + es2015: ScriptTarget.ES2015, + es2016: ScriptTarget.ES2016, + es2017: ScriptTarget.ES2017, + esnext: ScriptTarget.ESNext, }), paramType: Diagnostics.VERSION, showInSimplifiedHelpView: true, @@ -93,14 +93,14 @@ namespace ts { name: "module", shortName: "m", type: createMapFromTemplate({ - "none": ModuleKind.None, - "commonjs": ModuleKind.CommonJS, - "amd": ModuleKind.AMD, - "system": ModuleKind.System, - "umd": ModuleKind.UMD, - "es6": ModuleKind.ES2015, - "es2015": ModuleKind.ES2015, - "esnext": ModuleKind.ESNext + none: ModuleKind.None, + commonjs: ModuleKind.CommonJS, + amd: ModuleKind.AMD, + system: ModuleKind.System, + umd: ModuleKind.UMD, + es6: ModuleKind.ES2015, + es2015: ModuleKind.ES2015, + esnext: ModuleKind.ESNext }), paramType: Diagnostics.KIND, showInSimplifiedHelpView: true, @@ -326,8 +326,8 @@ namespace ts { { name: "moduleResolution", type: createMapFromTemplate({ - "node": ModuleResolutionKind.NodeJs, - "classic": ModuleResolutionKind.Classic, + node: ModuleResolutionKind.NodeJs, + classic: ModuleResolutionKind.Classic, }), paramType: Diagnostics.STRATEGY, category: Diagnostics.Module_Resolution_Options, @@ -522,8 +522,8 @@ namespace ts { { name: "newLine", type: createMapFromTemplate({ - "crlf": NewLineKind.CarriageReturnLineFeed, - "lf": NewLineKind.LineFeed + crlf: NewLineKind.CarriageReturnLineFeed, + lf: NewLineKind.LineFeed }), paramType: Diagnostics.NEWLINE, category: Diagnostics.Advanced_Options, diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index 2be6cdef0bc..ab44db8ef4b 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -309,258 +309,258 @@ namespace ts { } const entities = createMapFromTemplate({ - "quot": 0x0022, - "amp": 0x0026, - "apos": 0x0027, - "lt": 0x003C, - "gt": 0x003E, - "nbsp": 0x00A0, - "iexcl": 0x00A1, - "cent": 0x00A2, - "pound": 0x00A3, - "curren": 0x00A4, - "yen": 0x00A5, - "brvbar": 0x00A6, - "sect": 0x00A7, - "uml": 0x00A8, - "copy": 0x00A9, - "ordf": 0x00AA, - "laquo": 0x00AB, - "not": 0x00AC, - "shy": 0x00AD, - "reg": 0x00AE, - "macr": 0x00AF, - "deg": 0x00B0, - "plusmn": 0x00B1, - "sup2": 0x00B2, - "sup3": 0x00B3, - "acute": 0x00B4, - "micro": 0x00B5, - "para": 0x00B6, - "middot": 0x00B7, - "cedil": 0x00B8, - "sup1": 0x00B9, - "ordm": 0x00BA, - "raquo": 0x00BB, - "frac14": 0x00BC, - "frac12": 0x00BD, - "frac34": 0x00BE, - "iquest": 0x00BF, - "Agrave": 0x00C0, - "Aacute": 0x00C1, - "Acirc": 0x00C2, - "Atilde": 0x00C3, - "Auml": 0x00C4, - "Aring": 0x00C5, - "AElig": 0x00C6, - "Ccedil": 0x00C7, - "Egrave": 0x00C8, - "Eacute": 0x00C9, - "Ecirc": 0x00CA, - "Euml": 0x00CB, - "Igrave": 0x00CC, - "Iacute": 0x00CD, - "Icirc": 0x00CE, - "Iuml": 0x00CF, - "ETH": 0x00D0, - "Ntilde": 0x00D1, - "Ograve": 0x00D2, - "Oacute": 0x00D3, - "Ocirc": 0x00D4, - "Otilde": 0x00D5, - "Ouml": 0x00D6, - "times": 0x00D7, - "Oslash": 0x00D8, - "Ugrave": 0x00D9, - "Uacute": 0x00DA, - "Ucirc": 0x00DB, - "Uuml": 0x00DC, - "Yacute": 0x00DD, - "THORN": 0x00DE, - "szlig": 0x00DF, - "agrave": 0x00E0, - "aacute": 0x00E1, - "acirc": 0x00E2, - "atilde": 0x00E3, - "auml": 0x00E4, - "aring": 0x00E5, - "aelig": 0x00E6, - "ccedil": 0x00E7, - "egrave": 0x00E8, - "eacute": 0x00E9, - "ecirc": 0x00EA, - "euml": 0x00EB, - "igrave": 0x00EC, - "iacute": 0x00ED, - "icirc": 0x00EE, - "iuml": 0x00EF, - "eth": 0x00F0, - "ntilde": 0x00F1, - "ograve": 0x00F2, - "oacute": 0x00F3, - "ocirc": 0x00F4, - "otilde": 0x00F5, - "ouml": 0x00F6, - "divide": 0x00F7, - "oslash": 0x00F8, - "ugrave": 0x00F9, - "uacute": 0x00FA, - "ucirc": 0x00FB, - "uuml": 0x00FC, - "yacute": 0x00FD, - "thorn": 0x00FE, - "yuml": 0x00FF, - "OElig": 0x0152, - "oelig": 0x0153, - "Scaron": 0x0160, - "scaron": 0x0161, - "Yuml": 0x0178, - "fnof": 0x0192, - "circ": 0x02C6, - "tilde": 0x02DC, - "Alpha": 0x0391, - "Beta": 0x0392, - "Gamma": 0x0393, - "Delta": 0x0394, - "Epsilon": 0x0395, - "Zeta": 0x0396, - "Eta": 0x0397, - "Theta": 0x0398, - "Iota": 0x0399, - "Kappa": 0x039A, - "Lambda": 0x039B, - "Mu": 0x039C, - "Nu": 0x039D, - "Xi": 0x039E, - "Omicron": 0x039F, - "Pi": 0x03A0, - "Rho": 0x03A1, - "Sigma": 0x03A3, - "Tau": 0x03A4, - "Upsilon": 0x03A5, - "Phi": 0x03A6, - "Chi": 0x03A7, - "Psi": 0x03A8, - "Omega": 0x03A9, - "alpha": 0x03B1, - "beta": 0x03B2, - "gamma": 0x03B3, - "delta": 0x03B4, - "epsilon": 0x03B5, - "zeta": 0x03B6, - "eta": 0x03B7, - "theta": 0x03B8, - "iota": 0x03B9, - "kappa": 0x03BA, - "lambda": 0x03BB, - "mu": 0x03BC, - "nu": 0x03BD, - "xi": 0x03BE, - "omicron": 0x03BF, - "pi": 0x03C0, - "rho": 0x03C1, - "sigmaf": 0x03C2, - "sigma": 0x03C3, - "tau": 0x03C4, - "upsilon": 0x03C5, - "phi": 0x03C6, - "chi": 0x03C7, - "psi": 0x03C8, - "omega": 0x03C9, - "thetasym": 0x03D1, - "upsih": 0x03D2, - "piv": 0x03D6, - "ensp": 0x2002, - "emsp": 0x2003, - "thinsp": 0x2009, - "zwnj": 0x200C, - "zwj": 0x200D, - "lrm": 0x200E, - "rlm": 0x200F, - "ndash": 0x2013, - "mdash": 0x2014, - "lsquo": 0x2018, - "rsquo": 0x2019, - "sbquo": 0x201A, - "ldquo": 0x201C, - "rdquo": 0x201D, - "bdquo": 0x201E, - "dagger": 0x2020, - "Dagger": 0x2021, - "bull": 0x2022, - "hellip": 0x2026, - "permil": 0x2030, - "prime": 0x2032, - "Prime": 0x2033, - "lsaquo": 0x2039, - "rsaquo": 0x203A, - "oline": 0x203E, - "frasl": 0x2044, - "euro": 0x20AC, - "image": 0x2111, - "weierp": 0x2118, - "real": 0x211C, - "trade": 0x2122, - "alefsym": 0x2135, - "larr": 0x2190, - "uarr": 0x2191, - "rarr": 0x2192, - "darr": 0x2193, - "harr": 0x2194, - "crarr": 0x21B5, - "lArr": 0x21D0, - "uArr": 0x21D1, - "rArr": 0x21D2, - "dArr": 0x21D3, - "hArr": 0x21D4, - "forall": 0x2200, - "part": 0x2202, - "exist": 0x2203, - "empty": 0x2205, - "nabla": 0x2207, - "isin": 0x2208, - "notin": 0x2209, - "ni": 0x220B, - "prod": 0x220F, - "sum": 0x2211, - "minus": 0x2212, - "lowast": 0x2217, - "radic": 0x221A, - "prop": 0x221D, - "infin": 0x221E, - "ang": 0x2220, - "and": 0x2227, - "or": 0x2228, - "cap": 0x2229, - "cup": 0x222A, - "int": 0x222B, - "there4": 0x2234, - "sim": 0x223C, - "cong": 0x2245, - "asymp": 0x2248, - "ne": 0x2260, - "equiv": 0x2261, - "le": 0x2264, - "ge": 0x2265, - "sub": 0x2282, - "sup": 0x2283, - "nsub": 0x2284, - "sube": 0x2286, - "supe": 0x2287, - "oplus": 0x2295, - "otimes": 0x2297, - "perp": 0x22A5, - "sdot": 0x22C5, - "lceil": 0x2308, - "rceil": 0x2309, - "lfloor": 0x230A, - "rfloor": 0x230B, - "lang": 0x2329, - "rang": 0x232A, - "loz": 0x25CA, - "spades": 0x2660, - "clubs": 0x2663, - "hearts": 0x2665, - "diams": 0x2666 + quot: 0x0022, + amp: 0x0026, + apos: 0x0027, + lt: 0x003C, + gt: 0x003E, + nbsp: 0x00A0, + iexcl: 0x00A1, + cent: 0x00A2, + pound: 0x00A3, + curren: 0x00A4, + yen: 0x00A5, + brvbar: 0x00A6, + sect: 0x00A7, + uml: 0x00A8, + copy: 0x00A9, + ordf: 0x00AA, + laquo: 0x00AB, + not: 0x00AC, + shy: 0x00AD, + reg: 0x00AE, + macr: 0x00AF, + deg: 0x00B0, + plusmn: 0x00B1, + sup2: 0x00B2, + sup3: 0x00B3, + acute: 0x00B4, + micro: 0x00B5, + para: 0x00B6, + middot: 0x00B7, + cedil: 0x00B8, + sup1: 0x00B9, + ordm: 0x00BA, + raquo: 0x00BB, + frac14: 0x00BC, + frac12: 0x00BD, + frac34: 0x00BE, + iquest: 0x00BF, + Agrave: 0x00C0, + Aacute: 0x00C1, + Acirc: 0x00C2, + Atilde: 0x00C3, + Auml: 0x00C4, + Aring: 0x00C5, + AElig: 0x00C6, + Ccedil: 0x00C7, + Egrave: 0x00C8, + Eacute: 0x00C9, + Ecirc: 0x00CA, + Euml: 0x00CB, + Igrave: 0x00CC, + Iacute: 0x00CD, + Icirc: 0x00CE, + Iuml: 0x00CF, + ETH: 0x00D0, + Ntilde: 0x00D1, + Ograve: 0x00D2, + Oacute: 0x00D3, + Ocirc: 0x00D4, + Otilde: 0x00D5, + Ouml: 0x00D6, + times: 0x00D7, + Oslash: 0x00D8, + Ugrave: 0x00D9, + Uacute: 0x00DA, + Ucirc: 0x00DB, + Uuml: 0x00DC, + Yacute: 0x00DD, + THORN: 0x00DE, + szlig: 0x00DF, + agrave: 0x00E0, + aacute: 0x00E1, + acirc: 0x00E2, + atilde: 0x00E3, + auml: 0x00E4, + aring: 0x00E5, + aelig: 0x00E6, + ccedil: 0x00E7, + egrave: 0x00E8, + eacute: 0x00E9, + ecirc: 0x00EA, + euml: 0x00EB, + igrave: 0x00EC, + iacute: 0x00ED, + icirc: 0x00EE, + iuml: 0x00EF, + eth: 0x00F0, + ntilde: 0x00F1, + ograve: 0x00F2, + oacute: 0x00F3, + ocirc: 0x00F4, + otilde: 0x00F5, + ouml: 0x00F6, + divide: 0x00F7, + oslash: 0x00F8, + ugrave: 0x00F9, + uacute: 0x00FA, + ucirc: 0x00FB, + uuml: 0x00FC, + yacute: 0x00FD, + thorn: 0x00FE, + yuml: 0x00FF, + OElig: 0x0152, + oelig: 0x0153, + Scaron: 0x0160, + scaron: 0x0161, + Yuml: 0x0178, + fnof: 0x0192, + circ: 0x02C6, + tilde: 0x02DC, + Alpha: 0x0391, + Beta: 0x0392, + Gamma: 0x0393, + Delta: 0x0394, + Epsilon: 0x0395, + Zeta: 0x0396, + Eta: 0x0397, + Theta: 0x0398, + Iota: 0x0399, + Kappa: 0x039A, + Lambda: 0x039B, + Mu: 0x039C, + Nu: 0x039D, + Xi: 0x039E, + Omicron: 0x039F, + Pi: 0x03A0, + Rho: 0x03A1, + Sigma: 0x03A3, + Tau: 0x03A4, + Upsilon: 0x03A5, + Phi: 0x03A6, + Chi: 0x03A7, + Psi: 0x03A8, + Omega: 0x03A9, + alpha: 0x03B1, + beta: 0x03B2, + gamma: 0x03B3, + delta: 0x03B4, + epsilon: 0x03B5, + zeta: 0x03B6, + eta: 0x03B7, + theta: 0x03B8, + iota: 0x03B9, + kappa: 0x03BA, + lambda: 0x03BB, + mu: 0x03BC, + nu: 0x03BD, + xi: 0x03BE, + omicron: 0x03BF, + pi: 0x03C0, + rho: 0x03C1, + sigmaf: 0x03C2, + sigma: 0x03C3, + tau: 0x03C4, + upsilon: 0x03C5, + phi: 0x03C6, + chi: 0x03C7, + psi: 0x03C8, + omega: 0x03C9, + thetasym: 0x03D1, + upsih: 0x03D2, + piv: 0x03D6, + ensp: 0x2002, + emsp: 0x2003, + thinsp: 0x2009, + zwnj: 0x200C, + zwj: 0x200D, + lrm: 0x200E, + rlm: 0x200F, + ndash: 0x2013, + mdash: 0x2014, + lsquo: 0x2018, + rsquo: 0x2019, + sbquo: 0x201A, + ldquo: 0x201C, + rdquo: 0x201D, + bdquo: 0x201E, + dagger: 0x2020, + Dagger: 0x2021, + bull: 0x2022, + hellip: 0x2026, + permil: 0x2030, + prime: 0x2032, + Prime: 0x2033, + lsaquo: 0x2039, + rsaquo: 0x203A, + oline: 0x203E, + frasl: 0x2044, + euro: 0x20AC, + image: 0x2111, + weierp: 0x2118, + real: 0x211C, + trade: 0x2122, + alefsym: 0x2135, + larr: 0x2190, + uarr: 0x2191, + rarr: 0x2192, + darr: 0x2193, + harr: 0x2194, + crarr: 0x21B5, + lArr: 0x21D0, + uArr: 0x21D1, + rArr: 0x21D2, + dArr: 0x21D3, + hArr: 0x21D4, + forall: 0x2200, + part: 0x2202, + exist: 0x2203, + empty: 0x2205, + nabla: 0x2207, + isin: 0x2208, + notin: 0x2209, + ni: 0x220B, + prod: 0x220F, + sum: 0x2211, + minus: 0x2212, + lowast: 0x2217, + radic: 0x221A, + prop: 0x221D, + infin: 0x221E, + ang: 0x2220, + and: 0x2227, + or: 0x2228, + cap: 0x2229, + cup: 0x222A, + int: 0x222B, + there4: 0x2234, + sim: 0x223C, + cong: 0x2245, + asymp: 0x2248, + ne: 0x2260, + equiv: 0x2261, + le: 0x2264, + ge: 0x2265, + sub: 0x2282, + sup: 0x2283, + nsub: 0x2284, + sube: 0x2286, + supe: 0x2287, + oplus: 0x2295, + otimes: 0x2297, + perp: 0x22A5, + sdot: 0x22C5, + lceil: 0x2308, + rceil: 0x2309, + lfloor: 0x230A, + rfloor: 0x230B, + lang: 0x2329, + rang: 0x232A, + loz: 0x25CA, + spades: 0x2660, + clubs: 0x2663, + hearts: 0x2665, + diams: 0x2666 }); } \ No newline at end of file diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 0428d2d2d2e..0b40e20a7b7 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -1585,13 +1585,13 @@ namespace ts { // Add additional properties in debug mode to assist with debugging. Object.defineProperties(objectAllocator.getSymbolConstructor().prototype, { - "__debugFlags": { get(this: Symbol) { return formatSymbolFlags(this.flags); } } + __debugFlags: { get(this: Symbol) { return formatSymbolFlags(this.flags); } } }); Object.defineProperties(objectAllocator.getTypeConstructor().prototype, { - "__debugFlags": { get(this: Type) { return formatTypeFlags(this.flags); } }, - "__debugObjectFlags": { get(this: Type) { return this.flags & TypeFlags.Object ? formatObjectFlags((this).objectFlags) : ""; } }, - "__debugTypeToString": { value(this: Type) { return this.checker.typeToString(this); } }, + __debugFlags: { get(this: Type) { return formatTypeFlags(this.flags); } }, + __debugObjectFlags: { get(this: Type) { return this.flags & TypeFlags.Object ? formatObjectFlags((this).objectFlags) : ""; } }, + __debugTypeToString: { value(this: Type) { return this.checker.typeToString(this); } }, }); const nodeConstructors = [ @@ -1604,11 +1604,11 @@ namespace ts { for (const ctor of nodeConstructors) { if (!ctor.prototype.hasOwnProperty("__debugKind")) { Object.defineProperties(ctor.prototype, { - "__debugKind": { get(this: Node) { return formatSyntaxKind(this.kind); } }, - "__debugModifierFlags": { get(this: Node) { return formatModifierFlags(getModifierFlagsNoCache(this)); } }, - "__debugTransformFlags": { get(this: Node) { return formatTransformFlags(this.transformFlags); } }, - "__debugEmitFlags": { get(this: Node) { return formatEmitFlags(getEmitFlags(this)); } }, - "__debugGetText": { + __debugKind: { get(this: Node) { return formatSyntaxKind(this.kind); } }, + __debugModifierFlags: { get(this: Node) { return formatModifierFlags(getModifierFlagsNoCache(this)); } }, + __debugTransformFlags: { get(this: Node) { return formatTransformFlags(this.transformFlags); } }, + __debugEmitFlags: { get(this: Node) { return formatEmitFlags(getEmitFlags(this)); } }, + __debugGetText: { value(this: Node, includeTrivia?: boolean) { if (nodeIsSynthesized(this)) return ""; const parseNode = getParseTreeNode(this); diff --git a/src/harness/unittests/configurationExtension.ts b/src/harness/unittests/configurationExtension.ts index 0032505aba1..5a1b155fbcf 100644 --- a/src/harness/unittests/configurationExtension.ts +++ b/src/harness/unittests/configurationExtension.ts @@ -25,9 +25,9 @@ namespace ts { }, "/dev/configs/tests.json": { compilerOptions: { - "preserveConstEnums": true, - "removeComments": false, - "sourceMap": true + preserveConstEnums: true, + removeComments: false, + sourceMap: true }, exclude: [ "../tests/baselines", @@ -52,7 +52,7 @@ namespace ts { "/dev/missing.json": { extends: "./missing2", compilerOptions: { - "types": [] + types: [] } }, "/dev/failure.json": { diff --git a/src/harness/unittests/convertCompilerOptionsFromJson.ts b/src/harness/unittests/convertCompilerOptionsFromJson.ts index cbbe41ceadf..3a73971d7a3 100644 --- a/src/harness/unittests/convertCompilerOptionsFromJson.ts +++ b/src/harness/unittests/convertCompilerOptionsFromJson.ts @@ -58,12 +58,12 @@ namespace ts { it("Convert correctly format tsconfig.json to compiler-options ", () => { assertCompilerOptions( { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "lib": ["es5", "es2015.core", "es2015.symbol"] + compilerOptions: { + module: "commonjs", + target: "es5", + noImplicitAny: false, + sourceMap: false, + lib: ["es5", "es2015.core", "es2015.symbol"] } }, "tsconfig.json", { @@ -82,13 +82,13 @@ namespace ts { it("Convert correctly format tsconfig.json with allowJs is false to compiler-options ", () => { assertCompilerOptions( { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "allowJs": false, - "lib": ["es5", "es2015.core", "es2015.symbol"] + compilerOptions: { + module: "commonjs", + target: "es5", + noImplicitAny: false, + sourceMap: false, + allowJs: false, + lib: ["es5", "es2015.core", "es2015.symbol"] } }, "tsconfig.json", { @@ -108,12 +108,12 @@ namespace ts { it("Convert incorrect option of jsx to compiler-options ", () => { assertCompilerOptions( { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "jsx": "" + compilerOptions: { + module: "commonjs", + target: "es5", + noImplicitAny: false, + sourceMap: false, + jsx: "" } }, "tsconfig.json", { @@ -138,11 +138,11 @@ namespace ts { it("Convert incorrect option of module to compiler-options ", () => { assertCompilerOptions( { - "compilerOptions": { - "module": "", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, + compilerOptions: { + module: "", + target: "es5", + noImplicitAny: false, + sourceMap: false, } }, "tsconfig.json", { @@ -166,11 +166,11 @@ namespace ts { it("Convert incorrect option of newLine to compiler-options ", () => { assertCompilerOptions( { - "compilerOptions": { - "newLine": "", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, + compilerOptions: { + newLine: "", + target: "es5", + noImplicitAny: false, + sourceMap: false, } }, "tsconfig.json", { @@ -194,10 +194,10 @@ namespace ts { it("Convert incorrect option of target to compiler-options ", () => { assertCompilerOptions( { - "compilerOptions": { - "target": "", - "noImplicitAny": false, - "sourceMap": false, + compilerOptions: { + target: "", + noImplicitAny: false, + sourceMap: false, } }, "tsconfig.json", { @@ -220,10 +220,10 @@ namespace ts { it("Convert incorrect option of module-resolution to compiler-options ", () => { assertCompilerOptions( { - "compilerOptions": { - "moduleResolution": "", - "noImplicitAny": false, - "sourceMap": false, + compilerOptions: { + moduleResolution: "", + noImplicitAny: false, + sourceMap: false, } }, "tsconfig.json", { @@ -246,12 +246,12 @@ namespace ts { it("Convert incorrect option of libs to compiler-options ", () => { assertCompilerOptions( { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "lib": ["es5", "es2015.core", "incorrectLib"] + compilerOptions: { + module: "commonjs", + target: "es5", + noImplicitAny: false, + sourceMap: false, + lib: ["es5", "es2015.core", "incorrectLib"] } }, "tsconfig.json", { @@ -277,12 +277,12 @@ namespace ts { it("Convert empty string option of libs to compiler-options ", () => { assertCompilerOptions( { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "lib": ["es5", ""] + compilerOptions: { + module: "commonjs", + target: "es5", + noImplicitAny: false, + sourceMap: false, + lib: ["es5", ""] } }, "tsconfig.json", { @@ -308,12 +308,12 @@ namespace ts { it("Convert empty string option of libs to compiler-options ", () => { assertCompilerOptions( { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "lib": [""] + compilerOptions: { + module: "commonjs", + target: "es5", + noImplicitAny: false, + sourceMap: false, + lib: [""] } }, "tsconfig.json", { @@ -339,12 +339,12 @@ namespace ts { it("Convert trailing-whitespace string option of libs to compiler-options ", () => { assertCompilerOptions( { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "lib": [" "] + compilerOptions: { + module: "commonjs", + target: "es5", + noImplicitAny: false, + sourceMap: false, + lib: [" "] } }, "tsconfig.json", { @@ -370,12 +370,12 @@ namespace ts { it("Convert empty option of libs to compiler-options ", () => { assertCompilerOptions( { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "lib": [] + compilerOptions: { + module: "commonjs", + target: "es5", + noImplicitAny: false, + sourceMap: false, + lib: [] } }, "tsconfig.json", { @@ -394,8 +394,8 @@ namespace ts { it("Convert incorrectly format tsconfig.json to compiler-options ", () => { assertCompilerOptions( { - "compilerOptions": { - "modu": "commonjs", + compilerOptions: { + modu: "commonjs", } }, "tsconfig.json", { @@ -424,9 +424,9 @@ namespace ts { it("Convert negative numbers in tsconfig.json ", () => { assertCompilerOptions( { - "compilerOptions": { - "allowJs": true, - "maxNodeModuleJsDepth": -1 + compilerOptions: { + allowJs: true, + maxNodeModuleJsDepth: -1 } }, "tsconfig.json", { @@ -443,12 +443,12 @@ namespace ts { it("Convert correctly format jsconfig.json to compiler-options ", () => { assertCompilerOptions( { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "lib": ["es5", "es2015.core", "es2015.symbol"] + compilerOptions: { + module: "commonjs", + target: "es5", + noImplicitAny: false, + sourceMap: false, + lib: ["es5", "es2015.core", "es2015.symbol"] } }, "jsconfig.json", { @@ -471,13 +471,13 @@ namespace ts { it("Convert correctly format jsconfig.json with allowJs is false to compiler-options ", () => { assertCompilerOptions( { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "allowJs": false, - "lib": ["es5", "es2015.core", "es2015.symbol"] + compilerOptions: { + module: "commonjs", + target: "es5", + noImplicitAny: false, + sourceMap: false, + allowJs: false, + lib: ["es5", "es2015.core", "es2015.symbol"] } }, "jsconfig.json", { @@ -500,8 +500,8 @@ namespace ts { it("Convert incorrectly format jsconfig.json to compiler-options ", () => { assertCompilerOptions( { - "compilerOptions": { - "modu": "commonjs", + compilerOptions: { + modu: "commonjs", } }, "jsconfig.json", { diff --git a/src/harness/unittests/convertTypeAcquisitionFromJson.ts b/src/harness/unittests/convertTypeAcquisitionFromJson.ts index 5a367edebbb..be1ada10a97 100644 --- a/src/harness/unittests/convertTypeAcquisitionFromJson.ts +++ b/src/harness/unittests/convertTypeAcquisitionFromJson.ts @@ -55,11 +55,11 @@ namespace ts { it("Convert deprecated typingOptions.enableAutoDiscovery format tsconfig.json to typeAcquisition ", () => { assertTypeAcquisition( { - "typingOptions": + typingOptions: { - "enableAutoDiscovery": true, - "include": ["0.d.ts", "1.d.ts"], - "exclude": ["0.js", "1.js"] + enableAutoDiscovery: true, + include: ["0.d.ts", "1.d.ts"], + exclude: ["0.js", "1.js"] } }, "tsconfig.json", @@ -77,11 +77,11 @@ namespace ts { it("Convert correctly format tsconfig.json to typeAcquisition ", () => { assertTypeAcquisition( { - "typeAcquisition": + typeAcquisition: { - "enable": true, - "include": ["0.d.ts", "1.d.ts"], - "exclude": ["0.js", "1.js"] + enable: true, + include: ["0.d.ts", "1.d.ts"], + exclude: ["0.js", "1.js"] } }, "tsconfig.json", @@ -99,9 +99,9 @@ namespace ts { it("Convert incorrect format tsconfig.json to typeAcquisition ", () => { assertTypeAcquisition( { - "typeAcquisition": + typeAcquisition: { - "enableAutoDiscovy": true, + enableAutoDiscovy: true, } }, "tsconfig.json", { @@ -140,9 +140,9 @@ namespace ts { it("Convert tsconfig.json with only enable property to typeAcquisition ", () => { assertTypeAcquisition( { - "typeAcquisition": + typeAcquisition: { - "enable": true + enable: true } }, "tsconfig.json", { @@ -160,11 +160,11 @@ namespace ts { it("Convert jsconfig.json to typeAcquisition ", () => { assertTypeAcquisition( { - "typeAcquisition": + typeAcquisition: { - "enable": false, - "include": ["0.d.ts"], - "exclude": ["0.js"] + enable: false, + include: ["0.d.ts"], + exclude: ["0.js"] } }, "jsconfig.json", { @@ -194,9 +194,9 @@ namespace ts { it("Convert incorrect format jsconfig.json to typeAcquisition ", () => { assertTypeAcquisition( { - "typeAcquisition": + typeAcquisition: { - "enableAutoDiscovy": true, + enableAutoDiscovy: true, } }, "jsconfig.json", { @@ -222,9 +222,9 @@ namespace ts { it("Convert jsconfig.json with only enable property to typeAcquisition ", () => { assertTypeAcquisition( { - "typeAcquisition": + typeAcquisition: { - "enable": false + enable: false } }, "jsconfig.json", { diff --git a/src/harness/unittests/moduleResolution.ts b/src/harness/unittests/moduleResolution.ts index 6f62c78208f..de79ba06cf9 100644 --- a/src/harness/unittests/moduleResolution.ts +++ b/src/harness/unittests/moduleResolution.ts @@ -127,7 +127,7 @@ namespace ts { function test(hasDirectoryExists: boolean) { const containingFile = { name: containingFileName }; - const packageJson = { name: packageJsonFileName, content: JSON.stringify({ "typings": fieldRef }) }; + const packageJson = { name: packageJsonFileName, content: JSON.stringify({ typings: fieldRef }) }; const moduleFile = { name: moduleFileName }; const resolution = nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, moduleFile)); checkResolvedModule(resolution.resolvedModule, createResolvedModule(moduleFile.name)); @@ -149,7 +149,7 @@ namespace ts { function test(hasDirectoryExists: boolean) { const containingFile = { name: "/a/b.ts" }; - const packageJson = { name: "/node_modules/b/package.json", content: JSON.stringify({ "typings": typings }) }; + const packageJson = { name: "/node_modules/b/package.json", content: JSON.stringify({ typings }) }; const moduleFile = { name: "/a/b.d.ts" }; const indexPath = "/node_modules/b/index.d.ts"; @@ -163,7 +163,7 @@ namespace ts { it("module name as directory - handle invalid 'typings'", () => { testTypingsIgnored(["a", "b"]); - testTypingsIgnored({ "a": "b" }); + testTypingsIgnored({ a: "b" }); testTypingsIgnored(/*typings*/ true); testTypingsIgnored(/*typings*/ null); // tslint:disable-line no-null-keyword testTypingsIgnored(/*typings*/ undefined); diff --git a/src/harness/unittests/reuseProgramStructure.ts b/src/harness/unittests/reuseProgramStructure.ts index 6278742a0bd..fdccc8a7795 100644 --- a/src/harness/unittests/reuseProgramStructure.ts +++ b/src/harness/unittests/reuseProgramStructure.ts @@ -360,7 +360,7 @@ namespace ts { const options: CompilerOptions = { target }; const program1 = newProgram(files, ["a.ts"], options); - checkResolvedModulesCache(program1, "a.ts", createMapFromTemplate({ "b": createResolvedModule("b.ts") })); + checkResolvedModulesCache(program1, "a.ts", createMapFromTemplate({ b: createResolvedModule("b.ts") })); checkResolvedModulesCache(program1, "b.ts", /*expectedContent*/ undefined); const program2 = updateProgram(program1, ["a.ts"], options, files => { @@ -369,7 +369,7 @@ namespace ts { assert.equal(program1.structureIsReused, StructureIsReused.Completely); // content of resolution cache should not change - checkResolvedModulesCache(program1, "a.ts", createMapFromTemplate({ "b": createResolvedModule("b.ts") })); + checkResolvedModulesCache(program1, "a.ts", createMapFromTemplate({ b: createResolvedModule("b.ts") })); checkResolvedModulesCache(program1, "b.ts", /*expectedContent*/ undefined); // imports has changed - program is not reused @@ -386,7 +386,7 @@ namespace ts { files[0].text = files[0].text.updateImportsAndExports(newImports); }); assert.equal(program3.structureIsReused, StructureIsReused.SafeModules); - checkResolvedModulesCache(program4, "a.ts", createMapFromTemplate({ "b": createResolvedModule("b.ts"), "c": undefined })); + checkResolvedModulesCache(program4, "a.ts", createMapFromTemplate({ b: createResolvedModule("b.ts"), c: undefined })); }); it("resolved type directives cache follows type directives", () => { @@ -397,7 +397,7 @@ namespace ts { const options: CompilerOptions = { target, typeRoots: ["/types"] }; const program1 = newProgram(files, ["/a.ts"], options); - checkResolvedTypeDirectivesCache(program1, "/a.ts", createMapFromTemplate({ "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } })); + checkResolvedTypeDirectivesCache(program1, "/a.ts", createMapFromTemplate({ typedefs: { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } })); checkResolvedTypeDirectivesCache(program1, "/types/typedefs/index.d.ts", /*expectedContent*/ undefined); const program2 = updateProgram(program1, ["/a.ts"], options, files => { @@ -406,7 +406,7 @@ namespace ts { assert.equal(program1.structureIsReused, StructureIsReused.Completely); // content of resolution cache should not change - checkResolvedTypeDirectivesCache(program1, "/a.ts", createMapFromTemplate({ "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } })); + checkResolvedTypeDirectivesCache(program1, "/a.ts", createMapFromTemplate({ typedefs: { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } })); checkResolvedTypeDirectivesCache(program1, "/types/typedefs/index.d.ts", /*expectedContent*/ undefined); // type reference directives has changed - program is not reused @@ -424,7 +424,7 @@ namespace ts { files[0].text = files[0].text.updateReferences(newReferences); }); assert.equal(program3.structureIsReused, StructureIsReused.SafeModules); - checkResolvedTypeDirectivesCache(program1, "/a.ts", createMapFromTemplate({ "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } })); + checkResolvedTypeDirectivesCache(program1, "/a.ts", createMapFromTemplate({ typedefs: { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } })); }); it("fetches imports after npm install", () => { diff --git a/src/harness/unittests/services/preProcessFile.ts b/src/harness/unittests/services/preProcessFile.ts index d4195573cba..1e13bc3e345 100644 --- a/src/harness/unittests/services/preProcessFile.ts +++ b/src/harness/unittests/services/preProcessFile.ts @@ -278,7 +278,7 @@ describe("PreProcessFile:", () => { referencedFiles: [], typeReferenceDirectives: [], importedFiles: [ - { "fileName": "../Observable", "pos": 28, "end": 41 } + { fileName: "../Observable", pos: 28, end: 41 } ], ambientExternalModules: undefined, isLibFile: false @@ -298,8 +298,8 @@ describe("PreProcessFile:", () => { referencedFiles: [], typeReferenceDirectives: [], importedFiles: [ - { "fileName": "m", "pos": 123, "end": 124 }, - { "fileName": "../Observable", "pos": 28, "end": 41 } + { fileName: "m", pos: 123, end: 124 }, + { fileName: "../Observable", pos: 28, end: 41 } ], ambientExternalModules: undefined, isLibFile: false @@ -319,8 +319,8 @@ describe("PreProcessFile:", () => { referencedFiles: [], typeReferenceDirectives: [], importedFiles: [ - { "fileName": "m", "pos": 123, "end": 124 }, - { "fileName": "../Observable", "pos": 28, "end": 41 } + { fileName: "m", pos: 123, end: 124 }, + { fileName: "../Observable", pos: 28, end: 41 } ], ambientExternalModules: undefined, isLibFile: false @@ -340,7 +340,7 @@ describe("PreProcessFile:", () => { referencedFiles: [], typeReferenceDirectives: [], importedFiles: [ - { "fileName": "../Observable", "pos": 28, "end": 41 } + { fileName: "../Observable", pos: 28, end: 41 } ], ambientExternalModules: undefined, isLibFile: false @@ -360,7 +360,7 @@ describe("PreProcessFile:", () => { referencedFiles: [], typeReferenceDirectives: [], importedFiles: [ - { "fileName": "../Observable", "pos": 28, "end": 41 } + { fileName: "../Observable", pos: 28, end: 41 } ], ambientExternalModules: undefined, isLibFile: false @@ -379,7 +379,7 @@ describe("PreProcessFile:", () => { referencedFiles: [], typeReferenceDirectives: [], importedFiles: [ - { "fileName": "../Observable", "pos": 28, "end": 41 } + { fileName: "../Observable", pos: 28, end: 41 } ], ambientExternalModules: undefined, isLibFile: false @@ -400,8 +400,8 @@ describe("PreProcessFile:", () => { referencedFiles: [], typeReferenceDirectives: [], importedFiles: [ - { "fileName": "m2", "pos": 65, "end": 67 }, - { "fileName": "augmentation", "pos": 102, "end": 114 } + { fileName: "m2", pos: 65, end: 67 }, + { fileName: "augmentation", pos: 102, end: 114 } ], ambientExternalModules: ["m1"], isLibFile: false @@ -424,8 +424,8 @@ describe("PreProcessFile:", () => { referencedFiles: [], typeReferenceDirectives: [], importedFiles: [ - { "fileName": "m2", "pos": 127, "end": 129 }, - { "fileName": "augmentation", "pos": 164, "end": 176 } + { fileName: "m2", pos: 127, end: 129 }, + { fileName: "augmentation", pos: 164, end: 176 } ], ambientExternalModules: ["m1"], isLibFile: false @@ -442,12 +442,12 @@ describe("PreProcessFile:", () => { /*detectJavaScriptImports*/ false, { referencedFiles: [ - { "pos": 34, "end": 35, "fileName": "a" }, - { "pos": 112, "end": 114, "fileName": "a2" } + { pos: 34, end: 35, fileName: "a" }, + { pos: 112, end: 114, fileName: "a2" } ], typeReferenceDirectives: [ - { "pos": 73, "end": 75, "fileName": "a1" }, - { "pos": 152, "end": 154, "fileName": "a3" } + { pos: 73, end: 75, fileName: "a1" }, + { pos: 152, end: 154, fileName: "a3" } ], importedFiles: [], ambientExternalModules: undefined, diff --git a/src/harness/unittests/transpile.ts b/src/harness/unittests/transpile.ts index 16bef6500f2..7c4af8be167 100644 --- a/src/harness/unittests/transpile.ts +++ b/src/harness/unittests/transpile.ts @@ -149,21 +149,21 @@ var x = 0;`, { `import {foo} from "SomeName";\n` + `declare function use(a: any);\n` + `use(foo);`, { - options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } } + options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, renamedDependencies: { SomeName: "SomeOtherName" } } }); transpilesCorrectly("Rename dependencies - AMD", `import {foo} from "SomeName";\n` + `declare function use(a: any);\n` + `use(foo);`, { - options: { compilerOptions: { module: ModuleKind.AMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } } + options: { compilerOptions: { module: ModuleKind.AMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { SomeName: "SomeOtherName" } } }); transpilesCorrectly("Rename dependencies - UMD", `import {foo} from "SomeName";\n` + `declare function use(a: any);\n` + `use(foo);`, { - options: { compilerOptions: { module: ModuleKind.UMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } } + options: { compilerOptions: { module: ModuleKind.UMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { SomeName: "SomeOtherName" } } }); transpilesCorrectly("Transpile with emit decorators and emit metadata", diff --git a/src/harness/unittests/tscWatchMode.ts b/src/harness/unittests/tscWatchMode.ts index cddbfba9dc0..fc80a6f39ef 100644 --- a/src/harness/unittests/tscWatchMode.ts +++ b/src/harness/unittests/tscWatchMode.ts @@ -710,12 +710,12 @@ namespace ts.tscWatch { path: "/src/tsconfig.json", content: JSON.stringify( { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": true, - "sourceMap": false, - "lib": [ + compilerOptions: { + module: "commonjs", + target: "es5", + noImplicitAny: true, + sourceMap: false, + lib: [ "es5" ] } @@ -725,12 +725,12 @@ namespace ts.tscWatch { path: config1.path, content: JSON.stringify( { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": true, - "sourceMap": false, - "lib": [ + compilerOptions: { + module: "commonjs", + target: "es5", + noImplicitAny: true, + sourceMap: false, + lib: [ "es5", "es2015.promise" ] @@ -1963,12 +1963,12 @@ declare module "fs" { const configFile: FileOrFolder = { path: "/a/rootFolder/project/tsconfig.json", content: JSON.stringify({ - "compilerOptions": { - "module": "none", - "allowJs": true, - "outDir": "Static/scripts/" + compilerOptions: { + module: "none", + allowJs: true, + outDir: "Static/scripts/" }, - "include": [ + include: [ "Scripts/**/*" ], }) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 55d767d24a7..ffb811dddba 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -2607,7 +2607,7 @@ namespace ts.projectSystem { projectFileName, rootFiles: [toExternalFile(site.path), toExternalFile(configFile.path)], options: { allowJs: false }, - typeAcquisition: { "include": [] } + typeAcquisition: { include: [] } }; projectService.openExternalProjects([externalProject]); @@ -3114,12 +3114,12 @@ namespace ts.projectSystem { path: "/src/tsconfig.json", content: JSON.stringify( { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": true, - "sourceMap": false, - "lib": [ + compilerOptions: { + module: "commonjs", + target: "es5", + noImplicitAny: true, + sourceMap: false, + lib: [ "es5" ] } @@ -3129,12 +3129,12 @@ namespace ts.projectSystem { path: config1.path, content: JSON.stringify( { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": true, - "sourceMap": false, - "lib": [ + compilerOptions: { + module: "commonjs", + target: "es5", + noImplicitAny: true, + sourceMap: false, + lib: [ "es5", "es2015.promise" ] @@ -5483,31 +5483,31 @@ namespace ts.projectSystem { const tsconfigFile: FileOrFolder = { path: `${frontendDir}/tsconfig.json`, content: JSON.stringify({ - "compilerOptions": { - "strict": true, - "strictNullChecks": true, - "target": "es2016", - "module": "commonjs", - "moduleResolution": "node", - "sourceMap": true, - "noEmitOnError": true, - "experimentalDecorators": true, - "emitDecoratorMetadata": true, + compilerOptions: { + strict: true, + strictNullChecks: true, + target: "es2016", + module: "commonjs", + moduleResolution: "node", + sourceMap: true, + noEmitOnError: true, + experimentalDecorators: true, + emitDecoratorMetadata: true, types, - "noUnusedLocals": true, - "outDir": "./compiled", + noUnusedLocals: true, + outDir: "./compiled", typeRoots, - "baseUrl": ".", - "paths": { + baseUrl: ".", + paths: { "*": [ "types/*" ] } }, - "include": [ + include: [ "src/**/*" ], - "exclude": [ + exclude: [ "node_modules", "compiled" ] @@ -5632,30 +5632,30 @@ namespace ts.projectSystem { // Simulate npm install const filesAndFoldersToAdd: FileOrFolder[] = [ - { "path": "/a/b/node_modules" }, - { "path": "/a/b/node_modules/.staging/@types" }, - { "path": "/a/b/node_modules/.staging/lodash-b0733faa" }, - { "path": "/a/b/node_modules/.staging/@types/lodash-e56c4fe7" }, - { "path": "/a/b/node_modules/.staging/symbol-observable-24bcbbff" }, - { "path": "/a/b/node_modules/.staging/rxjs-22375c61" }, - { "path": "/a/b/node_modules/.staging/typescript-8493ea5d" }, - { "path": "/a/b/node_modules/.staging/symbol-observable-24bcbbff/package.json", "content": "{\n \"name\": \"symbol-observable\",\n \"version\": \"1.0.4\",\n \"description\": \"Symbol.observable ponyfill\",\n \"license\": \"MIT\",\n \"repository\": \"blesh/symbol-observable\",\n \"author\": {\n \"name\": \"Ben Lesh\",\n \"email\": \"ben@benlesh.com\"\n },\n \"engines\": {\n \"node\": \">=0.10.0\"\n },\n \"scripts\": {\n \"test\": \"npm run build && mocha && tsc ./ts-test/test.ts && node ./ts-test/test.js && check-es3-syntax -p lib/ --kill\",\n \"build\": \"babel es --out-dir lib\",\n \"prepublish\": \"npm test\"\n },\n \"files\": [\n \"" }, - { "path": "/a/b/node_modules/.staging/lodash-b0733faa/package.json", "content": "{\n \"name\": \"lodash\",\n \"version\": \"4.17.4\",\n \"description\": \"Lodash modular utilities.\",\n \"keywords\": \"modules, stdlib, util\",\n \"homepage\": \"https://lodash.com/\",\n \"repository\": \"lodash/lodash\",\n \"icon\": \"https://lodash.com/icon.svg\",\n \"license\": \"MIT\",\n \"main\": \"lodash.js\",\n \"author\": \"John-David Dalton (http://allyoucanleet.com/)\",\n \"contributors\": [\n \"John-David Dalton (http://allyoucanleet.com/)\",\n \"Mathias Bynens \",\n \"contributors\": [\n {\n \"name\": \"Ben Lesh\",\n \"email\": \"ben@benlesh.com\"\n },\n {\n \"name\": \"Paul Taylor\",\n \"email\": \"paul.e.taylor@me.com\"\n },\n {\n \"name\": \"Jeff Cross\",\n \"email\": \"crossj@google.com\"\n },\n {\n \"name\": \"Matthew Podwysocki\",\n \"email\": \"matthewp@microsoft.com\"\n },\n {\n \"name\": \"OJ Kwon\",\n \"email\": \"kwon.ohjoong@gmail.com\"\n },\n {\n \"name\": \"Andre Staltz\",\n \"email\": \"andre@staltz.com\"\n }\n ],\n \"license\": \"Apache-2.0\",\n \"bugs\": {\n \"url\": \"https://github.com/ReactiveX/RxJS/issues\"\n },\n \"homepage\": \"https://github.com/ReactiveX/RxJS\",\n \"devDependencies\": {\n \"babel-polyfill\": \"^6.23.0\",\n \"benchmark\": \"^2.1.0\",\n \"benchpress\": \"2.0.0-beta.1\",\n \"chai\": \"^3.5.0\",\n \"color\": \"^0.11.1\",\n \"colors\": \"1.1.2\",\n \"commitizen\": \"^2.8.6\",\n \"coveralls\": \"^2.11.13\",\n \"cz-conventional-changelog\": \"^1.2.0\",\n \"danger\": \"^1.1.0\",\n \"doctoc\": \"^1.0.0\",\n \"escape-string-regexp\": \"^1.0.5 \",\n \"esdoc\": \"^0.4.7\",\n \"eslint\": \"^3.8.0\",\n \"fs-extra\": \"^2.1.2\",\n \"get-folder-size\": \"^1.0.0\",\n \"glob\": \"^7.0.3\",\n \"gm\": \"^1.22.0\",\n \"google-closure-compiler-js\": \"^20170218.0.0\",\n \"gzip-size\": \"^3.0.0\",\n \"http-server\": \"^0.9.0\",\n \"husky\": \"^0.13.3\",\n \"lint-staged\": \"3.2.5\",\n \"lodash\": \"^4.15.0\",\n \"madge\": \"^1.4.3\",\n \"markdown-doctest\": \"^0.9.1\",\n \"minimist\": \"^1.2.0\",\n \"mkdirp\": \"^0.5.1\",\n \"mocha\": \"^3.0.2\",\n \"mocha-in-sauce\": \"0.0.1\",\n \"npm-run-all\": \"^4.0.2\",\n \"npm-scripts-info\": \"^0.3.4\",\n \"nyc\": \"^10.2.0\",\n \"opn-cli\": \"^3.1.0\",\n \"platform\": \"^1.3.1\",\n \"promise\": \"^7.1.1\",\n \"protractor\": \"^3.1.1\",\n \"rollup\": \"0.36.3\",\n \"rollup-plugin-inject\": \"^2.0.0\",\n \"rollup-plugin-node-resolve\": \"^2.0.0\",\n \"rx\": \"latest\",\n \"rxjs\": \"latest\",\n \"shx\": \"^0.2.2\",\n \"sinon\": \"^2.1.0\",\n \"sinon-chai\": \"^2.9.0\",\n \"source-map-support\": \"^0.4.0\",\n \"tslib\": \"^1.5.0\",\n \"tslint\": \"^4.4.2\",\n \"typescript\": \"~2.0.6\",\n \"typings\": \"^2.0.0\",\n \"validate-commit-msg\": \"^2.14.0\",\n \"watch\": \"^1.0.1\",\n \"webpack\": \"^1.13.1\",\n \"xmlhttprequest\": \"1.8.0\"\n },\n \"engines\": {\n \"npm\": \">=2.0.0\"\n },\n \"typings\": \"Rx.d.ts\",\n \"dependencies\": {\n \"symbol-observable\": \"^1.0.1\"\n }\n}" }, - { "path": "/a/b/node_modules/.staging/typescript-8493ea5d/package.json", "content": "{\n \"name\": \"typescript\",\n \"author\": \"Microsoft Corp.\",\n \"homepage\": \"http://typescriptlang.org/\",\n \"version\": \"2.4.2\",\n \"license\": \"Apache-2.0\",\n \"description\": \"TypeScript is a language for application scale JavaScript development\",\n \"keywords\": [\n \"TypeScript\",\n \"Microsoft\",\n \"compiler\",\n \"language\",\n \"javascript\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/Microsoft/TypeScript/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/Microsoft/TypeScript.git\"\n },\n \"main\": \"./lib/typescript.js\",\n \"typings\": \"./lib/typescript.d.ts\",\n \"bin\": {\n \"tsc\": \"./bin/tsc\",\n \"tsserver\": \"./bin/tsserver\"\n },\n \"engines\": {\n \"node\": \">=4.2.0\"\n },\n \"devDependencies\": {\n \"@types/browserify\": \"latest\",\n \"@types/chai\": \"latest\",\n \"@types/convert-source-map\": \"latest\",\n \"@types/del\": \"latest\",\n \"@types/glob\": \"latest\",\n \"@types/gulp\": \"latest\",\n \"@types/gulp-concat\": \"latest\",\n \"@types/gulp-help\": \"latest\",\n \"@types/gulp-newer\": \"latest\",\n \"@types/gulp-sourcemaps\": \"latest\",\n \"@types/merge2\": \"latest\",\n \"@types/minimatch\": \"latest\",\n \"@types/minimist\": \"latest\",\n \"@types/mkdirp\": \"latest\",\n \"@types/mocha\": \"latest\",\n \"@types/node\": \"latest\",\n \"@types/q\": \"latest\",\n \"@types/run-sequence\": \"latest\",\n \"@types/through2\": \"latest\",\n \"browserify\": \"latest\",\n \"chai\": \"latest\",\n \"convert-source-map\": \"latest\",\n \"del\": \"latest\",\n \"gulp\": \"latest\",\n \"gulp-clone\": \"latest\",\n \"gulp-concat\": \"latest\",\n \"gulp-help\": \"latest\",\n \"gulp-insert\": \"latest\",\n \"gulp-newer\": \"latest\",\n \"gulp-sourcemaps\": \"latest\",\n \"gulp-typescript\": \"latest\",\n \"into-stream\": \"latest\",\n \"istanbul\": \"latest\",\n \"jake\": \"latest\",\n \"merge2\": \"latest\",\n \"minimist\": \"latest\",\n \"mkdirp\": \"latest\",\n \"mocha\": \"latest\",\n \"mocha-fivemat-progress-reporter\": \"latest\",\n \"q\": \"latest\",\n \"run-sequence\": \"latest\",\n \"sorcery\": \"latest\",\n \"through2\": \"latest\",\n \"travis-fold\": \"latest\",\n \"ts-node\": \"latest\",\n \"tslint\": \"latest\",\n \"typescript\": \"^2.4\"\n },\n \"scripts\": {\n \"pretest\": \"jake tests\",\n \"test\": \"jake runtests-parallel\",\n \"build\": \"npm run build:compiler && npm run build:tests\",\n \"build:compiler\": \"jake local\",\n \"build:tests\": \"jake tests\",\n \"start\": \"node lib/tsc\",\n \"clean\": \"jake clean\",\n \"gulp\": \"gulp\",\n \"jake\": \"jake\",\n \"lint\": \"jake lint\",\n \"setup-hooks\": \"node scripts/link-hooks.js\"\n },\n \"browser\": {\n \"buffer\": false,\n \"fs\": false,\n \"os\": false,\n \"path\": false\n }\n}" }, - { "path": "/a/b/node_modules/.staging/symbol-observable-24bcbbff/index.js", "content": "module.exports = require('./lib/index');\n" }, - { "path": "/a/b/node_modules/.staging/symbol-observable-24bcbbff/index.d.ts", "content": "declare const observableSymbol: symbol;\nexport default observableSymbol;\n" }, - { "path": "/a/b/node_modules/.staging/symbol-observable-24bcbbff/lib" }, - { "path": "/a/b/node_modules/.staging/symbol-observable-24bcbbff/lib/index.js", "content": "'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _ponyfill = require('./ponyfill');\n\nvar _ponyfill2 = _interopRequireDefault(_ponyfill);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }\n\nvar root; /* global window */\n\n\nif (typeof self !== 'undefined') {\n root = self;\n} else if (typeof window !== 'undefined') {\n root = window;\n} else if (typeof global !== 'undefined') {\n root = global;\n} else if (typeof module !== 'undefined') {\n root = module;\n} else {\n root = Function('return this')();\n}\n\nvar result = (0, _ponyfill2['default'])(root);\nexports['default'] = result;" }, + { path: "/a/b/node_modules" }, + { path: "/a/b/node_modules/.staging/@types" }, + { path: "/a/b/node_modules/.staging/lodash-b0733faa" }, + { path: "/a/b/node_modules/.staging/@types/lodash-e56c4fe7" }, + { path: "/a/b/node_modules/.staging/symbol-observable-24bcbbff" }, + { path: "/a/b/node_modules/.staging/rxjs-22375c61" }, + { path: "/a/b/node_modules/.staging/typescript-8493ea5d" }, + { path: "/a/b/node_modules/.staging/symbol-observable-24bcbbff/package.json", content: "{\n \"name\": \"symbol-observable\",\n \"version\": \"1.0.4\",\n \"description\": \"Symbol.observable ponyfill\",\n \"license\": \"MIT\",\n \"repository\": \"blesh/symbol-observable\",\n \"author\": {\n \"name\": \"Ben Lesh\",\n \"email\": \"ben@benlesh.com\"\n },\n \"engines\": {\n \"node\": \">=0.10.0\"\n },\n \"scripts\": {\n \"test\": \"npm run build && mocha && tsc ./ts-test/test.ts && node ./ts-test/test.js && check-es3-syntax -p lib/ --kill\",\n \"build\": \"babel es --out-dir lib\",\n \"prepublish\": \"npm test\"\n },\n \"files\": [\n \"" }, + { path: "/a/b/node_modules/.staging/lodash-b0733faa/package.json", content: "{\n \"name\": \"lodash\",\n \"version\": \"4.17.4\",\n \"description\": \"Lodash modular utilities.\",\n \"keywords\": \"modules, stdlib, util\",\n \"homepage\": \"https://lodash.com/\",\n \"repository\": \"lodash/lodash\",\n \"icon\": \"https://lodash.com/icon.svg\",\n \"license\": \"MIT\",\n \"main\": \"lodash.js\",\n \"author\": \"John-David Dalton (http://allyoucanleet.com/)\",\n \"contributors\": [\n \"John-David Dalton (http://allyoucanleet.com/)\",\n \"Mathias Bynens \",\n \"contributors\": [\n {\n \"name\": \"Ben Lesh\",\n \"email\": \"ben@benlesh.com\"\n },\n {\n \"name\": \"Paul Taylor\",\n \"email\": \"paul.e.taylor@me.com\"\n },\n {\n \"name\": \"Jeff Cross\",\n \"email\": \"crossj@google.com\"\n },\n {\n \"name\": \"Matthew Podwysocki\",\n \"email\": \"matthewp@microsoft.com\"\n },\n {\n \"name\": \"OJ Kwon\",\n \"email\": \"kwon.ohjoong@gmail.com\"\n },\n {\n \"name\": \"Andre Staltz\",\n \"email\": \"andre@staltz.com\"\n }\n ],\n \"license\": \"Apache-2.0\",\n \"bugs\": {\n \"url\": \"https://github.com/ReactiveX/RxJS/issues\"\n },\n \"homepage\": \"https://github.com/ReactiveX/RxJS\",\n \"devDependencies\": {\n \"babel-polyfill\": \"^6.23.0\",\n \"benchmark\": \"^2.1.0\",\n \"benchpress\": \"2.0.0-beta.1\",\n \"chai\": \"^3.5.0\",\n \"color\": \"^0.11.1\",\n \"colors\": \"1.1.2\",\n \"commitizen\": \"^2.8.6\",\n \"coveralls\": \"^2.11.13\",\n \"cz-conventional-changelog\": \"^1.2.0\",\n \"danger\": \"^1.1.0\",\n \"doctoc\": \"^1.0.0\",\n \"escape-string-regexp\": \"^1.0.5 \",\n \"esdoc\": \"^0.4.7\",\n \"eslint\": \"^3.8.0\",\n \"fs-extra\": \"^2.1.2\",\n \"get-folder-size\": \"^1.0.0\",\n \"glob\": \"^7.0.3\",\n \"gm\": \"^1.22.0\",\n \"google-closure-compiler-js\": \"^20170218.0.0\",\n \"gzip-size\": \"^3.0.0\",\n \"http-server\": \"^0.9.0\",\n \"husky\": \"^0.13.3\",\n \"lint-staged\": \"3.2.5\",\n \"lodash\": \"^4.15.0\",\n \"madge\": \"^1.4.3\",\n \"markdown-doctest\": \"^0.9.1\",\n \"minimist\": \"^1.2.0\",\n \"mkdirp\": \"^0.5.1\",\n \"mocha\": \"^3.0.2\",\n \"mocha-in-sauce\": \"0.0.1\",\n \"npm-run-all\": \"^4.0.2\",\n \"npm-scripts-info\": \"^0.3.4\",\n \"nyc\": \"^10.2.0\",\n \"opn-cli\": \"^3.1.0\",\n \"platform\": \"^1.3.1\",\n \"promise\": \"^7.1.1\",\n \"protractor\": \"^3.1.1\",\n \"rollup\": \"0.36.3\",\n \"rollup-plugin-inject\": \"^2.0.0\",\n \"rollup-plugin-node-resolve\": \"^2.0.0\",\n \"rx\": \"latest\",\n \"rxjs\": \"latest\",\n \"shx\": \"^0.2.2\",\n \"sinon\": \"^2.1.0\",\n \"sinon-chai\": \"^2.9.0\",\n \"source-map-support\": \"^0.4.0\",\n \"tslib\": \"^1.5.0\",\n \"tslint\": \"^4.4.2\",\n \"typescript\": \"~2.0.6\",\n \"typings\": \"^2.0.0\",\n \"validate-commit-msg\": \"^2.14.0\",\n \"watch\": \"^1.0.1\",\n \"webpack\": \"^1.13.1\",\n \"xmlhttprequest\": \"1.8.0\"\n },\n \"engines\": {\n \"npm\": \">=2.0.0\"\n },\n \"typings\": \"Rx.d.ts\",\n \"dependencies\": {\n \"symbol-observable\": \"^1.0.1\"\n }\n}" }, + { path: "/a/b/node_modules/.staging/typescript-8493ea5d/package.json", content: "{\n \"name\": \"typescript\",\n \"author\": \"Microsoft Corp.\",\n \"homepage\": \"http://typescriptlang.org/\",\n \"version\": \"2.4.2\",\n \"license\": \"Apache-2.0\",\n \"description\": \"TypeScript is a language for application scale JavaScript development\",\n \"keywords\": [\n \"TypeScript\",\n \"Microsoft\",\n \"compiler\",\n \"language\",\n \"javascript\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/Microsoft/TypeScript/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/Microsoft/TypeScript.git\"\n },\n \"main\": \"./lib/typescript.js\",\n \"typings\": \"./lib/typescript.d.ts\",\n \"bin\": {\n \"tsc\": \"./bin/tsc\",\n \"tsserver\": \"./bin/tsserver\"\n },\n \"engines\": {\n \"node\": \">=4.2.0\"\n },\n \"devDependencies\": {\n \"@types/browserify\": \"latest\",\n \"@types/chai\": \"latest\",\n \"@types/convert-source-map\": \"latest\",\n \"@types/del\": \"latest\",\n \"@types/glob\": \"latest\",\n \"@types/gulp\": \"latest\",\n \"@types/gulp-concat\": \"latest\",\n \"@types/gulp-help\": \"latest\",\n \"@types/gulp-newer\": \"latest\",\n \"@types/gulp-sourcemaps\": \"latest\",\n \"@types/merge2\": \"latest\",\n \"@types/minimatch\": \"latest\",\n \"@types/minimist\": \"latest\",\n \"@types/mkdirp\": \"latest\",\n \"@types/mocha\": \"latest\",\n \"@types/node\": \"latest\",\n \"@types/q\": \"latest\",\n \"@types/run-sequence\": \"latest\",\n \"@types/through2\": \"latest\",\n \"browserify\": \"latest\",\n \"chai\": \"latest\",\n \"convert-source-map\": \"latest\",\n \"del\": \"latest\",\n \"gulp\": \"latest\",\n \"gulp-clone\": \"latest\",\n \"gulp-concat\": \"latest\",\n \"gulp-help\": \"latest\",\n \"gulp-insert\": \"latest\",\n \"gulp-newer\": \"latest\",\n \"gulp-sourcemaps\": \"latest\",\n \"gulp-typescript\": \"latest\",\n \"into-stream\": \"latest\",\n \"istanbul\": \"latest\",\n \"jake\": \"latest\",\n \"merge2\": \"latest\",\n \"minimist\": \"latest\",\n \"mkdirp\": \"latest\",\n \"mocha\": \"latest\",\n \"mocha-fivemat-progress-reporter\": \"latest\",\n \"q\": \"latest\",\n \"run-sequence\": \"latest\",\n \"sorcery\": \"latest\",\n \"through2\": \"latest\",\n \"travis-fold\": \"latest\",\n \"ts-node\": \"latest\",\n \"tslint\": \"latest\",\n \"typescript\": \"^2.4\"\n },\n \"scripts\": {\n \"pretest\": \"jake tests\",\n \"test\": \"jake runtests-parallel\",\n \"build\": \"npm run build:compiler && npm run build:tests\",\n \"build:compiler\": \"jake local\",\n \"build:tests\": \"jake tests\",\n \"start\": \"node lib/tsc\",\n \"clean\": \"jake clean\",\n \"gulp\": \"gulp\",\n \"jake\": \"jake\",\n \"lint\": \"jake lint\",\n \"setup-hooks\": \"node scripts/link-hooks.js\"\n },\n \"browser\": {\n \"buffer\": false,\n \"fs\": false,\n \"os\": false,\n \"path\": false\n }\n}" }, + { path: "/a/b/node_modules/.staging/symbol-observable-24bcbbff/index.js", content: "module.exports = require('./lib/index');\n" }, + { path: "/a/b/node_modules/.staging/symbol-observable-24bcbbff/index.d.ts", content: "declare const observableSymbol: symbol;\nexport default observableSymbol;\n" }, + { path: "/a/b/node_modules/.staging/symbol-observable-24bcbbff/lib" }, + { path: "/a/b/node_modules/.staging/symbol-observable-24bcbbff/lib/index.js", content: "'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _ponyfill = require('./ponyfill');\n\nvar _ponyfill2 = _interopRequireDefault(_ponyfill);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }\n\nvar root; /* global window */\n\n\nif (typeof self !== 'undefined') {\n root = self;\n} else if (typeof window !== 'undefined') {\n root = window;\n} else if (typeof global !== 'undefined') {\n root = global;\n} else if (typeof module !== 'undefined') {\n root = module;\n} else {\n root = Function('return this')();\n}\n\nvar result = (0, _ponyfill2['default'])(root);\nexports['default'] = result;" }, ].map(getRootedFileOrFolder); verifyAfterPartialOrCompleteNpmInstall(2); filesAndFoldersToAdd.push(...[ - { "path": "/a/b/node_modules/.staging/typescript-8493ea5d/lib" }, - { "path": "/a/b/node_modules/.staging/rxjs-22375c61/add/operator" }, - { "path": "/a/b/node_modules/.staging/@types/lodash-e56c4fe7/package.json", "content": "{\n \"name\": \"@types/lodash\",\n \"version\": \"4.14.74\",\n \"description\": \"TypeScript definitions for Lo-Dash\",\n \"license\": \"MIT\",\n \"contributors\": [\n {\n \"name\": \"Brian Zengel\",\n \"url\": \"https://github.com/bczengel\"\n },\n {\n \"name\": \"Ilya Mochalov\",\n \"url\": \"https://github.com/chrootsu\"\n },\n {\n \"name\": \"Stepan Mikhaylyuk\",\n \"url\": \"https://github.com/stepancar\"\n },\n {\n \"name\": \"Eric L Anderson\",\n \"url\": \"https://github.com/ericanderson\"\n },\n {\n \"name\": \"AJ Richardson\",\n \"url\": \"https://github.com/aj-r\"\n },\n {\n \"name\": \"Junyoung Clare Jang\",\n \"url\": \"https://github.com/ailrun\"\n }\n ],\n \"main\": \"\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://www.github.com/DefinitelyTyped/DefinitelyTyped.git\"\n },\n \"scripts\": {},\n \"dependencies\": {},\n \"typesPublisherContentHash\": \"12af578ffaf8d86d2df37e591857906a86b983fa9258414326544a0fe6af0de8\",\n \"typeScriptVersion\": \"2.2\"\n}" }, - { "path": "/a/b/node_modules/.staging/lodash-b0733faa/index.js", "content": "module.exports = require('./lodash');" }, - { "path": "/a/b/node_modules/.staging/typescript-8493ea5d/package.json.3017591594" } + { path: "/a/b/node_modules/.staging/typescript-8493ea5d/lib" }, + { path: "/a/b/node_modules/.staging/rxjs-22375c61/add/operator" }, + { path: "/a/b/node_modules/.staging/@types/lodash-e56c4fe7/package.json", content: "{\n \"name\": \"@types/lodash\",\n \"version\": \"4.14.74\",\n \"description\": \"TypeScript definitions for Lo-Dash\",\n \"license\": \"MIT\",\n \"contributors\": [\n {\n \"name\": \"Brian Zengel\",\n \"url\": \"https://github.com/bczengel\"\n },\n {\n \"name\": \"Ilya Mochalov\",\n \"url\": \"https://github.com/chrootsu\"\n },\n {\n \"name\": \"Stepan Mikhaylyuk\",\n \"url\": \"https://github.com/stepancar\"\n },\n {\n \"name\": \"Eric L Anderson\",\n \"url\": \"https://github.com/ericanderson\"\n },\n {\n \"name\": \"AJ Richardson\",\n \"url\": \"https://github.com/aj-r\"\n },\n {\n \"name\": \"Junyoung Clare Jang\",\n \"url\": \"https://github.com/ailrun\"\n }\n ],\n \"main\": \"\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://www.github.com/DefinitelyTyped/DefinitelyTyped.git\"\n },\n \"scripts\": {},\n \"dependencies\": {},\n \"typesPublisherContentHash\": \"12af578ffaf8d86d2df37e591857906a86b983fa9258414326544a0fe6af0de8\",\n \"typeScriptVersion\": \"2.2\"\n}" }, + { path: "/a/b/node_modules/.staging/lodash-b0733faa/index.js", content: "module.exports = require('./lodash');" }, + { path: "/a/b/node_modules/.staging/typescript-8493ea5d/package.json.3017591594" } ].map(getRootedFileOrFolder)); // Since we didnt add any supported extension file, there wont be any timeout scheduled verifyAfterPartialOrCompleteNpmInstall(0); @@ -5665,19 +5665,19 @@ namespace ts.projectSystem { verifyAfterPartialOrCompleteNpmInstall(0); filesAndFoldersToAdd.push(...[ - { "path": "/a/b/node_modules/.staging/rxjs-22375c61/bundles" }, - { "path": "/a/b/node_modules/.staging/rxjs-22375c61/operator" }, - { "path": "/a/b/node_modules/.staging/rxjs-22375c61/src/add/observable/dom" }, - { "path": "/a/b/node_modules/.staging/@types/lodash-e56c4fe7/index.d.ts", "content": "\n// Stub for lodash\nexport = _;\nexport as namespace _;\ndeclare var _: _.LoDashStatic;\ndeclare namespace _ {\n interface LoDashStatic {\n someProp: string;\n }\n class SomeClass {\n someMethod(): void;\n }\n}" } + { path: "/a/b/node_modules/.staging/rxjs-22375c61/bundles" }, + { path: "/a/b/node_modules/.staging/rxjs-22375c61/operator" }, + { path: "/a/b/node_modules/.staging/rxjs-22375c61/src/add/observable/dom" }, + { path: "/a/b/node_modules/.staging/@types/lodash-e56c4fe7/index.d.ts", content: "\n// Stub for lodash\nexport = _;\nexport as namespace _;\ndeclare var _: _.LoDashStatic;\ndeclare namespace _ {\n interface LoDashStatic {\n someProp: string;\n }\n class SomeClass {\n someMethod(): void;\n }\n}" } ].map(getRootedFileOrFolder)); verifyAfterPartialOrCompleteNpmInstall(2); filesAndFoldersToAdd.push(...[ - { "path": "/a/b/node_modules/.staging/rxjs-22375c61/src/scheduler" }, - { "path": "/a/b/node_modules/.staging/rxjs-22375c61/src/util" }, - { "path": "/a/b/node_modules/.staging/rxjs-22375c61/symbol" }, - { "path": "/a/b/node_modules/.staging/rxjs-22375c61/testing" }, - { "path": "/a/b/node_modules/.staging/rxjs-22375c61/package.json.2252192041", "content": "{\n \"_args\": [\n [\n {\n \"raw\": \"rxjs@^5.4.2\",\n \"scope\": null,\n \"escapedName\": \"rxjs\",\n \"name\": \"rxjs\",\n \"rawSpec\": \"^5.4.2\",\n \"spec\": \">=5.4.2 <6.0.0\",\n \"type\": \"range\"\n },\n \"C:\\\\Users\\\\shkamat\\\\Desktop\\\\app\"\n ]\n ],\n \"_from\": \"rxjs@>=5.4.2 <6.0.0\",\n \"_id\": \"rxjs@5.4.3\",\n \"_inCache\": true,\n \"_location\": \"/rxjs\",\n \"_nodeVersion\": \"7.7.2\",\n \"_npmOperationalInternal\": {\n \"host\": \"s3://npm-registry-packages\",\n \"tmp\": \"tmp/rxjs-5.4.3.tgz_1502407898166_0.6800217325799167\"\n },\n \"_npmUser\": {\n \"name\": \"blesh\",\n \"email\": \"ben@benlesh.com\"\n },\n \"_npmVersion\": \"5.3.0\",\n \"_phantomChildren\": {},\n \"_requested\": {\n \"raw\": \"rxjs@^5.4.2\",\n \"scope\": null,\n \"escapedName\": \"rxjs\",\n \"name\": \"rxjs\",\n \"rawSpec\": \"^5.4.2\",\n \"spec\": \">=5.4.2 <6.0.0\",\n \"type\": \"range\"\n },\n \"_requiredBy\": [\n \"/\"\n ],\n \"_resolved\": \"https://registry.npmjs.org/rxjs/-/rxjs-5.4.3.tgz\",\n \"_shasum\": \"0758cddee6033d68e0fd53676f0f3596ce3d483f\",\n \"_shrinkwrap\": null,\n \"_spec\": \"rxjs@^5.4.2\",\n \"_where\": \"C:\\\\Users\\\\shkamat\\\\Desktop\\\\app\",\n \"author\": {\n \"name\": \"Ben Lesh\",\n \"email\": \"ben@benlesh.com\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/ReactiveX/RxJS/issues\"\n },\n \"config\": {\n \"commitizen\": {\n \"path\": \"cz-conventional-changelog\"\n }\n },\n \"contributors\": [\n {\n \"name\": \"Ben Lesh\",\n \"email\": \"ben@benlesh.com\"\n },\n {\n \"name\": \"Paul Taylor\",\n \"email\": \"paul.e.taylor@me.com\"\n },\n {\n \"name\": \"Jeff Cross\",\n \"email\": \"crossj@google.com\"\n },\n {\n \"name\": \"Matthew Podwysocki\",\n \"email\": \"matthewp@microsoft.com\"\n },\n {\n \"name\": \"OJ Kwon\",\n \"email\": \"kwon.ohjoong@gmail.com\"\n },\n {\n \"name\": \"Andre Staltz\",\n \"email\": \"andre@staltz.com\"\n }\n ],\n \"dependencies\": {\n \"symbol-observable\": \"^1.0.1\"\n },\n \"description\": \"Reactive Extensions for modern JavaScript\",\n \"devDependencies\": {\n \"babel-polyfill\": \"^6.23.0\",\n \"benchmark\": \"^2.1.0\",\n \"benchpress\": \"2.0.0-beta.1\",\n \"chai\": \"^3.5.0\",\n \"color\": \"^0.11.1\",\n \"colors\": \"1.1.2\",\n \"commitizen\": \"^2.8.6\",\n \"coveralls\": \"^2.11.13\",\n \"cz-conventional-changelog\": \"^1.2.0\",\n \"danger\": \"^1.1.0\",\n \"doctoc\": \"^1.0.0\",\n \"escape-string-regexp\": \"^1.0.5 \",\n \"esdoc\": \"^0.4.7\",\n \"eslint\": \"^3.8.0\",\n \"fs-extra\": \"^2.1.2\",\n \"get-folder-size\": \"^1.0.0\",\n \"glob\": \"^7.0.3\",\n \"gm\": \"^1.22.0\",\n \"google-closure-compiler-js\": \"^20170218.0.0\",\n \"gzip-size\": \"^3.0.0\",\n \"http-server\": \"^0.9.0\",\n \"husky\": \"^0.13.3\",\n \"lint-staged\": \"3.2.5\",\n \"lodash\": \"^4.15.0\",\n \"madge\": \"^1.4.3\",\n \"markdown-doctest\": \"^0.9.1\",\n \"minimist\": \"^1.2.0\",\n \"mkdirp\": \"^0.5.1\",\n \"mocha\": \"^3.0.2\",\n \"mocha-in-sauce\": \"0.0.1\",\n \"npm-run-all\": \"^4.0.2\",\n \"npm-scripts-info\": \"^0.3.4\",\n \"nyc\": \"^10.2.0\",\n \"opn-cli\": \"^3.1.0\",\n \"platform\": \"^1.3.1\",\n \"promise\": \"^7.1.1\",\n \"protractor\": \"^3.1.1\",\n \"rollup\": \"0.36.3\",\n \"rollup-plugin-inject\": \"^2.0.0\",\n \"rollup-plugin-node-resolve\": \"^2.0.0\",\n \"rx\": \"latest\",\n \"rxjs\": \"latest\",\n \"shx\": \"^0.2.2\",\n \"sinon\": \"^2.1.0\",\n \"sinon-chai\": \"^2.9.0\",\n \"source-map-support\": \"^0.4.0\",\n \"tslib\": \"^1.5.0\",\n \"tslint\": \"^4.4.2\",\n \"typescript\": \"~2.0.6\",\n \"typings\": \"^2.0.0\",\n \"validate-commit-msg\": \"^2.14.0\",\n \"watch\": \"^1.0.1\",\n \"webpack\": \"^1.13.1\",\n \"xmlhttprequest\": \"1.8.0\"\n },\n \"directories\": {},\n \"dist\": {\n \"integrity\": \"sha512-fSNi+y+P9ss+EZuV0GcIIqPUK07DEaMRUtLJvdcvMyFjc9dizuDjere+A4V7JrLGnm9iCc+nagV/4QdMTkqC4A==\",\n \"shasum\": \"0758cddee6033d68e0fd53676f0f3596ce3d483f\",\n \"tarball\": \"https://registry.npmjs.org/rxjs/-/rxjs-5.4.3.tgz\"\n },\n \"engines\": {\n \"npm\": \">=2.0.0\"\n },\n \"homepage\": \"https://github.com/ReactiveX/RxJS\",\n \"keywords\": [\n \"Rx\",\n \"RxJS\",\n \"ReactiveX\",\n \"ReactiveExtensions\",\n \"Streams\",\n \"Observables\",\n \"Observable\",\n \"Stream\",\n \"ES6\",\n \"ES2015\"\n ],\n \"license\": \"Apache-2.0\",\n \"lint-staged\": {\n \"*.@(js)\": [\n \"eslint --fix\",\n \"git add\"\n ],\n \"*.@(ts)\": [\n \"tslint --fix\",\n \"git add\"\n ]\n },\n \"main\": \"Rx.js\",\n \"maintainers\": [\n {\n \"name\": \"blesh\",\n \"email\": \"ben@benlesh.com\"\n }\n ],\n \"name\": \"rxjs\",\n \"optionalDependencies\": {},\n \"readme\": \"ERROR: No README data found!\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+ssh://git@github.com/ReactiveX/RxJS.git\"\n },\n \"scripts-info\": {\n \"info\": \"List available script\",\n \"build_all\": \"Build all packages (ES6, CJS, UMD) and generate packages\",\n \"build_cjs\": \"Build CJS package with clean up existing build, copy source into dist\",\n \"build_es6\": \"Build ES6 package with clean up existing build, copy source into dist\",\n \"build_closure_core\": \"Minify Global core build using closure compiler\",\n \"build_global\": \"Build Global package, then minify build\",\n \"build_perf\": \"Build CJS & Global build, run macro performance test\",\n \"build_test\": \"Build CJS package & test spec, execute mocha test runner\",\n \"build_cover\": \"Run lint to current code, build CJS & test spec, execute test coverage\",\n \"build_docs\": \"Build ES6 & global package, create documentation using it\",\n \"build_spec\": \"Build test specs\",\n \"check_circular_dependencies\": \"Check codebase has circular dependencies\",\n \"clean_spec\": \"Clean up existing test spec build output\",\n \"clean_dist_cjs\": \"Clean up existing CJS package output\",\n \"clean_dist_es6\": \"Clean up existing ES6 package output\",\n \"clean_dist_global\": \"Clean up existing Global package output\",\n \"commit\": \"Run git commit wizard\",\n \"compile_dist_cjs\": \"Compile codebase into CJS module\",\n \"compile_module_es6\": \"Compile codebase into ES6\",\n \"cover\": \"Execute test coverage\",\n \"lint_perf\": \"Run lint against performance test suite\",\n \"lint_spec\": \"Run lint against test spec\",\n \"lint_src\": \"Run lint against source\",\n \"lint\": \"Run lint against everything\",\n \"perf\": \"Run macro performance benchmark\",\n \"perf_micro\": \"Run micro performance benchmark\",\n \"test_mocha\": \"Execute mocha test runner against existing test spec build\",\n \"test_browser\": \"Execute mocha test runner on browser against existing test spec build\",\n \"test\": \"Clean up existing test spec build, build test spec and execute mocha test runner\",\n \"tests2png\": \"Generate marble diagram image from test spec\",\n \"watch\": \"Watch codebase, trigger compile when source code changes\"\n },\n \"typings\": \"Rx.d.ts\",\n \"version\": \"5.4.3\"\n}\n" } + { path: "/a/b/node_modules/.staging/rxjs-22375c61/src/scheduler" }, + { path: "/a/b/node_modules/.staging/rxjs-22375c61/src/util" }, + { path: "/a/b/node_modules/.staging/rxjs-22375c61/symbol" }, + { path: "/a/b/node_modules/.staging/rxjs-22375c61/testing" }, + { path: "/a/b/node_modules/.staging/rxjs-22375c61/package.json.2252192041", content: "{\n \"_args\": [\n [\n {\n \"raw\": \"rxjs@^5.4.2\",\n \"scope\": null,\n \"escapedName\": \"rxjs\",\n \"name\": \"rxjs\",\n \"rawSpec\": \"^5.4.2\",\n \"spec\": \">=5.4.2 <6.0.0\",\n \"type\": \"range\"\n },\n \"C:\\\\Users\\\\shkamat\\\\Desktop\\\\app\"\n ]\n ],\n \"_from\": \"rxjs@>=5.4.2 <6.0.0\",\n \"_id\": \"rxjs@5.4.3\",\n \"_inCache\": true,\n \"_location\": \"/rxjs\",\n \"_nodeVersion\": \"7.7.2\",\n \"_npmOperationalInternal\": {\n \"host\": \"s3://npm-registry-packages\",\n \"tmp\": \"tmp/rxjs-5.4.3.tgz_1502407898166_0.6800217325799167\"\n },\n \"_npmUser\": {\n \"name\": \"blesh\",\n \"email\": \"ben@benlesh.com\"\n },\n \"_npmVersion\": \"5.3.0\",\n \"_phantomChildren\": {},\n \"_requested\": {\n \"raw\": \"rxjs@^5.4.2\",\n \"scope\": null,\n \"escapedName\": \"rxjs\",\n \"name\": \"rxjs\",\n \"rawSpec\": \"^5.4.2\",\n \"spec\": \">=5.4.2 <6.0.0\",\n \"type\": \"range\"\n },\n \"_requiredBy\": [\n \"/\"\n ],\n \"_resolved\": \"https://registry.npmjs.org/rxjs/-/rxjs-5.4.3.tgz\",\n \"_shasum\": \"0758cddee6033d68e0fd53676f0f3596ce3d483f\",\n \"_shrinkwrap\": null,\n \"_spec\": \"rxjs@^5.4.2\",\n \"_where\": \"C:\\\\Users\\\\shkamat\\\\Desktop\\\\app\",\n \"author\": {\n \"name\": \"Ben Lesh\",\n \"email\": \"ben@benlesh.com\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/ReactiveX/RxJS/issues\"\n },\n \"config\": {\n \"commitizen\": {\n \"path\": \"cz-conventional-changelog\"\n }\n },\n \"contributors\": [\n {\n \"name\": \"Ben Lesh\",\n \"email\": \"ben@benlesh.com\"\n },\n {\n \"name\": \"Paul Taylor\",\n \"email\": \"paul.e.taylor@me.com\"\n },\n {\n \"name\": \"Jeff Cross\",\n \"email\": \"crossj@google.com\"\n },\n {\n \"name\": \"Matthew Podwysocki\",\n \"email\": \"matthewp@microsoft.com\"\n },\n {\n \"name\": \"OJ Kwon\",\n \"email\": \"kwon.ohjoong@gmail.com\"\n },\n {\n \"name\": \"Andre Staltz\",\n \"email\": \"andre@staltz.com\"\n }\n ],\n \"dependencies\": {\n \"symbol-observable\": \"^1.0.1\"\n },\n \"description\": \"Reactive Extensions for modern JavaScript\",\n \"devDependencies\": {\n \"babel-polyfill\": \"^6.23.0\",\n \"benchmark\": \"^2.1.0\",\n \"benchpress\": \"2.0.0-beta.1\",\n \"chai\": \"^3.5.0\",\n \"color\": \"^0.11.1\",\n \"colors\": \"1.1.2\",\n \"commitizen\": \"^2.8.6\",\n \"coveralls\": \"^2.11.13\",\n \"cz-conventional-changelog\": \"^1.2.0\",\n \"danger\": \"^1.1.0\",\n \"doctoc\": \"^1.0.0\",\n \"escape-string-regexp\": \"^1.0.5 \",\n \"esdoc\": \"^0.4.7\",\n \"eslint\": \"^3.8.0\",\n \"fs-extra\": \"^2.1.2\",\n \"get-folder-size\": \"^1.0.0\",\n \"glob\": \"^7.0.3\",\n \"gm\": \"^1.22.0\",\n \"google-closure-compiler-js\": \"^20170218.0.0\",\n \"gzip-size\": \"^3.0.0\",\n \"http-server\": \"^0.9.0\",\n \"husky\": \"^0.13.3\",\n \"lint-staged\": \"3.2.5\",\n \"lodash\": \"^4.15.0\",\n \"madge\": \"^1.4.3\",\n \"markdown-doctest\": \"^0.9.1\",\n \"minimist\": \"^1.2.0\",\n \"mkdirp\": \"^0.5.1\",\n \"mocha\": \"^3.0.2\",\n \"mocha-in-sauce\": \"0.0.1\",\n \"npm-run-all\": \"^4.0.2\",\n \"npm-scripts-info\": \"^0.3.4\",\n \"nyc\": \"^10.2.0\",\n \"opn-cli\": \"^3.1.0\",\n \"platform\": \"^1.3.1\",\n \"promise\": \"^7.1.1\",\n \"protractor\": \"^3.1.1\",\n \"rollup\": \"0.36.3\",\n \"rollup-plugin-inject\": \"^2.0.0\",\n \"rollup-plugin-node-resolve\": \"^2.0.0\",\n \"rx\": \"latest\",\n \"rxjs\": \"latest\",\n \"shx\": \"^0.2.2\",\n \"sinon\": \"^2.1.0\",\n \"sinon-chai\": \"^2.9.0\",\n \"source-map-support\": \"^0.4.0\",\n \"tslib\": \"^1.5.0\",\n \"tslint\": \"^4.4.2\",\n \"typescript\": \"~2.0.6\",\n \"typings\": \"^2.0.0\",\n \"validate-commit-msg\": \"^2.14.0\",\n \"watch\": \"^1.0.1\",\n \"webpack\": \"^1.13.1\",\n \"xmlhttprequest\": \"1.8.0\"\n },\n \"directories\": {},\n \"dist\": {\n \"integrity\": \"sha512-fSNi+y+P9ss+EZuV0GcIIqPUK07DEaMRUtLJvdcvMyFjc9dizuDjere+A4V7JrLGnm9iCc+nagV/4QdMTkqC4A==\",\n \"shasum\": \"0758cddee6033d68e0fd53676f0f3596ce3d483f\",\n \"tarball\": \"https://registry.npmjs.org/rxjs/-/rxjs-5.4.3.tgz\"\n },\n \"engines\": {\n \"npm\": \">=2.0.0\"\n },\n \"homepage\": \"https://github.com/ReactiveX/RxJS\",\n \"keywords\": [\n \"Rx\",\n \"RxJS\",\n \"ReactiveX\",\n \"ReactiveExtensions\",\n \"Streams\",\n \"Observables\",\n \"Observable\",\n \"Stream\",\n \"ES6\",\n \"ES2015\"\n ],\n \"license\": \"Apache-2.0\",\n \"lint-staged\": {\n \"*.@(js)\": [\n \"eslint --fix\",\n \"git add\"\n ],\n \"*.@(ts)\": [\n \"tslint --fix\",\n \"git add\"\n ]\n },\n \"main\": \"Rx.js\",\n \"maintainers\": [\n {\n \"name\": \"blesh\",\n \"email\": \"ben@benlesh.com\"\n }\n ],\n \"name\": \"rxjs\",\n \"optionalDependencies\": {},\n \"readme\": \"ERROR: No README data found!\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+ssh://git@github.com/ReactiveX/RxJS.git\"\n },\n \"scripts-info\": {\n \"info\": \"List available script\",\n \"build_all\": \"Build all packages (ES6, CJS, UMD) and generate packages\",\n \"build_cjs\": \"Build CJS package with clean up existing build, copy source into dist\",\n \"build_es6\": \"Build ES6 package with clean up existing build, copy source into dist\",\n \"build_closure_core\": \"Minify Global core build using closure compiler\",\n \"build_global\": \"Build Global package, then minify build\",\n \"build_perf\": \"Build CJS & Global build, run macro performance test\",\n \"build_test\": \"Build CJS package & test spec, execute mocha test runner\",\n \"build_cover\": \"Run lint to current code, build CJS & test spec, execute test coverage\",\n \"build_docs\": \"Build ES6 & global package, create documentation using it\",\n \"build_spec\": \"Build test specs\",\n \"check_circular_dependencies\": \"Check codebase has circular dependencies\",\n \"clean_spec\": \"Clean up existing test spec build output\",\n \"clean_dist_cjs\": \"Clean up existing CJS package output\",\n \"clean_dist_es6\": \"Clean up existing ES6 package output\",\n \"clean_dist_global\": \"Clean up existing Global package output\",\n \"commit\": \"Run git commit wizard\",\n \"compile_dist_cjs\": \"Compile codebase into CJS module\",\n \"compile_module_es6\": \"Compile codebase into ES6\",\n \"cover\": \"Execute test coverage\",\n \"lint_perf\": \"Run lint against performance test suite\",\n \"lint_spec\": \"Run lint against test spec\",\n \"lint_src\": \"Run lint against source\",\n \"lint\": \"Run lint against everything\",\n \"perf\": \"Run macro performance benchmark\",\n \"perf_micro\": \"Run micro performance benchmark\",\n \"test_mocha\": \"Execute mocha test runner against existing test spec build\",\n \"test_browser\": \"Execute mocha test runner on browser against existing test spec build\",\n \"test\": \"Clean up existing test spec build, build test spec and execute mocha test runner\",\n \"tests2png\": \"Generate marble diagram image from test spec\",\n \"watch\": \"Watch codebase, trigger compile when source code changes\"\n },\n \"typings\": \"Rx.d.ts\",\n \"version\": \"5.4.3\"\n}\n" } ].map(getRootedFileOrFolder)); verifyAfterPartialOrCompleteNpmInstall(0); @@ -5685,13 +5685,13 @@ namespace ts.projectSystem { filesAndFoldersToAdd.length--; // and add few more folders/files filesAndFoldersToAdd.push(...[ - { "path": "/a/b/node_modules/symbol-observable" }, - { "path": "/a/b/node_modules/@types" }, - { "path": "/a/b/node_modules/@types/lodash" }, - { "path": "/a/b/node_modules/lodash" }, - { "path": "/a/b/node_modules/rxjs" }, - { "path": "/a/b/node_modules/typescript" }, - { "path": "/a/b/node_modules/.bin" } + { path: "/a/b/node_modules/symbol-observable" }, + { path: "/a/b/node_modules/@types" }, + { path: "/a/b/node_modules/@types/lodash" }, + { path: "/a/b/node_modules/lodash" }, + { path: "/a/b/node_modules/rxjs" }, + { path: "/a/b/node_modules/typescript" }, + { path: "/a/b/node_modules/.bin" } ].map(getRootedFileOrFolder)); // From the type root update verifyAfterPartialOrCompleteNpmInstall(2); diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index fb1a7a26a7a..2ae9587b78e 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -776,8 +776,8 @@ namespace ts.projectSystem { const bowerJson = { path: "/bower.json", content: JSON.stringify({ - "dependencies": { - "jquery": "^3.1.0" + dependencies: { + jquery: "^3.1.0" } }) }; @@ -1012,7 +1012,7 @@ namespace ts.projectSystem { const packageJson = { path: "/a/b/package.json", content: JSON.stringify({ - "dependencies": { + dependencies: { "; say ‘Hello from TypeScript!’ #": "0.0.x" } }) @@ -1094,7 +1094,7 @@ namespace ts.projectSystem { content: "" }; const host = createServerHost([f, node]); - const cache = createMapFromTemplate({ "node": node.path }); + const cache = createMapFromTemplate({ node: node.path }); const logger = trackingLogger(); const result = JsTyping.discoverTypings(host, logger.log, [f.path], getDirectoryPath(f.path), emptySafeList, cache, { enable: true }, ["fs", "bar"]); assert.deepEqual(logger.finish(), [ @@ -1144,7 +1144,7 @@ namespace ts.projectSystem { }; const packageFile = { path: "/a/package.json", - content: JSON.stringify({ dependencies: { "commander": "1.0.0" } }) + content: JSON.stringify({ dependencies: { commander: "1.0.0" } }) }; const cachePath = "/a/cache/"; const commander = { @@ -1194,7 +1194,7 @@ namespace ts.projectSystem { }; const packageFile = { path: "/a/package.json", - content: JSON.stringify({ dependencies: { "commander": "1.0.0" } }) + content: JSON.stringify({ dependencies: { commander: "1.0.0" } }) }; const cachePath = "/a/cache/"; const commander = { @@ -1246,7 +1246,7 @@ namespace ts.projectSystem { }; const packageFile = { path: "/a/package.json", - content: JSON.stringify({ dependencies: { "commander": "1.0.0" } }) + content: JSON.stringify({ dependencies: { commander: "1.0.0" } }) }; const cachePath = "/a/cache/"; const host = createServerHost([f1, packageFile]); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 086bb6b38d8..0627f3038bb 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -103,9 +103,9 @@ namespace ts.server { const compilerOptionConverters = prepareConvertersForEnumLikeCompilerOptions(optionDeclarations); const indentStyle = createMapFromTemplate({ - "none": IndentStyle.None, - "block": IndentStyle.Block, - "smart": IndentStyle.Smart + none: IndentStyle.None, + block: IndentStyle.Block, + smart: IndentStyle.Smart }); export interface TypesMapFile { @@ -134,31 +134,31 @@ namespace ts.server { const defaultTypeSafeList: SafeList = { "jquery": { // jquery files can have names like "jquery-1.10.2.min.js" (or "jquery.intellisense.js") - "match": /jquery(-(\.?\d+)+)?(\.intellisense)?(\.min)?\.js$/i, - "types": ["jquery"] + match: /jquery(-(\.?\d+)+)?(\.intellisense)?(\.min)?\.js$/i, + types: ["jquery"] }, "WinJS": { // e.g. c:/temp/UWApp1/lib/winjs-4.0.1/js/base.js - "match": /^(.*\/winjs-[.\d]+)\/js\/base\.js$/i, // If the winjs/base.js file is found.. - "exclude": [["^", 1, "/.*"]], // ..then exclude all files under the winjs folder - "types": ["winjs"] // And fetch the @types package for WinJS + match: /^(.*\/winjs-[.\d]+)\/js\/base\.js$/i, // If the winjs/base.js file is found.. + exclude: [["^", 1, "/.*"]], // ..then exclude all files under the winjs folder + types: ["winjs"] // And fetch the @types package for WinJS }, "Kendo": { // e.g. /Kendo3/wwwroot/lib/kendo/kendo.all.min.js - "match": /^(.*\/kendo)\/kendo\.all\.min\.js$/i, - "exclude": [["^", 1, "/.*"]], - "types": ["kendo-ui"] + match: /^(.*\/kendo)\/kendo\.all\.min\.js$/i, + exclude: [["^", 1, "/.*"]], + types: ["kendo-ui"] }, "Office Nuget": { // e.g. /scripts/Office/1/excel-15.debug.js - "match": /^(.*\/office\/1)\/excel-\d+\.debug\.js$/i, // Office NuGet package is installed under a "1/office" folder - "exclude": [["^", 1, "/.*"]], // Exclude that whole folder if the file indicated above is found in it - "types": ["office"] // @types package to fetch instead + match: /^(.*\/office\/1)\/excel-\d+\.debug\.js$/i, // Office NuGet package is installed under a "1/office" folder + exclude: [["^", 1, "/.*"]], // Exclude that whole folder if the file indicated above is found in it + types: ["office"] // @types package to fetch instead }, "Minified files": { // e.g. /whatever/blah.min.js - "match": /^(.+\.min\.js)$/i, - "exclude": [["^", 1, "$"]] + match: /^(.+\.min\.js)$/i, + exclude: [["^", 1, "$"]] } }; diff --git a/src/server/server.ts b/src/server/server.ts index 4902983ad45..f4faa0d3c77 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -828,7 +828,7 @@ namespace ts.server { if (logger.hasLevel(LogLevel.verbose)) { logger.info(`Starting ${process.execPath} with args:${stringifyIndented(args)}`); } - childProcess.execFileSync(process.execPath, args, { stdio: "ignore", env: { "ELECTRON_RUN_AS_NODE": "1" } }); + childProcess.execFileSync(process.execPath, args, { stdio: "ignore", env: { ELECTRON_RUN_AS_NODE: "1" } }); status = true; if (logger.hasLevel(LogLevel.verbose)) { logger.info(`WatchGuard for path ${path} returned: OK`); diff --git a/tslint.json b/tslint.json index 98033b92265..2d7c702b8aa 100644 --- a/tslint.json +++ b/tslint.json @@ -74,6 +74,7 @@ // Config different from tslint:latest "no-implicit-dependencies": [true, "dev"], + "object-literal-key-quotes": [true, "consistent-as-needed"], "variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore"], // TODO @@ -94,7 +95,6 @@ "no-submodule-imports": false, "no-unnecessary-initializer": false, "no-var-requires": false, - "object-literal-key-quotes": false, "ordered-imports": false, "prefer-conditional-expression": false, "radix": false, From 2f13222180dee1cbfac550955d98f2da556b7c8a Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Mon, 6 Nov 2017 18:29:38 -0800 Subject: [PATCH 055/138] Handle windows linebreaks in getSourceFileImportLocation --- src/services/utilities.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 36089f94f73..643aae2bae1 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1335,18 +1335,30 @@ namespace ts { let position = 0; // However we should still skip a pinned comment at the top if (ranges.length && ranges[0].kind === SyntaxKind.MultiLineCommentTrivia && isPinnedComment(text, ranges[0])) { - position = ranges[0].end + 1; + position = ranges[0].end; + AdvancePastLineBreak(); ranges = ranges.slice(1); } // As well as any triple slash references for (const range of ranges) { if (range.kind === SyntaxKind.SingleLineCommentTrivia && isRecognizedTripleSlashComment(node.text, range.pos, range.end)) { - position = range.end + 1; + position = range.end; + AdvancePastLineBreak(); continue; } break; } return position; + + function AdvancePastLineBreak() { + if (text.charCodeAt(position) === 0xD) { + position++; + } + + if (text.charCodeAt(position) === 0xA) { + position++; + } + } } /** From 77b24aec839501c709d3c37be6626e399cb7fd97 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 6 Nov 2017 18:38:03 -0800 Subject: [PATCH 056/138] Apply 'unified-signatures' tslint rule (#19738) * Apply 'unified-signatures' tslint rule * Fix new failure --- src/compiler/factory.ts | 7 +++--- src/harness/fourslash.ts | 23 ++++++------------- src/services/types.ts | 2 ++ .../reference/api/tsserverlibrary.d.ts | 5 ++-- tests/baselines/reference/api/typescript.d.ts | 5 ++-- tslint.json | 1 - 6 files changed, 17 insertions(+), 26 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index c9e0fec5927..6a56b6da049 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -70,11 +70,10 @@ namespace ts { // Literals - export function createLiteral(value: string): StringLiteral; + /** If a node is passed, creates a string literal whose source text is read from a source node during emit. */ + export function createLiteral(value: string | StringLiteral | NumericLiteral | Identifier): StringLiteral; export function createLiteral(value: number): NumericLiteral; export function createLiteral(value: boolean): BooleanLiteral; - /** Create a string literal whose source text is read from a source node during emit. */ - export function createLiteral(sourceNode: StringLiteral | NumericLiteral | Identifier): StringLiteral; export function createLiteral(value: string | number | boolean): PrimaryExpression; export function createLiteral(value: string | number | boolean | StringLiteral | NumericLiteral | Identifier): PrimaryExpression { if (typeof value === "number") { @@ -113,6 +112,7 @@ namespace ts { export function createIdentifier(text: string): Identifier; /* @internal */ + // tslint:disable-next-line unified-signatures export function createIdentifier(text: string, typeArguments: ReadonlyArray): Identifier; export function createIdentifier(text: string, typeArguments?: ReadonlyArray): Identifier { const node = createSynthesizedNode(SyntaxKind.Identifier); @@ -166,6 +166,7 @@ namespace ts { /** Create a unique name generated for a node. */ export function getGeneratedNameForNode(node: Node): Identifier; + // tslint:disable-next-line unified-signatures /*@internal*/ export function getGeneratedNameForNode(node: Node, shouldSkipNameGenerationScope?: boolean): Identifier; export function getGeneratedNameForNode(node: Node, shouldSkipNameGenerationScope?: boolean): Identifier { const name = createIdentifier(""); diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 85011525d52..91e22689fcf 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -483,9 +483,7 @@ namespace FourSlash { } // Opens a file given its 0-based index or fileName - public openFile(index: number, content?: string, scriptKindName?: string): void; - public openFile(name: string, content?: string, scriptKindName?: string): void; - public openFile(indexOrName: any, content?: string, scriptKindName?: string) { + public openFile(indexOrName: number | string, content?: string, scriptKindName?: string): void { const fileToOpen: FourSlashFile = this.findFile(indexOrName); fileToOpen.fileName = ts.normalizeSlashes(fileToOpen.fileName); this.activeFile = fileToOpen; @@ -3093,7 +3091,7 @@ Actual: ${stringify(fullActual)}`); this.raiseError(`Expected "${stringify({ entryId, text, documentation, kind })}" to be in list [${itemsString}]`); } - private findFile(indexOrName: any) { + private findFile(indexOrName: string | number) { let result: FourSlashFile; if (typeof indexOrName === "number") { const index = indexOrName; @@ -3745,9 +3743,7 @@ namespace FourSlashInterface { this.state.goToImplementation(); } - public position(position: number, fileIndex?: number): void; - public position(position: number, fileName?: string): void; - public position(position: number, fileNameOrIndex?: any): void { + public position(position: number, fileNameOrIndex?: string | number): void { if (fileNameOrIndex !== undefined) { this.file(fileNameOrIndex); } @@ -3757,9 +3753,7 @@ namespace FourSlashInterface { // Opens a file, given either its index as it // appears in the test source, or its filename // as specified in the test metadata - public file(index: number, content?: string, scriptKindName?: string): void; - public file(name: string, content?: string, scriptKindName?: string): void; - public file(indexOrName: any, content?: string, scriptKindName?: string): void { + public file(indexOrName: number | string, content?: string, scriptKindName?: string): void { this.state.openFile(indexOrName, content, scriptKindName); } @@ -3966,17 +3960,14 @@ namespace FourSlashInterface { this.state.verifyGoToDefinitionIs(endMarkers); } - public goToDefinition(startMarkerName: string | string[], endMarkerName: string | string[]): void; - public goToDefinition(startMarkerName: string | string[], endMarkerName: string | string[], range: FourSlash.Range): void; - public goToDefinition(startsAndEnds: [string | string[], string | string[]][]): void; - public goToDefinition(startsAndEnds: { [startMarkerName: string]: string | string[] }): void; + public goToDefinition(startMarkerName: string | string[], endMarkerName: string | string[], range?: FourSlash.Range): void; + public goToDefinition(startsAndEnds: [string | string[], string | string[]][] | { [startMarkerName: string]: string | string[] }): void; public goToDefinition(arg0: any, endMarkerName?: string | string[]) { this.state.verifyGoToDefinition(arg0, endMarkerName); } public goToType(startMarkerName: string | string[], endMarkerName: string | string[]): void; - public goToType(startsAndEnds: [string | string[], string | string[]][]): void; - public goToType(startsAndEnds: { [startMarkerName: string]: string | string[] }): void; + public goToType(startsAndEnds: [string | string[], string | string[]][] | { [startMarkerName: string]: string | string[] }): void; public goToType(arg0: any, endMarkerName?: string | string[]) { this.state.verifyGoToType(arg0, endMarkerName); } diff --git a/src/services/types.ts b/src/services/types.ts index e93ae9686d7..a9244982fbb 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -5,9 +5,11 @@ namespace ts { getChildAt(index: number, sourceFile?: SourceFile): Node; getChildren(sourceFile?: SourceFile): Node[]; /* @internal */ + // tslint:disable-next-line unified-signatures getChildren(sourceFile?: SourceFileLike): Node[]; getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number; /* @internal */ + // tslint:disable-next-line unified-signatures getStart(sourceFile?: SourceFileLike, includeJsDocComment?: boolean): number; getFullStart(): number; getEnd(): number; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 415565a6fa1..9b2270d29e5 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3271,11 +3271,10 @@ declare namespace ts { } declare namespace ts { function createNodeArray(elements?: ReadonlyArray, hasTrailingComma?: boolean): NodeArray; - function createLiteral(value: string): StringLiteral; + /** If a node is passed, creates a string literal whose source text is read from a source node during emit. */ + function createLiteral(value: string | StringLiteral | NumericLiteral | Identifier): StringLiteral; function createLiteral(value: number): NumericLiteral; function createLiteral(value: boolean): BooleanLiteral; - /** Create a string literal whose source text is read from a source node during emit. */ - function createLiteral(sourceNode: StringLiteral | NumericLiteral | Identifier): StringLiteral; function createLiteral(value: string | number | boolean): PrimaryExpression; function createNumericLiteral(value: string): NumericLiteral; function createIdentifier(text: string): Identifier; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index fd58e72181a..6ef259ddc8f 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3218,11 +3218,10 @@ declare namespace ts { } declare namespace ts { function createNodeArray(elements?: ReadonlyArray, hasTrailingComma?: boolean): NodeArray; - function createLiteral(value: string): StringLiteral; + /** If a node is passed, creates a string literal whose source text is read from a source node during emit. */ + function createLiteral(value: string | StringLiteral | NumericLiteral | Identifier): StringLiteral; function createLiteral(value: number): NumericLiteral; function createLiteral(value: boolean): BooleanLiteral; - /** Create a string literal whose source text is read from a source node during emit. */ - function createLiteral(sourceNode: StringLiteral | NumericLiteral | Identifier): StringLiteral; function createLiteral(value: string | number | boolean): PrimaryExpression; function createNumericLiteral(value: string): NumericLiteral; function createIdentifier(text: string): Identifier; diff --git a/tslint.json b/tslint.json index 2d7c702b8aa..658beb14d16 100644 --- a/tslint.json +++ b/tslint.json @@ -100,7 +100,6 @@ "radix": false, "space-before-function-paren": false, "trailing-comma": false, - "unified-signatures": false, // These should be done automatically by a formatter. https://github.com/Microsoft/TypeScript/issues/18340 "align": false, From 6d273cfb33dfebe0dcd9b0314b0e1c6a571edfde Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 6 Nov 2017 19:14:24 -0800 Subject: [PATCH 057/138] Consistently use "JSX Attribute" completion kind (#19781) * Consistently use "JSX Attribute" completion kind * Update tests and fix bug * Fix bug: In a JsxOpeningElement, if at an Identifier we are not at an attribute but at the tag itself. If at a GreaterThanToken, we are about to fill in an attribute. --- src/services/symbolDisplay.ts | 12 +++++++--- .../fourslash/completionsJsxAttribute.ts | 22 +++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 tests/cases/fourslash/completionsJsxAttribute.ts diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index e3ef4d3e495..ad9ac88bdfc 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -75,10 +75,16 @@ namespace ts.SymbolDisplay { } return unionPropertyKind; } - if (location.parent && isJsxAttribute(location.parent)) { - return ScriptElementKind.jsxAttribute; + // If we requested completions after `x.` at the top-level, we may be at a source file location. + switch (location.parent && location.parent.kind) { + // If we've typed a character of the attribute name, will be 'JsxAttribute', else will be 'JsxOpeningElement'. + case SyntaxKind.JsxOpeningElement: + return location.kind === SyntaxKind.Identifier ? ScriptElementKind.memberVariableElement : ScriptElementKind.jsxAttribute; + case SyntaxKind.JsxAttribute: + return ScriptElementKind.jsxAttribute; + default: + return ScriptElementKind.memberVariableElement; } - return ScriptElementKind.memberVariableElement; } return ScriptElementKind.unknown; diff --git a/tests/cases/fourslash/completionsJsxAttribute.ts b/tests/cases/fourslash/completionsJsxAttribute.ts new file mode 100644 index 00000000000..29e6122ef18 --- /dev/null +++ b/tests/cases/fourslash/completionsJsxAttribute.ts @@ -0,0 +1,22 @@ +/// + +// @jsx: preserve + +// @Filename: /a.tsx +////declare namespace JSX { +//// interface Element {} +//// interface IntrinsicElements { +//// div: { +//// /** Doc */ +//// foo: string +//// } +//// } +////} +//// +////
; + +goTo.marker(); +verify.completionEntryDetailIs("foo", "(JSX attribute) foo: string", "Doc ", "JSX attribute", []); +edit.insert("f"); +verify.completionEntryDetailIs("foo", "(JSX attribute) foo: string", "Doc ", "JSX attribute", []); + From ed335a66fa685077452dd6059bfff21b9742889d Mon Sep 17 00:00:00 2001 From: csigs Date: Tue, 7 Nov 2017 05:10:13 +0000 Subject: [PATCH 058/138] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 36 +++++++++++++++++++ .../diagnosticMessages.generated.json.lcl | 36 +++++++++++++++++++ .../diagnosticMessages.generated.json.lcl | 36 +++++++++++++++++++ 3 files changed, 108 insertions(+) diff --git a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl index d96fb42d4ea..4865cf6c508 100644 --- a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2250,6 +2250,15 @@ + + + + + + + + + @@ -2979,6 +2988,15 @@ + + + + + + + + + @@ -4221,6 +4239,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl index 326158fcca0..2bf61430d60 100644 --- a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2250,6 +2250,15 @@ + + + + + + + + + @@ -2979,6 +2988,15 @@ + + + + + + + + + @@ -4221,6 +4239,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl index b0897a56d25..1e480ff2a08 100644 --- a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2225,6 +2225,15 @@ + + + + + + + + + @@ -2954,6 +2963,15 @@ + + + + + + + + + @@ -4193,6 +4211,24 @@ + + + + + + + + + + + + + + + + + + From 70cabdda419748c0ce10d0cd15e025cbb5bc0fae Mon Sep 17 00:00:00 2001 From: Aluan Haddad Date: Tue, 7 Nov 2017 01:55:37 -0500 Subject: [PATCH 059/138] fix inconsistencies in import UMD code fixes adapting to module format (#19572) * improve import code fixes for UMD modules - use default import under --allowSyntheticDefaultImports - import..require support - make make quick fix info match resulting import - make diagnostics * Address PR feedback: - extract test for synethetic default imports into getAllowSyntheticDefaultImports in core.ts - use getAllowSyntheticDefaultImports in checker.ts and importFixes.ts - move compilerOptions to top level destructuring * add tests * remove `import =` quick fix and supporting code. * update feature tests * remove errant whitespace --- src/compiler/checker.ts | 2 +- src/compiler/core.ts | 7 ++++ src/compiler/diagnosticMessages.json | 8 ++++ src/services/codefixes/importFixes.ts | 39 +++++++++++++------ ...xNewImportAllowSyntheticDefaultImports0.ts | 18 +++++++++ ...xNewImportAllowSyntheticDefaultImports1.ts | 18 +++++++++ ...xNewImportAllowSyntheticDefaultImports2.ts | 18 +++++++++ 7 files changed, 98 insertions(+), 12 deletions(-) create mode 100644 tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports0.ts create mode 100644 tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports1.ts create mode 100644 tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 556046f3d76..7bce66892de 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -66,7 +66,7 @@ namespace ts { const languageVersion = getEmitScriptTarget(compilerOptions); const modulekind = getEmitModuleKind(compilerOptions); const noUnusedIdentifiers = !!compilerOptions.noUnusedLocals || !!compilerOptions.noUnusedParameters; - const allowSyntheticDefaultImports = typeof compilerOptions.allowSyntheticDefaultImports !== "undefined" ? compilerOptions.allowSyntheticDefaultImports : modulekind === ModuleKind.System; + const allowSyntheticDefaultImports = getAllowSyntheticDefaultImports(compilerOptions); const strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks"); const strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes"); const noImplicitAny = getStrictOptionValue(compilerOptions, "noImplicitAny"); diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 5fb7019dfb2..4fb072b1112 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1916,6 +1916,13 @@ namespace ts { return moduleResolution; } + export function getAllowSyntheticDefaultImports(compilerOptions: CompilerOptions) { + const moduleKind = getEmitModuleKind(compilerOptions); + return compilerOptions.allowSyntheticDefaultImports !== undefined + ? compilerOptions.allowSyntheticDefaultImports + : moduleKind === ModuleKind.System; + } + export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "alwaysStrict"; export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index d3669ce397d..60e3d6c4c4f 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3801,5 +3801,13 @@ "Install '{0}'": { "category": "Message", "code": 95014 + }, + "Import '{0}' = require(\"{1}\").": { + "category": "Message", + "code": 95015 + }, + "Import * as '{0}' from \"{1}\".": { + "category": "Message", + "code": 95016 } } diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 3f0d27e5b07..73cedc883be 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -180,7 +180,7 @@ namespace ts.codefix { export const enum ImportKind { Named, Default, - Namespace, + Namespace } export function getCodeActionForImport(moduleSymbol: Symbol, context: ImportCodeFixOptions): ImportCodeAction[] { @@ -212,7 +212,7 @@ namespace ts.codefix { function getNamespaceImportName(declaration: AnyImportSyntax): Identifier { if (declaration.kind === SyntaxKind.ImportDeclaration) { - const namedBindings = declaration.importClause && declaration.importClause.namedBindings; + const namedBindings = declaration.importClause && isImportClause(declaration.importClause) && declaration.importClause.namedBindings; return namedBindings && namedBindings.kind === SyntaxKind.NamespaceImport ? namedBindings.name : undefined; } else { @@ -237,6 +237,8 @@ namespace ts.codefix { return parent as ImportDeclaration; case SyntaxKind.ExternalModuleReference: return (parent as ExternalModuleReference).parent; + case SyntaxKind.ImportEqualsDeclaration: + return parent as ImportEqualsDeclaration; default: Debug.assert(parent.kind === SyntaxKind.ExportDeclaration); // Ignore these, can't add imports to them. @@ -249,11 +251,13 @@ namespace ts.codefix { const lastImportDeclaration = findLast(sourceFile.statements, isAnyImportSyntax); const moduleSpecifierWithoutQuotes = stripQuotes(moduleSpecifier); + const quotedModuleSpecifier = createStringLiteralWithQuoteStyle(sourceFile, moduleSpecifierWithoutQuotes); const importDecl = createImportDeclaration( - /*decorators*/ undefined, - /*modifiers*/ undefined, + /*decorators*/ undefined, + /*modifiers*/ undefined, createImportClauseOfKind(kind, symbolName), - createStringLiteralWithQuoteStyle(sourceFile, moduleSpecifierWithoutQuotes)); + quotedModuleSpecifier); + const changes = ChangeTracker.with(context, changeTracker => { if (lastImportDeclaration) { changeTracker.insertNodeAfter(sourceFile, lastImportDeclaration, importDecl, { suffix: newLineCharacter }); @@ -263,11 +267,15 @@ namespace ts.codefix { } }); + const actionFormat = kind === ImportKind.Namespace + ? Diagnostics.Import_Asterisk_as_0_from_1 + : Diagnostics.Import_0_from_1; + // if this file doesn't have any import statements, insert an import statement and then insert a new line // between the only import statement and user code. Otherwise just insert the statement because chances // are there are already a new line seperating code and import statements. return createCodeAction( - Diagnostics.Import_0_from_1, + actionFormat, [symbolName, moduleSpecifierWithoutQuotes], changes, "NewImport", @@ -282,7 +290,7 @@ namespace ts.codefix { return literal; } - function createImportClauseOfKind(kind: ImportKind, symbolName: string) { + function createImportClauseOfKind(kind: ImportKind.Default | ImportKind.Named | ImportKind.Namespace, symbolName: string) { const id = createIdentifier(symbolName); switch (kind) { case ImportKind.Default: @@ -534,7 +542,7 @@ namespace ts.codefix { declarations: ReadonlyArray): ImportCodeAction { const fromExistingImport = firstDefined(declarations, declaration => { if (declaration.kind === SyntaxKind.ImportDeclaration && declaration.importClause) { - const changes = tryUpdateExistingImport(ctx, declaration.importClause); + const changes = tryUpdateExistingImport(ctx, isImportClause(declaration.importClause) && declaration.importClause || undefined); if (changes) { const moduleSpecifierWithoutQuotes = stripQuotes(declaration.moduleSpecifier.getText()); return createCodeAction( @@ -564,9 +572,10 @@ namespace ts.codefix { return expression && isStringLiteral(expression) ? expression.text : undefined; } - function tryUpdateExistingImport(context: SymbolContext & { kind: ImportKind }, importClause: ImportClause): FileTextChanges[] | undefined { + function tryUpdateExistingImport(context: SymbolContext & { kind: ImportKind }, importClause: ImportClause | ImportEqualsDeclaration): FileTextChanges[] | undefined { const { symbolName, sourceFile, kind } = context; - const { name, namedBindings } = importClause; + const { name } = importClause; + const { namedBindings } = importClause.kind !== SyntaxKind.ImportEqualsDeclaration && importClause; switch (kind) { case ImportKind.Default: return name ? undefined : ChangeTracker.with(context, t => @@ -627,7 +636,7 @@ namespace ts.codefix { } function getActionsForUMDImport(context: ImportCodeFixContext): ImportCodeAction[] { - const { checker, symbolToken } = context; + const { checker, symbolToken, compilerOptions } = context; const umdSymbol = checker.getSymbolAtLocation(symbolToken); let symbol: ts.Symbol; let symbolName: string; @@ -644,6 +653,14 @@ namespace ts.codefix { Debug.fail("Either the symbol or the JSX namespace should be a UMD global if we got here"); } + const allowSyntheticDefaultImports = getAllowSyntheticDefaultImports(compilerOptions); + + // Import a synthetic `default` if enabled. + if (allowSyntheticDefaultImports) { + return getCodeActionForImport(symbol, { ...context, symbolName, kind: ImportKind.Default }); + } + + // Fall back to the `import * as ns` style import. return getCodeActionForImport(symbol, { ...context, symbolName, kind: ImportKind.Namespace }); } diff --git a/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports0.ts b/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports0.ts new file mode 100644 index 00000000000..3b62e0e9d5f --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports0.ts @@ -0,0 +1,18 @@ +/// +// @AllowSyntheticDefaultImports: true + +// @Filename: a/f1.ts +//// [|export var x = 0; +//// bar/*0*/();|] + +// @Filename: a/foo.d.ts +//// declare function bar(): number; +//// export = bar; +//// export as namespace bar; + +verify.importFixAtPosition([ +`import bar from "./foo"; + +export var x = 0; +bar();` + ]); \ No newline at end of file diff --git a/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports1.ts b/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports1.ts new file mode 100644 index 00000000000..c6c2a554874 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports1.ts @@ -0,0 +1,18 @@ +/// +// @Module: system + +// @Filename: a/f1.ts +//// [|export var x = 0; +//// bar/*0*/();|] + +// @Filename: a/foo.d.ts +//// declare function bar(): number; +//// export = bar; +//// export as namespace bar; + +verify.importFixAtPosition([ +`import bar from "./foo"; + +export var x = 0; +bar();` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports2.ts b/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports2.ts new file mode 100644 index 00000000000..3421d603297 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports2.ts @@ -0,0 +1,18 @@ +/// +// @AllowSyntheticDefaultImports: false + +// @Filename: a/f1.ts +//// [|export var x = 0; +//// bar/*0*/();|] + +// @Filename: a/foo.d.ts +//// declare function bar(): number; +//// export = bar; +//// export as namespace bar; + +verify.importFixAtPosition([ +`import * as bar from "./foo"; + +export var x = 0; +bar();` +]); \ No newline at end of file From 9ba9a893cc7f8fa3ab2bb40cbe5559147f081018 Mon Sep 17 00:00:00 2001 From: csigs Date: Tue, 7 Nov 2017 11:10:13 +0000 Subject: [PATCH 060/138] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl index 2653d211440..2693d7cce27 100644 --- a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2241,6 +2241,15 @@ + + + + + + + + + @@ -2970,6 +2979,15 @@ + + + + + + + + + @@ -4212,6 +4230,24 @@ + + + + + + + + + + + + + + + + + + From 9c8129eeac9747f953f95c82f7bd05fd8d45d579 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 7 Nov 2017 06:51:35 -0800 Subject: [PATCH 061/138] Enable 'no-invalid-template-strings' lint rule (#19790) --- src/compiler/utilities.ts | 2 ++ src/harness/unittests/printer.ts | 1 + src/harness/unittests/services/colorization.ts | 2 ++ tslint.json | 1 - 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index dffadda45b2..41a5512cb2a 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -363,8 +363,10 @@ namespace ts { case SyntaxKind.NoSubstitutionTemplateLiteral: return "`" + escapeText(node.text, CharacterCodes.backtick) + "`"; case SyntaxKind.TemplateHead: + // tslint:disable-next-line no-invalid-template-strings return "`" + escapeText(node.text, CharacterCodes.backtick) + "${"; case SyntaxKind.TemplateMiddle: + // tslint:disable-next-line no-invalid-template-strings return "}" + escapeText(node.text, CharacterCodes.backtick) + "${"; case SyntaxKind.TemplateTail: return "}" + escapeText(node.text, CharacterCodes.backtick) + "`"; diff --git a/src/harness/unittests/printer.ts b/src/harness/unittests/printer.ts index 4aaddce5c00..ad60484d963 100644 --- a/src/harness/unittests/printer.ts +++ b/src/harness/unittests/printer.ts @@ -55,6 +55,7 @@ namespace ts { printsCorrectly("removeComments", { removeComments: true }, printer => printer.printFile(sourceFile)); // github #14948 + // tslint:disable-next-line no-invalid-template-strings printsCorrectly("templateLiteral", {}, printer => printer.printFile(createSourceFile("source.ts", "let greeting = `Hi ${name}, how are you?`;", ScriptTarget.ES2017))); // github #18071 diff --git a/src/harness/unittests/services/colorization.ts b/src/harness/unittests/services/colorization.ts index 6dbc7732a00..17d4132e9e5 100644 --- a/src/harness/unittests/services/colorization.ts +++ b/src/harness/unittests/services/colorization.ts @@ -1,5 +1,7 @@ /// +// tslint:disable no-invalid-template-strings (lots of tests use quoted code) + interface ClassificationEntry { value: any; classification: ts.TokenClass; diff --git a/tslint.json b/tslint.json index 658beb14d16..914681329ec 100644 --- a/tslint.json +++ b/tslint.json @@ -89,7 +89,6 @@ "no-empty": false, "no-empty-interface": false, "no-eval": false, - "no-invalid-template-strings": false, "no-object-literal-type-assertion": false, "no-shadowed-variable": false, "no-submodule-imports": false, From 2fcf8b7068b5cf2ef1bd5c1929b1fb9a241f9a1f Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 7 Nov 2017 07:41:21 -0800 Subject: [PATCH 062/138] Fix assertion -- an import may come from a require() call (#19667) * Fix assertion -- an import may come from a require() call * Add test for `import("./a")` --- src/services/codefixes/importFixes.ts | 8 ++-- .../fourslash/completionsImport_require.ts | 42 +++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 tests/cases/fourslash/completionsImport_require.ts diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 73cedc883be..a7f0e2e0814 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -237,12 +237,12 @@ namespace ts.codefix { return parent as ImportDeclaration; case SyntaxKind.ExternalModuleReference: return (parent as ExternalModuleReference).parent; - case SyntaxKind.ImportEqualsDeclaration: - return parent as ImportEqualsDeclaration; - default: - Debug.assert(parent.kind === SyntaxKind.ExportDeclaration); + case SyntaxKind.ExportDeclaration: + case SyntaxKind.CallExpression: // For "require()" calls // Ignore these, can't add imports to them. return undefined; + default: + Debug.fail(); } } diff --git a/tests/cases/fourslash/completionsImport_require.ts b/tests/cases/fourslash/completionsImport_require.ts new file mode 100644 index 00000000000..e0a6b00d462 --- /dev/null +++ b/tests/cases/fourslash/completionsImport_require.ts @@ -0,0 +1,42 @@ +/// + +// @allowJs: true + +// @Filename: /a.ts +////export const foo = 0; + +// @Filename: /b.js +////const a = require("./a"); +////fo/*b*/ + +// @Filename: /c.js +////const a = import("./a"); +////fo/*c*/ + +goTo.marker("b"); +verify.completionListContains({ name: "foo", source: "/a" }, "const foo: 0", "", "const", /*spanIndex*/ undefined, /*hasAction*/ true, { includeExternalModuleExports: true }); + +verify.applyCodeActionFromCompletion("b", { + name: "foo", + source: "/a", + description: `Import 'foo' from "./a".`, + // TODO: GH#18445 + newFileContent: `import { foo } from "./a";\r +\r +const a = require("./a"); +fo`, +}); + +goTo.marker("c"); +verify.completionListContains({ name: "foo", source: "/a" }, "const foo: 0", "", "const", /*spanIndex*/ undefined, /*hasAction*/ true, { includeExternalModuleExports: true }); + +verify.applyCodeActionFromCompletion("c", { + name: "foo", + source: "/a", + description: `Import 'foo' from "./a".`, + // TODO: GH#18445 + newFileContent: `import { foo } from "./a";\r +\r +const a = import("./a"); +fo`, +}); From 6a0779333212ea4156481d369752d8f66269424f Mon Sep 17 00:00:00 2001 From: Jing Ma Date: Wed, 8 Nov 2017 01:02:26 +0800 Subject: [PATCH 063/138] Fixed minor syntactics error (#19801) --- src/lib/es2015.core.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/es2015.core.d.ts b/src/lib/es2015.core.d.ts index 0e1b46f2eb0..ccff68968f1 100644 --- a/src/lib/es2015.core.d.ts +++ b/src/lib/es2015.core.d.ts @@ -449,7 +449,7 @@ interface String { /** * Returns a String value that is made from count copies appended together. If count is 0, - * T is the empty String is returned. + * the empty string is returned. * @param count number of copies to append */ repeat(count: number): string; From b50fb3ef3ff120efe37eb3ac094093893f3ceb88 Mon Sep 17 00:00:00 2001 From: csigs Date: Tue, 7 Nov 2017 17:10:19 +0000 Subject: [PATCH 064/138] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 36 ++++++++++++++++++ .../diagnosticMessages.generated.json.lcl | 38 ++++++++++++++++++- .../diagnosticMessages.generated.json.lcl | 18 +++++++++ .../diagnosticMessages.generated.json.lcl | 36 ++++++++++++++++++ .../diagnosticMessages.generated.json.lcl | 36 ++++++++++++++++++ .../diagnosticMessages.generated.json.lcl | 36 ++++++++++++++++++ 6 files changed, 199 insertions(+), 1 deletion(-) diff --git a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl index 3ea6148617a..929b7edf058 100644 --- a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2241,6 +2241,15 @@ + + + + + + + + + @@ -2970,6 +2979,15 @@ + + + + + + + + + @@ -4212,6 +4230,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl index 078b17179a4..8dab90a1ba2 100644 --- a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2250,6 +2250,15 @@ + + + + + + + + + @@ -2979,6 +2988,15 @@ + + + + + + + + + @@ -4221,6 +4239,24 @@ + + + + + + + + + + + + + + + + + + @@ -8320,7 +8356,7 @@ - + diff --git a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl index 6c74cb8ca90..c00e5a2a2e7 100644 --- a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2232,6 +2232,15 @@ + + + + + + + + + @@ -2964,6 +2973,9 @@ + + + @@ -4209,12 +4221,18 @@ + + + + + + diff --git a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl index 34a98237a2a..b2ae023f5a4 100644 --- a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2241,6 +2241,15 @@ + + + + + + + + + @@ -2970,6 +2979,15 @@ + + + + + + + + + @@ -4212,6 +4230,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 3b132575e58..b9d115872b6 100644 --- a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2225,6 +2225,15 @@ + + + + + + + + + @@ -2954,6 +2963,15 @@ + + + + + + + + + @@ -4193,6 +4211,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 34f080a97cc..0eafa4da0b2 100644 --- a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2234,6 +2234,15 @@ + + + + + + + + + @@ -2963,6 +2972,15 @@ + + + + + + + + + @@ -4205,6 +4223,24 @@ + + + + + + + + + + + + + + + + + + From bd2e97597d731635a44866569b1b4f6095b4a946 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 7 Nov 2017 09:22:28 -0800 Subject: [PATCH 065/138] Enable 'no-empty' tslint rule (#19769) * Enable 'no-empty' tslint rule * Fix bug --- Gulpfile.ts | 3 +- src/compiler/core.ts | 7 ++-- src/compiler/performance.ts | 4 +-- src/compiler/sys.ts | 4 +-- src/harness/harness.ts | 5 ++- src/harness/harnessLanguageService.ts | 36 ++++++------------- src/harness/projectsRunner.ts | 5 +-- src/harness/runnerbase.ts | 2 -- src/harness/unittests/extractTestHelpers.ts | 4 +-- src/harness/unittests/hostNewLineSupport.ts | 6 ++-- .../unittests/tsserverProjectSystem.ts | 7 ++-- src/server/session.ts | 3 +- src/server/watchGuard/watchGuard.ts | 3 +- src/services/pathCompletions.ts | 7 ++-- tslint.json | 1 - 15 files changed, 35 insertions(+), 62 deletions(-) diff --git a/Gulpfile.ts b/Gulpfile.ts index 84770f7edbc..aedde5c33d9 100644 --- a/Gulpfile.ts +++ b/Gulpfile.ts @@ -74,7 +74,8 @@ const cmdLineOptions = minimist(process.argv.slice(2), { } }); -function exec(cmd: string, args: string[], complete: () => void = (() => { }), error: (e: any, status: number) => void = (() => { })) { +const noop = () => {}; // tslint:disable-line no-empty +function exec(cmd: string, args: string[], complete: () => void = noop, error: (e: any, status: number) => void = noop) { console.log(`${cmd} ${args.join(" ")}`); // TODO (weswig): Update child_process types to add windowsVerbatimArguments to the type definition const subshellFlag = isWin ? "/c" : "-c"; diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 4fb072b1112..d9e0faf3aed 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1341,7 +1341,7 @@ namespace ts { } /** Does nothing. */ - export function noop(): void { } + export function noop(_?: {} | null | undefined): void { } // tslint:disable-line no-empty /** Do nothing and return false */ export function returnFalse(): false { return false; } @@ -2659,8 +2659,7 @@ namespace ts { } } - function Signature() { - } + function Signature() {} // tslint:disable-line no-empty function Node(this: Node, kind: SyntaxKind, pos: number, end: number) { this.id = 0; @@ -2931,7 +2930,7 @@ namespace ts { return (arg: T) => f(arg) && g(arg); } - export function assertTypeIsNever(_: never): void { } + export function assertTypeIsNever(_: never): void { } // tslint:disable-line no-empty export interface FileAndDirectoryExistence { fileExists: boolean; diff --git a/src/compiler/performance.ts b/src/compiler/performance.ts index 8c24b3b9f1b..225b34de9cf 100644 --- a/src/compiler/performance.ts +++ b/src/compiler/performance.ts @@ -10,9 +10,7 @@ namespace ts { namespace ts.performance { declare const onProfilerEvent: { (markName: string): void; profiler: boolean; }; - const profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true - ? onProfilerEvent - : (_markName: string) => { }; + const profilerEvent: (markName: string) => void = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true ? onProfilerEvent : noop; let enabled = false; let profilerStart = 0; diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 2400266f9c7..529ece36fa6 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -511,7 +511,7 @@ namespace ts { return stat.size; } } - catch (e) { } + catch { /*ignore*/ } return 0; }, exit(exitCode?: number): void { @@ -525,7 +525,7 @@ namespace ts { try { require("source-map-support").install(); } - catch (e) { + catch { // Could not enable source maps. } }, diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 737e444835c..abec41ea4a4 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -555,8 +555,7 @@ namespace Harness { try { fs.unlinkSync(path); } - catch (e) { - } + catch { /*ignore*/ } } export function directoryExists(path: string): boolean { @@ -615,7 +614,7 @@ namespace Harness { namespace Http { function waitForXHR(xhr: XMLHttpRequest) { - while (xhr.readyState !== 4) { } + while (xhr.readyState !== 4) { } // tslint:disable-line no-empty return { status: xhr.status, responseText: xhr.responseText }; } diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index f8f09049d4d..d4b5a9c2a16 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -166,8 +166,7 @@ namespace Harness.LanguageService { throw new Error("No script with name '" + fileName + "'"); } - public openFile(_fileName: string, _content?: string, _scriptKindName?: string): void { - } + public openFile(_fileName: string, _content?: string, _scriptKindName?: string): void { /*overridden*/ } /** * @param line 0 based index @@ -237,9 +236,9 @@ namespace Harness.LanguageService { } - log(_: string): void { } - trace(_: string): void { } - error(_: string): void { } + log = ts.noop; + trace = ts.noop; + error = ts.noop; } export class NativeLanguageServiceAdapter implements LanguageServiceAdapter { @@ -596,13 +595,8 @@ namespace Harness.LanguageService { super(cancellationToken, settings); } - onMessage(): void { - - } - - writeMessage(): void { - - } + onMessage = ts.noop; + writeMessage = ts.noop; setClient(client: ts.server.SessionClient) { this.client = client; @@ -628,13 +622,8 @@ namespace Harness.LanguageService { this.newLine = this.host.getNewLine(); } - onMessage(): void { - - } - - writeMessage(_message: string): void { - } - + onMessage = ts.noop; + writeMessage = ts.noop; // overridden write(message: string): void { this.writeMessage(message); } @@ -648,8 +637,7 @@ namespace Harness.LanguageService { return snapshot && snapshot.getText(0, snapshot.getLength()); } - writeFile(): void { - } + writeFile = ts.noop; resolvePath(path: string): string { return path; @@ -668,8 +656,7 @@ namespace Harness.LanguageService { return ""; } - exit(): void { - } + exit = ts.noop; createDirectory(_directoryName: string): void { return ts.notImplemented(); @@ -697,8 +684,7 @@ namespace Harness.LanguageService { return { close: ts.noop }; } - close(): void { - } + close = ts.noop; info(message: string): void { this.host.log(message); diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index fccbba88ff6..c617cc7a0a3 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -396,7 +396,7 @@ class ProjectRunner extends RunnerBase { }); // Dont allow config files since we are compiling existing source options - return compileProjectFiles(compilerResult.moduleKind, compilerResult.configFileSourceFiles, getInputFiles, getSourceFileText, writeFile, compilerResult.compilerOptions); + return compileProjectFiles(compilerResult.moduleKind, compilerResult.configFileSourceFiles, getInputFiles, getSourceFileText, /*writeFile*/ ts.noop, compilerResult.compilerOptions); function findOutputDtsFile(fileName: string) { return ts.forEach(compilerResult.outputFiles, outputFile => outputFile.emittedFileName === fileName ? outputFile : undefined); @@ -416,9 +416,6 @@ class ProjectRunner extends RunnerBase { } return undefined; } - - function writeFile() { - } } function getErrorsBaseline(compilerResult: CompileProjectFilesResult) { diff --git a/src/harness/runnerbase.ts b/src/harness/runnerbase.ts index 2fef2264b73..14be5e0682a 100644 --- a/src/harness/runnerbase.ts +++ b/src/harness/runnerbase.ts @@ -6,8 +6,6 @@ type CompilerTestKind = "conformance" | "compiler"; type FourslashTestKind = "fourslash" | "fourslash-shims" | "fourslash-shims-pp" | "fourslash-server"; abstract class RunnerBase { - constructor() { } - // contains the tests to run public tests: string[] = []; diff --git a/src/harness/unittests/extractTestHelpers.ts b/src/harness/unittests/extractTestHelpers.ts index b8974694cfe..ae3f663aa51 100644 --- a/src/harness/unittests/extractTestHelpers.ts +++ b/src/harness/unittests/extractTestHelpers.ts @@ -126,7 +126,7 @@ namespace ts { const sourceFile = program.getSourceFile(path); const context: RefactorContext = { - cancellationToken: { throwIfCancellationRequested() { }, isCancellationRequested() { return false; } }, + cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse }, newLineCharacter, program, file: sourceFile, @@ -190,7 +190,7 @@ namespace ts { const program = projectService.inferredProjects[0].getLanguageService().getProgram(); const sourceFile = program.getSourceFile(f.path); const context: RefactorContext = { - cancellationToken: { throwIfCancellationRequested() { }, isCancellationRequested() { return false; } }, + cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse }, newLineCharacter, program, file: sourceFile, diff --git a/src/harness/unittests/hostNewLineSupport.ts b/src/harness/unittests/hostNewLineSupport.ts index 9f6b09dfb72..95a05f101f7 100644 --- a/src/harness/unittests/hostNewLineSupport.ts +++ b/src/harness/unittests/hostNewLineSupport.ts @@ -5,10 +5,10 @@ namespace ts { function snapFor(path: string): IScriptSnapshot { if (path === "lib.d.ts") { return { - dispose() {}, + dispose: noop, getChangeRange() { return undefined; }, getLength() { return 0; }, - getText(_start, _end) { + getText() { return ""; } }; @@ -16,7 +16,7 @@ namespace ts { const result = forEach(files, f => f.unitName === path ? f : undefined); if (result) { return { - dispose() {}, + dispose: noop, getChangeRange() { return undefined; }, getLength() { return result.content.length; }, getText(start, end) { diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index ffb811dddba..432a6e7a5c5 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -85,8 +85,7 @@ namespace ts.projectSystem { assert.equal(this.postExecActions.length, expectedCount, `Expected ${expectedCount} post install actions`); } - onProjectClosed() { - } + onProjectClosed = noop; attach(projectService: server.ProjectService) { this.projectService = projectService; @@ -4717,7 +4716,7 @@ namespace ts.projectSystem { const host = createServerHost([f1, config]); const session = createSession(host, { canUseEvents: true, - eventHandler: () => { }, + eventHandler: noop, cancellationToken }); { @@ -4854,7 +4853,7 @@ namespace ts.projectSystem { const host = createServerHost([f1, config]); const session = createSession(host, { canUseEvents: true, - eventHandler: () => { }, + eventHandler: noop, cancellationToken, throttleWaitMilliseconds: 0 }); diff --git a/src/server/session.ts b/src/server/session.ts index 07fcc49d1b2..6c97c3c8bd4 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1687,8 +1687,7 @@ namespace ts.server { return normalizePath(name); } - exit() { - } + exit() { /*overridden*/ } private notRequired(): HandlerResponse { return { responseRequired: false }; diff --git a/src/server/watchGuard/watchGuard.ts b/src/server/watchGuard/watchGuard.ts index f57369aecb9..8ec248ebb87 100644 --- a/src/server/watchGuard/watchGuard.ts +++ b/src/server/watchGuard/watchGuard.ts @@ -14,6 +14,5 @@ try { const watcher = fs.watch(directoryName, { recursive: true }, () => ({})); watcher.close(); } -catch (_e) { -} +catch { /*ignore*/ } process.exit(0); \ No newline at end of file diff --git a/src/services/pathCompletions.ts b/src/services/pathCompletions.ts index 977b43899c9..a6dfb53da80 100644 --- a/src/services/pathCompletions.ts +++ b/src/services/pathCompletions.ts @@ -320,10 +320,9 @@ namespace ts.Completions.PathCompletions { else if (host.getDirectories) { let typeRoots: ReadonlyArray; try { - // Wrap in try catch because getEffectiveTypeRoots touches the filesystem typeRoots = getEffectiveTypeRoots(options, host); } - catch (e) {} + catch { /* Wrap in try catch because getEffectiveTypeRoots touches the filesystem */ } if (typeRoots) { for (const root of typeRoots) { @@ -484,7 +483,7 @@ namespace ts.Completions.PathCompletions { try { return directoryProbablyExists(path, host); } - catch (e) {} + catch { /*ignore*/ } return undefined; } @@ -492,7 +491,7 @@ namespace ts.Completions.PathCompletions { try { return toApply && toApply.apply(host, args); } - catch (e) {} + catch { /*ignore*/ } return undefined; } } diff --git a/tslint.json b/tslint.json index 914681329ec..f4403d48f19 100644 --- a/tslint.json +++ b/tslint.json @@ -86,7 +86,6 @@ "no-conditional-assignment": false, "no-console": false, "no-debugger": false, - "no-empty": false, "no-empty-interface": false, "no-eval": false, "no-object-literal-type-assertion": false, From b2b54cbf5c41397135a2642510fa4af12af95fd4 Mon Sep 17 00:00:00 2001 From: Aluan Haddad Date: Tue, 7 Nov 2017 12:45:30 -0500 Subject: [PATCH 066/138] Import fix add import require support (#19802) * import fix: suggest import..require where supported if synthetic defaults are unavailable * Add tests for import..require fix when targeting CommonJS, AMD, and UMD modules * fix failing tests --- src/services/codefixes/importFixes.ts | 30 +++++++++++++++---- ...xNewImportAllowSyntheticDefaultImports2.ts | 1 + ...xNewImportAllowSyntheticDefaultImports3.ts | 19 ++++++++++++ ...xNewImportAllowSyntheticDefaultImports4.ts | 19 ++++++++++++ ...xNewImportAllowSyntheticDefaultImports5.ts | 19 ++++++++++++ .../fourslash/importNameCodeFixUMDGlobal0.ts | 3 ++ .../fourslash/importNameCodeFixUMDGlobal1.ts | 3 ++ .../importNameCodeFixUMDGlobalReact0.ts | 2 ++ .../importNameCodeFixUMDGlobalReact1.ts | 2 ++ 9 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports3.ts create mode 100644 tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports4.ts create mode 100644 tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports5.ts diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index a7f0e2e0814..e0e57801cf8 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -180,7 +180,8 @@ namespace ts.codefix { export const enum ImportKind { Named, Default, - Namespace + Namespace, + Equals } export function getCodeActionForImport(moduleSymbol: Symbol, context: ImportCodeFixOptions): ImportCodeAction[] { @@ -252,11 +253,17 @@ namespace ts.codefix { const moduleSpecifierWithoutQuotes = stripQuotes(moduleSpecifier); const quotedModuleSpecifier = createStringLiteralWithQuoteStyle(sourceFile, moduleSpecifierWithoutQuotes); - const importDecl = createImportDeclaration( + const importDecl = kind !== ImportKind.Equals + ? createImportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - createImportClauseOfKind(kind, symbolName), - quotedModuleSpecifier); + createImportClauseOfKind(kind, symbolName), + quotedModuleSpecifier) + : createImportEqualsDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + createIdentifier(symbolName), + createExternalModuleReference(quotedModuleSpecifier)); const changes = ChangeTracker.with(context, changeTracker => { if (lastImportDeclaration) { @@ -267,8 +274,10 @@ namespace ts.codefix { } }); - const actionFormat = kind === ImportKind.Namespace - ? Diagnostics.Import_Asterisk_as_0_from_1 + const actionFormat = kind === ImportKind.Equals + ? Diagnostics.Import_0_require_1 + : kind === ImportKind.Namespace + ? Diagnostics.Import_Asterisk_as_0_from_1 : Diagnostics.Import_0_from_1; // if this file doesn't have any import statements, insert an import statement and then insert a new line @@ -601,6 +610,9 @@ namespace ts.codefix { return namedBindings ? undefined : ChangeTracker.with(context, t => t.replaceNode(sourceFile, importClause, createImportClause(name, createNamespaceImport(createIdentifier(symbolName))))); + case ImportKind.Equals: + return undefined; + default: Debug.assertNever(kind); } @@ -659,6 +671,12 @@ namespace ts.codefix { if (allowSyntheticDefaultImports) { return getCodeActionForImport(symbol, { ...context, symbolName, kind: ImportKind.Default }); } + const moduleKind = getEmitModuleKind(compilerOptions); + + // When a synthetic `default` is unavailable, use `import..require` if the module kind supports it. + if (moduleKind === ModuleKind.AMD || moduleKind === ModuleKind.CommonJS || moduleKind === ModuleKind.UMD) { + return getCodeActionForImport(symbol, { ...context, symbolName, kind: ImportKind.Equals }); + } // Fall back to the `import * as ns` style import. return getCodeActionForImport(symbol, { ...context, symbolName, kind: ImportKind.Namespace }); diff --git a/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports2.ts b/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports2.ts index 3421d603297..f6ba985715e 100644 --- a/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports2.ts +++ b/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports2.ts @@ -1,5 +1,6 @@ /// // @AllowSyntheticDefaultImports: false +// @Module: system // @Filename: a/f1.ts //// [|export var x = 0; diff --git a/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports3.ts b/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports3.ts new file mode 100644 index 00000000000..bc0ba6d8163 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports3.ts @@ -0,0 +1,19 @@ +/// +// @AllowSyntheticDefaultImports: false +// @Module: commonjs + +// @Filename: a/f1.ts +//// [|export var x = 0; +//// bar/*0*/();|] + +// @Filename: a/foo.d.ts +//// declare function bar(): number; +//// export = bar; +//// export as namespace bar; + +verify.importFixAtPosition([ +`import bar = require("./foo"); + +export var x = 0; +bar();` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports4.ts b/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports4.ts new file mode 100644 index 00000000000..c8ce87db71a --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports4.ts @@ -0,0 +1,19 @@ +/// +// @AllowSyntheticDefaultImports: false +// @Module: amd + +// @Filename: a/f1.ts +//// [|export var x = 0; +//// bar/*0*/();|] + +// @Filename: a/foo.d.ts +//// declare function bar(): number; +//// export = bar; +//// export as namespace bar; + +verify.importFixAtPosition([ +`import bar = require("./foo"); + +export var x = 0; +bar();` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports5.ts b/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports5.ts new file mode 100644 index 00000000000..7830faaacc8 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFixNewImportAllowSyntheticDefaultImports5.ts @@ -0,0 +1,19 @@ +/// +// @AllowSyntheticDefaultImports: false +// @Module: umd + +// @Filename: a/f1.ts +//// [|export var x = 0; +//// bar/*0*/();|] + +// @Filename: a/foo.d.ts +//// declare function bar(): number; +//// export = bar; +//// export as namespace bar; + +verify.importFixAtPosition([ +`import bar = require("./foo"); + +export var x = 0; +bar();` +]); \ No newline at end of file diff --git a/tests/cases/fourslash/importNameCodeFixUMDGlobal0.ts b/tests/cases/fourslash/importNameCodeFixUMDGlobal0.ts index 3c780dc0af6..3208a41bba1 100644 --- a/tests/cases/fourslash/importNameCodeFixUMDGlobal0.ts +++ b/tests/cases/fourslash/importNameCodeFixUMDGlobal0.ts @@ -1,5 +1,8 @@ /// +// @AllowSyntheticDefaultImports: false +// @Module: es2015 + // @Filename: a/f1.ts //// [|export function test() { }; //// bar1/*0*/.bar;|] diff --git a/tests/cases/fourslash/importNameCodeFixUMDGlobal1.ts b/tests/cases/fourslash/importNameCodeFixUMDGlobal1.ts index 96671ad6f91..1beebb0477c 100644 --- a/tests/cases/fourslash/importNameCodeFixUMDGlobal1.ts +++ b/tests/cases/fourslash/importNameCodeFixUMDGlobal1.ts @@ -1,5 +1,8 @@ /// +// @AllowSyntheticDefaultImports: false +// @Module: esnext + // @Filename: a/f1.ts //// [|import { bar } from "./foo"; //// diff --git a/tests/cases/fourslash/importNameCodeFixUMDGlobalReact0.ts b/tests/cases/fourslash/importNameCodeFixUMDGlobalReact0.ts index 260c34d10a6..5b6df7a5173 100644 --- a/tests/cases/fourslash/importNameCodeFixUMDGlobalReact0.ts +++ b/tests/cases/fourslash/importNameCodeFixUMDGlobalReact0.ts @@ -1,6 +1,8 @@ /// // @jsx: react +// @allowSyntheticDefaultImports: false +// @module: es2015 // @Filename: /node_modules/@types/react/index.d.ts ////export = React; diff --git a/tests/cases/fourslash/importNameCodeFixUMDGlobalReact1.ts b/tests/cases/fourslash/importNameCodeFixUMDGlobalReact1.ts index ccd69c50199..669db55342b 100644 --- a/tests/cases/fourslash/importNameCodeFixUMDGlobalReact1.ts +++ b/tests/cases/fourslash/importNameCodeFixUMDGlobalReact1.ts @@ -1,6 +1,8 @@ /// // @jsx: react +// @allowSyntheticDefaultImports: false +// @module: es2015 // @Filename: /node_modules/@types/react/index.d.ts ////export = React; From 2f2a82b91dd1286723308b9af0505560491af700 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 7 Nov 2017 09:45:58 -0800 Subject: [PATCH 067/138] Move "space-before-function-paren" lint rule to list of rules waiting on a formatter (#19807) --- tslint.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tslint.json b/tslint.json index f4403d48f19..718c437b372 100644 --- a/tslint.json +++ b/tslint.json @@ -96,7 +96,6 @@ "ordered-imports": false, "prefer-conditional-expression": false, "radix": false, - "space-before-function-paren": false, "trailing-comma": false, // These should be done automatically by a formatter. https://github.com/Microsoft/TypeScript/issues/18340 @@ -104,6 +103,7 @@ "eofline": false, "max-line-length": false, "no-consecutive-blank-lines": false, + "space-before-function-paren": false, // Not doing "ban-comma-operator": false, From 57f247eff490d804ff047e7d8b88b64b294ea13f Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 7 Nov 2017 09:46:40 -0800 Subject: [PATCH 068/138] Add hyphen in completionEntryDetails-full (#19808) --- src/server/protocol.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 93d5c69d361..f44efa0db21 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -16,7 +16,7 @@ namespace ts.server.protocol { CompletionsFull = "completions-full", CompletionDetails = "completionEntryDetails", /* @internal */ - CompletionDetailsFull = "completionEntryDetailsFull", + CompletionDetailsFull = "completionEntryDetails-full", CompileOnSaveAffectedFileList = "compileOnSaveAffectedFileList", CompileOnSaveEmitFile = "compileOnSaveEmitFile", Configure = "configure", 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 069/138] 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 d1fa006a1e1761e39430f9363768356a5b8f360a Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Tue, 7 Nov 2017 10:10:34 -0800 Subject: [PATCH 070/138] Use CharacterCode enum --- src/services/utilities.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 643aae2bae1..4f95682d949 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1351,11 +1351,11 @@ namespace ts { return position; function AdvancePastLineBreak() { - if (text.charCodeAt(position) === 0xD) { + if (text.charCodeAt(position) === CharacterCodes.carriageReturn) { position++; } - if (text.charCodeAt(position) === 0xA) { + if (text.charCodeAt(position) === CharacterCodes.lineFeed) { position++; } } From 3e339d88a1b192e86a448ed26643e1351f80afb9 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Tue, 7 Nov 2017 10:33:35 -0800 Subject: [PATCH 071/138] Handle other linebreak characters and add boundary checks --- src/services/utilities.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 4f95682d949..179e5edde52 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1330,6 +1330,7 @@ namespace ts { export function getSourceFileImportLocation(node: SourceFile) { // For a source file, it is possible there are detached comments we should not skip const text = node.text; + const textLength = text.length; let ranges = getLeadingCommentRanges(text, 0); if (!ranges) return 0; let position = 0; @@ -1351,12 +1352,15 @@ namespace ts { return position; function AdvancePastLineBreak() { - if (text.charCodeAt(position) === CharacterCodes.carriageReturn) { - position++; - } + if (position < textLength) { + const charCode = text.charCodeAt(position); + if (isLineBreak(charCode)) { + position++; - if (text.charCodeAt(position) === CharacterCodes.lineFeed) { - position++; + if (position < textLength && charCode === CharacterCodes.carriageReturn && text.charCodeAt(position) === CharacterCodes.lineFeed) { + position++; + } + } } } } 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 072/138] 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 2715f890b4993a94ca75b7ba1453aa5982dc1803 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Tue, 7 Nov 2017 10:47:36 -0800 Subject: [PATCH 073/138] PascalCase -> camelCase --- src/services/utilities.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 179e5edde52..f59f6e56e91 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1337,21 +1337,21 @@ namespace ts { // However we should still skip a pinned comment at the top if (ranges.length && ranges[0].kind === SyntaxKind.MultiLineCommentTrivia && isPinnedComment(text, ranges[0])) { position = ranges[0].end; - AdvancePastLineBreak(); + advancePastLineBreak(); ranges = ranges.slice(1); } // As well as any triple slash references for (const range of ranges) { if (range.kind === SyntaxKind.SingleLineCommentTrivia && isRecognizedTripleSlashComment(node.text, range.pos, range.end)) { position = range.end; - AdvancePastLineBreak(); + advancePastLineBreak(); continue; } break; } return position; - function AdvancePastLineBreak() { + function advancePastLineBreak() { if (position < textLength) { const charCode = text.charCodeAt(position); if (isLineBreak(charCode)) { 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 074/138] 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 075/138] 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 c6f343e266f2ffd3c69711dbf3ea02fdde2d3485 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 7 Nov 2017 14:47:08 -0800 Subject: [PATCH 076/138] Improve asserts in getSuggestionForNonexistentSymbol --- src/compiler/checker.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4c88bce12f2..2990f0cc3f8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15291,8 +15291,9 @@ namespace ts { } function getSuggestionForNonexistentSymbol(location: Node, outerName: __String, meaning: SymbolFlags): string { + Debug.assert(outerName !== undefined, "outername should always be defined"); const result = resolveNameHelper(location, outerName, meaning, /*nameNotFoundMessage*/ undefined, outerName, /*isUse*/ false, (symbols, name, meaning) => { - Debug.assert(name !== undefined, "name should always be defined, and equal to " + outerName); + Debug.assertEqual(outerName, name, "name should equal outerName"); const symbol = getSymbol(symbols, name, meaning); // Sometimes the symbol is found when location is a return type of a function: `typeof x` and `x` is declared in the body of the function // So the table *contains* `x` but `x` isn't actually in scope. From 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 077/138] 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 078/138] 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 079/138] 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 080/138] 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 081/138] 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 082/138] 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 083/138] 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 084/138] 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 085/138] 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 086/138] 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 087/138] 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 088/138] 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 089/138] 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 090/138] 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 091/138] 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 092/138] 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 093/138] 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 094/138] 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 095/138] 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 096/138] 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 097/138] 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 098/138] 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 099/138] 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 100/138] 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 101/138] 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 102/138] 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 103/138] 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 104/138] 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 105/138] 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 106/138] 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 107/138] 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 108/138] 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 109/138] 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 110/138] 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 111/138] 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 112/138] 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 113/138] 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 114/138] 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 115/138] 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 116/138] 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 117/138] 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 118/138] 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 119/138] 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 120/138] 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 121/138] 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 122/138] 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 123/138] 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 d66e94d09e6e66574b06a8fe01d1db63eb7b6a74 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 10 Nov 2017 13:50:18 -0800 Subject: [PATCH 124/138] ExternalCompileRunner works with submodules If there is a test.json in the directory, it expects to find a submodule in the directory. The submodule should have the same name as the directory itself. test.json contains a list of global types that need to be available, or the empty list if none. --- .gitmodules | 6 +++++ src/harness/externalCompileRunner.ts | 26 ++++++++++++++++--- .../TypeScript-Node-Starter | 1 + .../TypeScript-React-Starter | 1 + 4 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 .gitmodules create mode 160000 tests/cases/user/TypeScript-Node-Starter/TypeScript-Node-Starter create mode 160000 tests/cases/user/TypeScript-React-Starter/TypeScript-React-Starter diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000000..1a1c6e193fd --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "tests/cases/user/TypeScript-React-Starter/TypeScript-React-Starter"] + path = tests/cases/user/TypeScript-React-Starter/TypeScript-React-Starter + url = https://github.com/Microsoft/TypeScript-React-Starter +[submodule "tests/cases/user/TypeScript-Node-Starter/TypeScript-Node-Starter"] + path = tests/cases/user/TypeScript-Node-Starter/TypeScript-Node-Starter + url = https://github.com/Microsoft/TypeScript-Node-Starter.git diff --git a/src/harness/externalCompileRunner.ts b/src/harness/externalCompileRunner.ts index 33803752f94..0f9386ddb0f 100644 --- a/src/harness/externalCompileRunner.ts +++ b/src/harness/externalCompileRunner.ts @@ -9,6 +9,10 @@ interface ExecResult { status: number; } +interface UserConfig { + types: string[]; +} + abstract class ExternalCompileRunnerBase extends RunnerBase { abstract testDir: string; abstract report(result: ExecResult, cwd: string): string; @@ -33,18 +37,34 @@ abstract class ExternalCompileRunnerBase extends RunnerBase { const cp = require("child_process"); it("should build successfully", () => { - const cwd = path.join(__dirname, "../../", this.testDir, directoryName); + let cwd = path.join(__dirname, "../../", this.testDir, directoryName); const timeout = 600000; // 600s = 10 minutes + const stdio = isWorker ? "pipe" : "inherit"; + let types: string[]; + if (fs.existsSync(path.join(cwd, "test.json"))) { + const update = cp.spawnSync('git', ["submodule", "update", "--remote"], { cwd, timeout, shell: true, stdio }) + if (update.status !== 0) throw new Error(`git submodule update for ${directoryName} failed!`); + + const config = JSON.parse(fs.readFileSync(path.join(cwd, "test.json"), { encoding: "utf8" })) as UserConfig; + ts.Debug.assert(!!config.types, "Git is the only reason for using test.json right now"); + types = config.types; + + cwd = path.join(cwd, directoryName); + } 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!`); } + const args = [path.join(__dirname, "tsc.js")]; + if (types) { + args.push("--types", types.join(",")); + } + args.push("--noEmit"); Harness.Baseline.runBaseline(`${this.kind()}/${directoryName}.log`, () => { - return this.report(cp.spawnSync(`node`, [path.join(__dirname, "tsc.js")], { cwd, timeout, shell: true }), cwd); + return this.report(cp.spawnSync(`node`, args, { cwd, timeout, shell: true }), cwd); }); }); }); diff --git a/tests/cases/user/TypeScript-Node-Starter/TypeScript-Node-Starter b/tests/cases/user/TypeScript-Node-Starter/TypeScript-Node-Starter new file mode 160000 index 00000000000..ed149eb0c78 --- /dev/null +++ b/tests/cases/user/TypeScript-Node-Starter/TypeScript-Node-Starter @@ -0,0 +1 @@ +Subproject commit ed149eb0c787b1195a95b44105822c64bb6eb636 diff --git a/tests/cases/user/TypeScript-React-Starter/TypeScript-React-Starter b/tests/cases/user/TypeScript-React-Starter/TypeScript-React-Starter new file mode 160000 index 00000000000..96fb6237a9d --- /dev/null +++ b/tests/cases/user/TypeScript-React-Starter/TypeScript-React-Starter @@ -0,0 +1 @@ +Subproject commit 96fb6237a9dda8d17059eea7fa7c22dd7db82c97 From c82c6f21cb0305ec1dc18a6118895444b05489d1 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 10 Nov 2017 14:03:41 -0800 Subject: [PATCH 125/138] 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 d4c001d47c90d14a1ca020d2877babf58fffeb90 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 10 Nov 2017 14:20:55 -0800 Subject: [PATCH 126/138] Add test w/submodules for our starter kits --- .gitmodules | 9 +++++++++ tests/cases/user/TypeScript-Node-Starter/test.json | 3 +++ .../TypeScript-React-Native-Starter | 1 + .../cases/user/TypeScript-React-Native-Starter/test.json | 3 +++ tests/cases/user/TypeScript-React-Starter/test.json | 3 +++ .../user/TypeScript-Vue-Starter/TypeScript-Vue-Starter | 1 + tests/cases/user/TypeScript-Vue-Starter/test.json | 3 +++ .../TypeScript-WeChat-Starter/TypeScript-WeChat-Starter | 1 + tests/cases/user/TypeScript-WeChat-Starter/test.json | 3 +++ 9 files changed, 27 insertions(+) create mode 100644 tests/cases/user/TypeScript-Node-Starter/test.json create mode 160000 tests/cases/user/TypeScript-React-Native-Starter/TypeScript-React-Native-Starter create mode 100644 tests/cases/user/TypeScript-React-Native-Starter/test.json create mode 100644 tests/cases/user/TypeScript-React-Starter/test.json create mode 160000 tests/cases/user/TypeScript-Vue-Starter/TypeScript-Vue-Starter create mode 100644 tests/cases/user/TypeScript-Vue-Starter/test.json create mode 160000 tests/cases/user/TypeScript-WeChat-Starter/TypeScript-WeChat-Starter create mode 100644 tests/cases/user/TypeScript-WeChat-Starter/test.json diff --git a/.gitmodules b/.gitmodules index 1a1c6e193fd..f83d0f77c9e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,12 @@ [submodule "tests/cases/user/TypeScript-Node-Starter/TypeScript-Node-Starter"] path = tests/cases/user/TypeScript-Node-Starter/TypeScript-Node-Starter url = https://github.com/Microsoft/TypeScript-Node-Starter.git +[submodule "tests/cases/user/TypeScript-React-Native-Starter/TypeScript-React-Native-Starter"] + path = tests/cases/user/TypeScript-React-Native-Starter/TypeScript-React-Native-Starter + url = https://github.com/Microsoft/TypeScript-React-Native-Starter.git +[submodule "tests/cases/user/TypeScript-Vue-Starter/TypeScript-Vue-Starter"] + path = tests/cases/user/TypeScript-Vue-Starter/TypeScript-Vue-Starter + url = https://github.com/Microsoft/TypeScript-Vue-Starter.git +[submodule "tests/cases/user/TypeScript-WeChat-Starter/TypeScript-WeChat-Starter"] + path = tests/cases/user/TypeScript-WeChat-Starter/TypeScript-WeChat-Starter + url = https://github.com/Microsoft/TypeScript-WeChat-Starter.git diff --git a/tests/cases/user/TypeScript-Node-Starter/test.json b/tests/cases/user/TypeScript-Node-Starter/test.json new file mode 100644 index 00000000000..11d2aa87c59 --- /dev/null +++ b/tests/cases/user/TypeScript-Node-Starter/test.json @@ -0,0 +1,3 @@ +{ + "types": ["jquery"] +} diff --git a/tests/cases/user/TypeScript-React-Native-Starter/TypeScript-React-Native-Starter b/tests/cases/user/TypeScript-React-Native-Starter/TypeScript-React-Native-Starter new file mode 160000 index 00000000000..2c62f5a4ea5 --- /dev/null +++ b/tests/cases/user/TypeScript-React-Native-Starter/TypeScript-React-Native-Starter @@ -0,0 +1 @@ +Subproject commit 2c62f5a4ea51978e3715b475e17962cdeca75e38 diff --git a/tests/cases/user/TypeScript-React-Native-Starter/test.json b/tests/cases/user/TypeScript-React-Native-Starter/test.json new file mode 100644 index 00000000000..8b177c575aa --- /dev/null +++ b/tests/cases/user/TypeScript-React-Native-Starter/test.json @@ -0,0 +1,3 @@ +{ + "types": ["jest"] +} diff --git a/tests/cases/user/TypeScript-React-Starter/test.json b/tests/cases/user/TypeScript-React-Starter/test.json new file mode 100644 index 00000000000..8b177c575aa --- /dev/null +++ b/tests/cases/user/TypeScript-React-Starter/test.json @@ -0,0 +1,3 @@ +{ + "types": ["jest"] +} diff --git a/tests/cases/user/TypeScript-Vue-Starter/TypeScript-Vue-Starter b/tests/cases/user/TypeScript-Vue-Starter/TypeScript-Vue-Starter new file mode 160000 index 00000000000..713c6986f04 --- /dev/null +++ b/tests/cases/user/TypeScript-Vue-Starter/TypeScript-Vue-Starter @@ -0,0 +1 @@ +Subproject commit 713c6986f043f2c31976b8bc2c03aa0a2b05590b diff --git a/tests/cases/user/TypeScript-Vue-Starter/test.json b/tests/cases/user/TypeScript-Vue-Starter/test.json new file mode 100644 index 00000000000..e0d4d26bdca --- /dev/null +++ b/tests/cases/user/TypeScript-Vue-Starter/test.json @@ -0,0 +1,3 @@ +{ + "types": [] +} diff --git a/tests/cases/user/TypeScript-WeChat-Starter/TypeScript-WeChat-Starter b/tests/cases/user/TypeScript-WeChat-Starter/TypeScript-WeChat-Starter new file mode 160000 index 00000000000..5fca1032eda --- /dev/null +++ b/tests/cases/user/TypeScript-WeChat-Starter/TypeScript-WeChat-Starter @@ -0,0 +1 @@ +Subproject commit 5fca1032edaab5414ec1c167f42d3dc59220d9aa diff --git a/tests/cases/user/TypeScript-WeChat-Starter/test.json b/tests/cases/user/TypeScript-WeChat-Starter/test.json new file mode 100644 index 00000000000..e0d4d26bdca --- /dev/null +++ b/tests/cases/user/TypeScript-WeChat-Starter/test.json @@ -0,0 +1,3 @@ +{ + "types": [] +} From 0d63589fb2da23c0a243a8fd47cb0c96df6deac7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 10 Nov 2017 14:21:53 -0800 Subject: [PATCH 127/138] Fix quote lint --- 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 0f9386ddb0f..75ccecb047d 100644 --- a/src/harness/externalCompileRunner.ts +++ b/src/harness/externalCompileRunner.ts @@ -42,7 +42,7 @@ abstract class ExternalCompileRunnerBase extends RunnerBase { const stdio = isWorker ? "pipe" : "inherit"; let types: string[]; if (fs.existsSync(path.join(cwd, "test.json"))) { - const update = cp.spawnSync('git', ["submodule", "update", "--remote"], { cwd, timeout, shell: true, stdio }) + const update = cp.spawnSync("git", ["submodule", "update", "--remote"], { cwd, timeout, shell: true, stdio }); if (update.status !== 0) throw new Error(`git submodule update for ${directoryName} failed!`); const config = JSON.parse(fs.readFileSync(path.join(cwd, "test.json"), { encoding: "utf8" })) as UserConfig; From ba232b2164e7d0789bdc668e6b750696f8f7a8e2 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 10 Nov 2017 14:36:49 -0800 Subject: [PATCH 128/138] Update baselines --- tests/baselines/reference/user/electron.log | 2 +- tests/baselines/reference/user/leveldown.log | 2 +- tests/baselines/reference/user/rxjs.log | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/baselines/reference/user/electron.log b/tests/baselines/reference/user/electron.log index e5eef689d49..7ba43481c3b 100644 --- a/tests/baselines/reference/user/electron.log +++ b/tests/baselines/reference/user/electron.log @@ -1,4 +1,4 @@ -Exit Code: 2 +Exit Code: 1 Standard output: node_modules/electron/electron.d.ts(5390,13): error TS2430: Interface 'WebviewTag' incorrectly extends interface 'HTMLElement'. Types of property 'addEventListener' are incompatible. diff --git a/tests/baselines/reference/user/leveldown.log b/tests/baselines/reference/user/leveldown.log index c37a983f73d..011071ebc52 100644 --- a/tests/baselines/reference/user/leveldown.log +++ b/tests/baselines/reference/user/leveldown.log @@ -1,4 +1,4 @@ -Exit Code: 2 +Exit Code: 1 Standard output: node_modules/abstract-leveldown/index.d.ts(2,3): error TS7010: 'open', which lacks return-type annotation, implicitly has an 'any' return type. node_modules/abstract-leveldown/index.d.ts(3,3): error TS7010: 'open', which lacks return-type annotation, implicitly has an 'any' return type. diff --git a/tests/baselines/reference/user/rxjs.log b/tests/baselines/reference/user/rxjs.log index 73058119ce9..c17014c5c13 100644 --- a/tests/baselines/reference/user/rxjs.log +++ b/tests/baselines/reference/user/rxjs.log @@ -1,4 +1,4 @@ -Exit Code: 2 +Exit Code: 1 Standard output: node_modules/rxjs/scheduler/VirtualTimeScheduler.d.ts(22,22): error TS2415: Class 'VirtualAction' incorrectly extends base class 'AsyncAction'. Types of property 'work' are incompatible. From 19b26c564cf18a3a76d00204d8fa92979f20e1f9 Mon Sep 17 00:00:00 2001 From: csigs Date: Fri, 10 Nov 2017 23:10:42 +0000 Subject: [PATCH 129/138] 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 4d0139084596a18a2ba0af583bd2cc3bad164aab Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 10 Nov 2017 15:55:29 -0800 Subject: [PATCH 130/138] Improve assert message --- 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 75ccecb047d..2a44badd813 100644 --- a/src/harness/externalCompileRunner.ts +++ b/src/harness/externalCompileRunner.ts @@ -46,7 +46,7 @@ abstract class ExternalCompileRunnerBase extends RunnerBase { if (update.status !== 0) throw new Error(`git submodule update for ${directoryName} failed!`); const config = JSON.parse(fs.readFileSync(path.join(cwd, "test.json"), { encoding: "utf8" })) as UserConfig; - ts.Debug.assert(!!config.types, "Git is the only reason for using test.json right now"); + ts.Debug.assert(!!config.types, "Bad format from test.json: Types field must be present."); types = config.types; cwd = path.join(cwd, directoryName); From 59fca7fc30bfbcdde8d5b3e544bdf09da5fa9e9a Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 10 Nov 2017 16:26:16 -0800 Subject: [PATCH 131/138] 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 132/138] 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 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - From 74fe5c5b74983a2b152b4fe3e23b2e450431128b Mon Sep 17 00:00:00 2001 From: csigs Date: Mon, 13 Nov 2017 17:10:16 +0000 Subject: [PATCH 133/138] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 160 +++++++++--------- .../diagnosticMessages.generated.json.lcl | 160 +++++++++--------- 2 files changed, 154 insertions(+), 166 deletions(-) diff --git a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl index 929b7edf058..a55da48f2c2 100644 --- a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/cht/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/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl index 4865cf6c508..58a00519e04 100644 --- a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/esn/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 e7df83263df9433d2b27a2b86e9d198fca68bd92 Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 13 Nov 2017 09:18:36 -0800 Subject: [PATCH 134/138] Break out of speculative parsing on bad parameter initializer (#19158) * Break out of speculative parsing on bad parameter initializer * Remove uses of 'finally' * give up -> stop * Do without exceptions * Remove `resetAfterSpeculation` * Use Fail and FailList objects * Remove `inSpeculation` parameter to parseDelimitedList * Don't use `createNodeArray`, it's not always in scope * Move Fail and FailList inside initializeState * More code review * More code review --- src/compiler/parser.ts | 180 +++++++++++++----- .../parserArrowFunctionExpression7.js | 16 ++ .../parserArrowFunctionExpression7.symbols | 10 + .../parserArrowFunctionExpression7.types | 13 ++ .../parserArrowFunctionExpression7.ts | 7 + 5 files changed, 176 insertions(+), 50 deletions(-) create mode 100644 tests/baselines/reference/parserArrowFunctionExpression7.js create mode 100644 tests/baselines/reference/parserArrowFunctionExpression7.symbols create mode 100644 tests/baselines/reference/parserArrowFunctionExpression7.types create mode 100644 tests/cases/conformance/parser/ecmascript5/ArrowFunctionExpressions/parserArrowFunctionExpression7.ts diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 79b5eb30c49..64cd8219a01 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -531,6 +531,18 @@ namespace ts { let TokenConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; let IdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; + interface Fail extends Node { kind: SyntaxKind.Unknown; } + interface FailList extends NodeArray { pos: -1; } + let Fail: Fail; + let FailList: FailList; + function isFail(x: Node | undefined): x is Fail { + Debug.assert(Fail !== undefined); + return x === Fail; + } + function isFailList(x: NodeArray | undefined): x is FailList { + Debug.assert(Fail !== undefined); + return x === FailList; + } // tslint:enable variable-name let sourceFile: SourceFile; @@ -681,6 +693,9 @@ namespace ts { IdentifierConstructor = objectAllocator.getIdentifierConstructor(); SourceFileConstructor = objectAllocator.getSourceFileConstructor(); + Fail = createNode(SyntaxKind.Unknown) as Fail; + FailList = createNodeArray([], -1) as FailList; + sourceText = _sourceText; syntaxCursor = _syntaxCursor; @@ -736,7 +751,7 @@ namespace ts { processReferenceComments(sourceFile); sourceFile.statements = parseList(ParsingContext.SourceElements, parseStatement); - Debug.assert(token() === SyntaxKind.EndOfFileToken); + Debug.assertEqual(token(), SyntaxKind.EndOfFileToken); sourceFile.endOfFileToken = addJSDocComment(parseTokenNode() as EndOfFileToken); setExternalModuleIndicator(sourceFile); @@ -1003,7 +1018,7 @@ namespace ts { return currentToken = scanner.scanJsxAttributeValue(); } - function speculationHelper(callback: () => T, isLookAhead: boolean): T { + function speculationHelper(callback: () => T, isLookAhead: boolean): T | undefined { // Keep track of the state we'll need to rollback to if lookahead fails (or if the // caller asked us to always reset our state). const saveToken = currentToken; @@ -1015,6 +1030,7 @@ namespace ts { // descent nature of our parser. However, we still store this here just so we can // assert that invariant holds. const saveContextFlags = contextFlags; + const saveParsingContext = parsingContext; // If we're only looking ahead, then tell the scanner to only lookahead as well. // Otherwise, if we're actually speculatively parsing, then tell the scanner to do the @@ -1023,7 +1039,8 @@ namespace ts { ? scanner.lookAhead(callback) : scanner.tryScan(callback); - Debug.assert(saveContextFlags === contextFlags); + Debug.assertEqual(saveContextFlags, contextFlags); + Debug.assertEqual(saveParsingContext, parsingContext); // If our callback returned something 'falsy' or we're just looking ahead, // then unconditionally restore us to where we were. @@ -1577,7 +1594,7 @@ namespace ts { return createNodeArray(list, listPos); } - function parseListElement(parsingContext: ParsingContext, parseElement: () => T): T { + function parseListElement(parsingContext: ParsingContext, parseElement: () => T): T { const node = currentNode(parsingContext); if (node) { return consumeNode(node); @@ -1901,17 +1918,24 @@ namespace ts { } // Parses a comma-delimited list of elements - function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray { + function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray; + function parseDelimitedList(kind: ParsingContext, parseElement: () => T | Fail, considerSemicolonAsDelimiter?: boolean): NodeArray | FailList; + function parseDelimitedList(kind: ParsingContext, parseElement: () => T | Fail, considerSemicolonAsDelimiter?: boolean): NodeArray | FailList { const saveParsingContext = parsingContext; parsingContext |= 1 << kind; - const list = []; + const list: T[] = []; const listPos = getNodePos(); let commaStart = -1; // Meaning the previous token was not a comma while (true) { if (isListElement(kind, /*inErrorRecovery*/ false)) { const startPos = scanner.getStartPos(); - list.push(parseListElement(kind, parseElement)); + const elem = parseListElement(kind, parseElement); + if (isFail(elem)) { + parsingContext = saveParsingContext; + return FailList; + } + list.push(elem); commaStart = scanner.getTokenPos(); if (parseOptional(SyntaxKind.CommaToken)) { @@ -2271,7 +2295,13 @@ namespace ts { isStartOfType(/*inStartOfParameter*/ true); } - function parseParameter(requireEqualsToken?: boolean): ParameterDeclaration { + function tryParseParameter(): ParameterDeclaration | Fail { + return parseParameterWorker(/*inSpeculation*/ true); + } + function parseParameter(): ParameterDeclaration { + return parseParameterWorker(/*inSpeculation*/ false) as ParameterDeclaration; + } + function parseParameterWorker(inSpeculation: boolean): ParameterDeclaration | Fail { const node = createNode(SyntaxKind.Parameter); if (token() === SyntaxKind.ThisKeyword) { node.name = createIdentifier(/*isIdentifier*/ true); @@ -2285,7 +2315,11 @@ namespace ts { // FormalParameter [Yield,Await]: // BindingElement[?Yield,?Await] - node.name = parseIdentifierOrPattern(); + const name = parseIdentifierOrPattern(inSpeculation); + if (isFail(name)) { + return Fail; + } + node.name = name; if (getFullWidth(node.name) === 0 && !hasModifiers(node) && isModifierKind(token())) { // in cases like // 'use strict' @@ -2300,20 +2334,27 @@ namespace ts { node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken); node.type = parseParameterType(); - node.initializer = parseInitializer(/*inParameter*/ true, requireEqualsToken); + const initializer = parseInitializer(/*inParameter*/ true, inSpeculation); + if (isFail(initializer)) { + return Fail; + } + node.initializer = initializer; return addJSDocComment(finishNode(node)); } - function fillSignature( - returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, - flags: SignatureFlags, - signature: SignatureDeclaration): void { + /** @return 'true' on success. */ + function fillSignature(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, flags: SignatureFlags, signature: SignatureDeclaration, inSpeculation?: boolean): boolean { if (!(flags & SignatureFlags.JSDoc)) { signature.typeParameters = parseTypeParameters(); } - signature.parameters = parseParameterList(flags); + const parameters = parseParameterList(flags, inSpeculation); + if (isFailList(parameters)) { + return false; + } + signature.parameters = parameters; signature.type = parseReturnType(returnToken, !!(flags & SignatureFlags.Type)); + return true; } function parseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean): TypeNode | undefined { @@ -2336,7 +2377,7 @@ namespace ts { return false; } - function parseParameterList(flags: SignatureFlags) { + function parseParameterList(flags: SignatureFlags, inSpeculation: boolean): NodeArray | FailList { // FormalParameters [Yield,Await]: (modified) // [empty] // FormalParameterList[?Yield,Await] @@ -2357,9 +2398,9 @@ namespace ts { setYieldContext(!!(flags & SignatureFlags.Yield)); setAwaitContext(!!(flags & SignatureFlags.Await)); - const result = parseDelimitedList(ParsingContext.Parameters, - flags & SignatureFlags.JSDoc ? parseJSDocParameter : () => parseParameter(!!(flags & SignatureFlags.RequireCompleteParameterList))); - + const result = parseDelimitedList( + ParsingContext.Parameters, + flags & SignatureFlags.JSDoc ? parseJSDocParameter : inSpeculation ? tryParseParameter : parseParameter); setYieldContext(savedYieldContext); setAwaitContext(savedAwaitContext); @@ -3032,14 +3073,16 @@ namespace ts { while ((operatorToken = parseOptionalToken(SyntaxKind.CommaToken))) { expr = makeBinaryExpression(expr, operatorToken, parseAssignmentExpressionOrHigher()); } - if (saveDecoratorContext) { setDecoratorContext(/*val*/ true); } + return expr; } - function parseInitializer(inParameter: boolean, requireEqualsToken?: boolean): Expression { + function parseInitializer(inParameter: boolean): Expression | undefined; + function parseInitializer(inParameter: boolean, inSpeculation?: boolean): Expression | Fail | undefined; + function parseInitializer(inParameter: boolean, inSpeculation?: boolean): Expression | Fail | undefined { if (token() !== SyntaxKind.EqualsToken) { // It's not uncommon during typing for the user to miss writing the '=' token. Check if // there is no newline after the last token and if we're on an expression. If so, parse @@ -3054,12 +3097,8 @@ namespace ts { // do not try to parse initializer return undefined; } - if (inParameter && requireEqualsToken) { - // = is required when speculatively parsing arrow function parameters, - // so return a fake initializer as a signal that the equals token was missing - const result = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics._0_expected, "=") as Identifier; - result.escapedText = "= not found" as __String; - return result; + if (inSpeculation) { + return Fail; } } @@ -3225,7 +3264,7 @@ namespace ts { // it out, but don't allow any ambiguity, and return 'undefined' if this could be an // expression instead. const arrowFunction = triState === Tristate.True - ? parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ true) + ? parseParenthesizedArrowFunctionExpressionHead(/*inSpeculation*/ false) : tryParse(parsePossibleParenthesizedArrowFunctionExpressionHead); if (!arrowFunction) { @@ -3373,7 +3412,7 @@ namespace ts { } function parsePossibleParenthesizedArrowFunctionExpressionHead(): ArrowFunction { - return parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ false); + return parseParenthesizedArrowFunctionExpressionHead(/*inSpeculation*/ true); } function tryParseAsyncSimpleArrowFunctionExpression(): ArrowFunction | undefined { @@ -3409,7 +3448,7 @@ namespace ts { return Tristate.False; } - function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): ArrowFunction { + function parseParenthesizedArrowFunctionExpressionHead(inSpeculation: boolean): ArrowFunction | undefined { const node = createNode(SyntaxKind.ArrowFunction); node.modifiers = parseModifiersForArrowFunction(); const isAsync = hasModifier(node, ModifierFlags.Async) ? SignatureFlags.Await : SignatureFlags.None; @@ -3420,7 +3459,10 @@ namespace ts { // a => (b => c) // And think that "(b =>" was actually a parenthesized arrow function with a missing // close paren. - fillSignature(SyntaxKind.ColonToken, isAsync | (allowAmbiguity ? SignatureFlags.None : SignatureFlags.RequireCompleteParameterList), node); + + if (!fillSignature(SyntaxKind.ColonToken, isAsync | (inSpeculation ? SignatureFlags.RequireCompleteParameterList : SignatureFlags.None), node, inSpeculation)) { + return undefined; + } // If we couldn't get parameters, we definitely could not parse out an arrow function. if (!node.parameters) { @@ -3435,8 +3477,7 @@ namespace ts { // - "a ? (b): c" will have "(b):" parsed as a signature with a return type annotation. // // So we need just a bit of lookahead to ensure that it can only be a signature. - if (!allowAmbiguity && ((token() !== SyntaxKind.EqualsGreaterThanToken && token() !== SyntaxKind.OpenBraceToken) || - find(node.parameters, p => p.initializer && ts.isIdentifier(p.initializer) && p.initializer.escapedText === "= not found"))) { + if (inSpeculation && token() !== SyntaxKind.EqualsGreaterThanToken && token() !== SyntaxKind.OpenBraceToken) { // Returning undefined here will cause our caller to rewind to where we started from. return undefined; } @@ -4574,7 +4615,6 @@ namespace ts { if (saveDecoratorContext) { setDecoratorContext(/*val*/ false); } - const node = createNode(SyntaxKind.FunctionExpression); node.modifiers = parseModifiers(); parseExpected(SyntaxKind.FunctionKeyword); @@ -4590,7 +4630,6 @@ namespace ts { fillSignature(SyntaxKind.ColonToken, isGenerator | isAsync, node); node.body = parseFunctionBlock(isGenerator | isAsync); - if (saveDecoratorContext) { setDecoratorContext(/*val*/ true); } @@ -4653,7 +4692,6 @@ namespace ts { } const block = parseBlock(!!(flags & SignatureFlags.IgnoreMissingOpenBrace), diagnosticMessage); - if (saveDecoratorContext) { setDecoratorContext(/*val*/ true); } @@ -5227,18 +5265,38 @@ namespace ts { // DECLARATIONS + function tryParseArrayBindingElement(): ArrayBindingElement | Fail { + return parseArrayBindingElementWorker(/*inSpeculation*/ true); + } function parseArrayBindingElement(): ArrayBindingElement { + return parseArrayBindingElementWorker(/*inSpeculation*/ false) as ArrayBindingElement; + } + function parseArrayBindingElementWorker(inSpeculation: boolean): ArrayBindingElement | Fail { if (token() === SyntaxKind.CommaToken) { return createNode(SyntaxKind.OmittedExpression); } const node = createNode(SyntaxKind.BindingElement); node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); - node.name = parseIdentifierOrPattern(); - node.initializer = parseInitializer(/*inParameter*/ false); + const name = parseIdentifierOrPattern(inSpeculation); + if (isFail(name)) { + return Fail; + } + node.name = name; + const init = parseInitializer(/*inParameter*/ false, inSpeculation); + if (isFail(init)) { + return Fail; + } + node.initializer = init; return finishNode(node); } + function tryParseObjectBindingElement(): BindingElement | Fail { + return parseObjectBindingElementWorker(/*inSpeculation*/ true); + } function parseObjectBindingElement(): BindingElement { + return parseObjectBindingElementWorker(/*inSpeculation*/ false) as BindingElement; + } + function parseObjectBindingElementWorker(inSpeculation: boolean): BindingElement | Fail { const node = createNode(SyntaxKind.BindingElement); node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); const tokenIsIdentifier = isIdentifier(); @@ -5249,24 +5307,46 @@ namespace ts { else { parseExpected(SyntaxKind.ColonToken); node.propertyName = propertyName; - node.name = parseIdentifierOrPattern(); + const name = parseIdentifierOrPattern(inSpeculation); + if (isFail(name)) { + return Fail; + } + node.name = name; } - node.initializer = parseInitializer(/*inParameter*/ false); + const init = parseInitializer(/*inParameter*/ false, inSpeculation); + if (isFail(init)) { + return Fail; + } + node.initializer = init; return finishNode(node); } - function parseObjectBindingPattern(): ObjectBindingPattern { + function parseObjectBindingPattern(inSpeculation: boolean): ObjectBindingPattern | Fail { const node = createNode(SyntaxKind.ObjectBindingPattern); parseExpected(SyntaxKind.OpenBraceToken); - node.elements = parseDelimitedList(ParsingContext.ObjectBindingElements, parseObjectBindingElement); + const elements = parseDelimitedList( + ParsingContext.ObjectBindingElements, + inSpeculation ? tryParseObjectBindingElement : parseObjectBindingElement, + /*considerSemicolonAsDelimiter*/ undefined); + if (isFailList(elements)) { + return Fail; + } + node.elements = elements; parseExpected(SyntaxKind.CloseBraceToken); return finishNode(node); } - function parseArrayBindingPattern(): ArrayBindingPattern { + function parseArrayBindingPattern(inSpeculation: boolean): ArrayBindingPattern | Fail { const node = createNode(SyntaxKind.ArrayBindingPattern); parseExpected(SyntaxKind.OpenBracketToken); - node.elements = parseDelimitedList(ParsingContext.ArrayBindingElements, parseArrayBindingElement); + const elements = parseDelimitedList( + ParsingContext.ArrayBindingElements, + inSpeculation ? tryParseArrayBindingElement : parseArrayBindingElement, + /*considerSemicolonAsDelimiter*/ undefined); + if (isFailList(elements)) { + return Fail; + } + node.elements = elements; parseExpected(SyntaxKind.CloseBracketToken); return finishNode(node); } @@ -5275,12 +5355,14 @@ namespace ts { return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.OpenBracketToken || isIdentifier(); } - function parseIdentifierOrPattern(): Identifier | BindingPattern { + function parseIdentifierOrPattern(): Identifier | BindingPattern; + function parseIdentifierOrPattern(inSpeculation: boolean): Identifier | BindingPattern | Fail; + function parseIdentifierOrPattern(inSpeculation?: boolean): Identifier | BindingPattern | Fail { if (token() === SyntaxKind.OpenBracketToken) { - return parseArrayBindingPattern(); + return parseArrayBindingPattern(inSpeculation); } if (token() === SyntaxKind.OpenBraceToken) { - return parseObjectBindingPattern(); + return parseObjectBindingPattern(inSpeculation); } return parseIdentifier(); } @@ -5328,9 +5410,7 @@ namespace ts { else { const savedDisallowIn = inDisallowInContext(); setDisallowInContext(inForStatementInitializer); - node.declarations = parseDelimitedList(ParsingContext.VariableDeclarations, parseVariableDeclaration); - setDisallowInContext(savedDisallowIn); } @@ -5428,7 +5508,7 @@ namespace ts { } } - function parseNonParameterInitializer() { + function parseNonParameterInitializer(): Expression | undefined { return parseInitializer(/*inParameter*/ false); } diff --git a/tests/baselines/reference/parserArrowFunctionExpression7.js b/tests/baselines/reference/parserArrowFunctionExpression7.js new file mode 100644 index 00000000000..0646a1bf438 --- /dev/null +++ b/tests/baselines/reference/parserArrowFunctionExpression7.js @@ -0,0 +1,16 @@ +//// [parserArrowFunctionExpression7.ts] +({ + async m() { + for (;;) { + } + } +}); + + +//// [parserArrowFunctionExpression7.js] +({ + async m() { + for (;;) { + } + } +}); diff --git a/tests/baselines/reference/parserArrowFunctionExpression7.symbols b/tests/baselines/reference/parserArrowFunctionExpression7.symbols new file mode 100644 index 00000000000..0dbc2cf05a1 --- /dev/null +++ b/tests/baselines/reference/parserArrowFunctionExpression7.symbols @@ -0,0 +1,10 @@ +=== tests/cases/conformance/parser/ecmascript5/ArrowFunctionExpressions/parserArrowFunctionExpression7.ts === +({ + async m() { +>m : Symbol(m, Decl(parserArrowFunctionExpression7.ts, 0, 2)) + + for (;;) { + } + } +}); + diff --git a/tests/baselines/reference/parserArrowFunctionExpression7.types b/tests/baselines/reference/parserArrowFunctionExpression7.types new file mode 100644 index 00000000000..072a1548bd2 --- /dev/null +++ b/tests/baselines/reference/parserArrowFunctionExpression7.types @@ -0,0 +1,13 @@ +=== tests/cases/conformance/parser/ecmascript5/ArrowFunctionExpressions/parserArrowFunctionExpression7.ts === +({ +>({ async m() { for (;;) { } }}) : { m(): Promise; } +>{ async m() { for (;;) { } }} : { m(): Promise; } + + async m() { +>m : () => Promise + + for (;;) { + } + } +}); + diff --git a/tests/cases/conformance/parser/ecmascript5/ArrowFunctionExpressions/parserArrowFunctionExpression7.ts b/tests/cases/conformance/parser/ecmascript5/ArrowFunctionExpressions/parserArrowFunctionExpression7.ts new file mode 100644 index 00000000000..65911cf0fc6 --- /dev/null +++ b/tests/cases/conformance/parser/ecmascript5/ArrowFunctionExpressions/parserArrowFunctionExpression7.ts @@ -0,0 +1,7 @@ +// @target: esnext +({ + async m() { + for (;;) { + } + } +}); From 52e8e47cfbc8dbac41e75bb9d95a5a06ff9e1f38 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Mon, 13 Nov 2017 10:17:35 -0800 Subject: [PATCH 135/138] Extract JSXChildren checking --- src/compiler/checker.ts | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 981380c70de..85033816766 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14378,19 +14378,7 @@ namespace ts { const parent = openingLikeElement.parent.kind === SyntaxKind.JsxElement ? openingLikeElement.parent as JsxElement : undefined; // We have to check that openingElement of the parent is the one we are visiting as this may not be true for selfClosingElement if (parent && parent.openingElement === openingLikeElement && parent.children.length > 0) { - const childrenTypes: Type[] = []; - for (const child of (parent as JsxElement).children) { - // In React, JSX text that contains only whitespaces will be ignored so we don't want to type-check that - // because then type of children property will have constituent of string type. - if (child.kind === SyntaxKind.JsxText) { - if (!child.containsOnlyWhiteSpaces) { - childrenTypes.push(stringType); - } - } - else { - childrenTypes.push(checkExpression(child, checkMode)); - } - } + const childrenTypes: Type[] = checkJsxChildren(parent as JsxElement, checkMode); if (!hasSpreadAnyType && jsxChildrenPropertyName && jsxChildrenPropertyName !== "") { // Error if there is a attribute named "children" explicitly specified and children element. @@ -14430,6 +14418,23 @@ namespace ts { } } + function checkJsxChildren(node: JsxElement | JsxFragment, checkMode?: CheckMode) { + const childrenTypes: Type[] = []; + for (const child of node.children) { + // In React, JSX text that contains only whitespaces will be ignored so we don't want to type-check that + // because then type of children property will have constituent of string type. + if (child.kind === SyntaxKind.JsxText) { + if (!child.containsOnlyWhiteSpaces) { + childrenTypes.push(stringType); + } + } + else { + childrenTypes.push(checkExpression(child, checkMode)); + } + } + return childrenTypes; + } + /** * Check attributes property of opening-like element. This function is called during chooseOverload to get call signature of a JSX opening-like element. * (See "checkApplicableSignatureForJsxOpeningLikeElement" for how the function is used) @@ -14964,6 +14969,9 @@ namespace ts { if (isNodeOpeningLikeElement) { checkJsxAttributesAssignableToTagNameAttributes(node); } + else { + checkJsxChildren((node as JsxOpeningFragment).parent); + } } /** From c2f0c580dbfec93f6d00a449faa60760469918ea Mon Sep 17 00:00:00 2001 From: Wilson Hobbs Date: Mon, 13 Nov 2017 13:37:54 -0500 Subject: [PATCH 136/138] add types for escape and unescape methods #18813 (#19015) * add types for escape and unescape methods #18813 although the issue is marked working as expected, it is important to mention that most major browsers maintain support for escape and unescape, and some javascript codebases moving to typescript may have escape and unescape in them. They are valid JavaScript, and thus they should be included in the global definition. * add escape and unescape types to lib in tests * update tests to turn CI green --- src/lib/es5.d.ts | 12 + .../fourslash/completionInJSDocFunctionNew.ts | 2 +- .../completionInJSDocFunctionThis.ts | 2 +- .../tsxCompletionOnOpeningTagWithoutJSX1.ts | 2 +- tests/lib/lib.d.ts | 1652 +++++++++-------- 5 files changed, 847 insertions(+), 823 deletions(-) diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index fd2ae5b3fdf..aaefeec7d1a 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -62,6 +62,18 @@ declare function encodeURI(uri: string): string; */ declare function encodeURIComponent(uriComponent: string): string; +/** + * Computes a new string in which certain characters have been replaced by a hexadecimal escape sequence. + * @param string A string value + */ +declare function escape(string: string): string; + +/** + * Computes a new string in which hexadecimal escape sequences are replaced with the character that it represents. + * @param string A string value + */ +declare function unescape(string: string): string; + interface PropertyDescriptor { configurable?: boolean; enumerable?: boolean; diff --git a/tests/cases/fourslash/completionInJSDocFunctionNew.ts b/tests/cases/fourslash/completionInJSDocFunctionNew.ts index 0d3391cf774..742627974bd 100644 --- a/tests/cases/fourslash/completionInJSDocFunctionNew.ts +++ b/tests/cases/fourslash/completionInJSDocFunctionNew.ts @@ -6,5 +6,5 @@ ////var f = function () { return new/**/; } goTo.marker(); -verify.completionListCount(115); +verify.completionListCount(117); verify.completionListContains('new'); diff --git a/tests/cases/fourslash/completionInJSDocFunctionThis.ts b/tests/cases/fourslash/completionInJSDocFunctionThis.ts index c28eeeb397f..e22180aab52 100644 --- a/tests/cases/fourslash/completionInJSDocFunctionThis.ts +++ b/tests/cases/fourslash/completionInJSDocFunctionThis.ts @@ -5,6 +5,6 @@ ////var f = function (s) { return this/**/; } goTo.marker(); -verify.completionListCount(116); +verify.completionListCount(118); verify.completionListContains('this'); diff --git a/tests/cases/fourslash/tsxCompletionOnOpeningTagWithoutJSX1.ts b/tests/cases/fourslash/tsxCompletionOnOpeningTagWithoutJSX1.ts index f208b0a44a4..85cae83288a 100644 --- a/tests/cases/fourslash/tsxCompletionOnOpeningTagWithoutJSX1.ts +++ b/tests/cases/fourslash/tsxCompletionOnOpeningTagWithoutJSX1.ts @@ -4,4 +4,4 @@ //// var x = (o: T): T; @@ -189,25 +201,25 @@ interface ObjectConstructor { /** * Prevents the addition of new properties to an object. - * @param o Object to make non-extensible. + * @param o Object to make non-extensible. */ preventExtensions(o: T): T; /** * Returns true if existing property attributes cannot be modified in an object and new properties cannot be added to the object. - * @param o Object to test. + * @param o Object to test. */ isSealed(o: any): boolean; /** * Returns true if existing property attributes and values cannot be modified in an object, and new properties cannot be added to the object. - * @param o Object to test. + * @param o Object to test. */ isFrozen(o: any): boolean; /** * Returns a value that indicates whether new properties can be added to an object. - * @param o Object to test. + * @param o Object to test. */ isExtensible(o: any): boolean; @@ -242,7 +254,7 @@ interface Function { call(thisArg: any, ...argArray: any[]): any; /** - * For a given function, creates a bound function that has the same body as the original function. + * For a given function, creates a bound function that has the same body as the original function. * The this object of the bound function is associated with the specified object, and has the specified initial parameters. * @param thisArg An object to which the this keyword can refer inside the new function. * @param argArray A list of arguments to be passed to the new function. @@ -285,7 +297,7 @@ interface String { */ charAt(pos: number): string; - /** + /** * Returns the Unicode value of the character at the specified location. * @param index The zero-based index of the desired character. If there is no character at the specified index, NaN is returned. */ @@ -293,12 +305,12 @@ interface String { /** * Returns a string that contains the concatenation of two or more strings. - * @param strings The strings to append to the end of the string. + * @param strings The strings to append to the end of the string. */ concat(...strings: string[]): string; /** - * Returns the position of the first occurrence of a substring. + * Returns the position of the first occurrence of a substring. * @param searchString The substring to search for in the string * @param position The index at which to begin searching the String object. If omitted, search starts at the beginning of the string. */ @@ -317,15 +329,15 @@ interface String { */ localeCompare(that: string): number; - /** + /** * Matches a string with a regular expression, and returns an array containing the results of that search. * @param regexp A variable name or string literal containing the regular expression pattern and flags. */ match(regexp: string): RegExpMatchArray; - /** + /** * Matches a string with a regular expression, and returns an array containing the results of that search. - * @param regexp A regular expression object that contains the regular expression pattern and applicable flags. + * @param regexp A regular expression object that contains the regular expression pattern and applicable flags. */ match(regexp: RegExp): RegExpMatchArray; @@ -359,40 +371,40 @@ interface String { /** * Finds the first substring match in a regular expression search. - * @param regexp The regular expression pattern and applicable flags. + * @param regexp The regular expression pattern and applicable flags. */ search(regexp: string): number; /** * Finds the first substring match in a regular expression search. - * @param regexp The regular expression pattern and applicable flags. + * @param regexp The regular expression pattern and applicable flags. */ search(regexp: RegExp): number; /** * Returns a section of a string. - * @param start The index to the beginning of the specified portion of stringObj. - * @param end The index to the end of the specified portion of stringObj. The substring includes the characters up to, but not including, the character indicated by end. + * @param start The index to the beginning of the specified portion of stringObj. + * @param end The index to the end of the specified portion of stringObj. The substring includes the characters up to, but not including, the character indicated by end. * If this value is not specified, the substring continues to the end of stringObj. */ slice(start?: number, end?: number): string; /** * Split a string into substrings using the specified separator and return them as an array. - * @param separator A string that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned. + * @param separator A string that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned. * @param limit A value used to limit the number of elements returned in the array. */ split(separator: string, limit?: number): string[]; /** * Split a string into substrings using the specified separator and return them as an array. - * @param separator A Regular Express that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned. + * @param separator A Regular Express that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned. * @param limit A value used to limit the number of elements returned in the array. */ split(separator: RegExp, limit?: number): string[]; /** - * Returns the substring at the specified location within a String object. + * Returns the substring at the specified location within a String object. * @param start The zero-based index number indicating the beginning of the substring. * @param end Zero-based index number indicating the end of the substring. The substring includes the characters up to, but not including, the character indicated by end. * If end is omitted, the characters from start through the end of the original string are returned. @@ -438,8 +450,8 @@ interface StringConstructor { fromCharCode(...codes: number[]): string; } -/** - * Allows manipulation and formatting of text strings and determination and location of substrings within strings. +/** + * Allows manipulation and formatting of text strings and determination and location of substrings within strings. */ declare var String: StringConstructor; @@ -463,7 +475,7 @@ interface Number { */ toString(radix?: number): string; - /** + /** * Returns a string representing a number in fixed-point notation. * @param fractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive. */ @@ -496,21 +508,21 @@ interface NumberConstructor { /** The closest number to zero that can be represented in JavaScript. Equal to approximately 5.00E-324. */ MIN_VALUE: number; - /** + /** * A value that is not a number. * In equality comparisons, NaN does not equal any value, including itself. To test whether a value is equivalent to NaN, use the isNaN function. */ NaN: number; - /** + /** * A value that is less than the largest negative number that can be represented in JavaScript. - * JavaScript displays NEGATIVE_INFINITY values as -infinity. + * JavaScript displays NEGATIVE_INFINITY values as -infinity. */ NEGATIVE_INFINITY: number; /** - * A value greater than the largest number that can be represented in JavaScript. - * JavaScript displays POSITIVE_INFINITY values as infinity. + * A value greater than the largest number that can be represented in JavaScript. + * JavaScript displays POSITIVE_INFINITY values as infinity. */ POSITIVE_INFINITY: number; } @@ -540,23 +552,23 @@ interface Math { /** The square root of 2. */ SQRT2: number; /** - * Returns the absolute value of a number (the value without regard to whether it is positive or negative). + * Returns the absolute value of a number (the value without regard to whether it is positive or negative). * For example, the absolute value of -5 is the same as the absolute value of 5. * @param x A numeric expression for which the absolute value is needed. */ abs(x: number): number; /** - * Returns the arc cosine (or inverse cosine) of a number. + * Returns the arc cosine (or inverse cosine) of a number. * @param x A numeric expression. */ acos(x: number): number; - /** - * Returns the arcsine of a number. + /** + * Returns the arcsine of a number. * @param x A numeric expression. */ asin(x: number): number; /** - * Returns the arctangent of a number. + * Returns the arctangent of a number. * @param x A numeric expression for which the arctangent is needed. */ atan(x: number): number; @@ -567,49 +579,49 @@ interface Math { */ atan2(y: number, x: number): number; /** - * Returns the smallest number greater than or equal to its numeric argument. + * Returns the smallest number greater than or equal to its numeric argument. * @param x A numeric expression. */ ceil(x: number): number; /** - * Returns the cosine of a number. + * Returns the cosine of a number. * @param x A numeric expression that contains an angle measured in radians. */ cos(x: number): number; /** - * Returns e (the base of natural logarithms) raised to a power. + * Returns e (the base of natural logarithms) raised to a power. * @param x A numeric expression representing the power of e. */ exp(x: number): number; /** - * Returns the greatest number less than or equal to its numeric argument. + * Returns the greatest number less than or equal to its numeric argument. * @param x A numeric expression. */ floor(x: number): number; /** - * Returns the natural logarithm (base e) of a number. + * Returns the natural logarithm (base e) of a number. * @param x A numeric expression. */ log(x: number): number; /** - * Returns the larger of a set of supplied numeric expressions. + * Returns the larger of a set of supplied numeric expressions. * @param values Numeric expressions to be evaluated. */ max(...values: number[]): number; /** - * Returns the smaller of a set of supplied numeric expressions. + * Returns the smaller of a set of supplied numeric expressions. * @param values Numeric expressions to be evaluated. */ min(...values: number[]): number; /** - * Returns the value of a base expression taken to a specified power. + * Returns the value of a base expression taken to a specified power. * @param x The base value of the expression. * @param y The exponent value of the expression. */ pow(x: number, y: number): number; /** Returns a pseudorandom number between 0 and 1. */ random(): number; - /** + /** * Returns a supplied numeric expression rounded to the nearest number. * @param x The value to be rounded to the nearest number. */ @@ -685,24 +697,24 @@ interface Date { getUTCMilliseconds(): number; /** Gets the difference in minutes between the time on the local computer and Universal Coordinated Time (UTC). */ getTimezoneOffset(): number; - /** + /** * Sets the date and time value in the Date object. - * @param time A numeric value representing the number of elapsed milliseconds since midnight, January 1, 1970 GMT. + * @param time A numeric value representing the number of elapsed milliseconds since midnight, January 1, 1970 GMT. */ setTime(time: number): number; /** - * Sets the milliseconds value in the Date object using local time. + * Sets the milliseconds value in the Date object using local time. * @param ms A numeric value equal to the millisecond value. */ setMilliseconds(ms: number): number; - /** + /** * Sets the milliseconds value in the Date object using Universal Coordinated Time (UTC). - * @param ms A numeric value equal to the millisecond value. + * @param ms A numeric value equal to the millisecond value. */ setUTCMilliseconds(ms: number): number; /** - * Sets the seconds value in the Date object using local time. + * Sets the seconds value in the Date object using local time. * @param sec A numeric value equal to the seconds value. * @param ms A numeric value equal to the milliseconds value. */ @@ -714,16 +726,16 @@ interface Date { */ setUTCSeconds(sec: number, ms?: number): number; /** - * Sets the minutes value in the Date object using local time. - * @param min A numeric value equal to the minutes value. - * @param sec A numeric value equal to the seconds value. + * Sets the minutes value in the Date object using local time. + * @param min A numeric value equal to the minutes value. + * @param sec A numeric value equal to the seconds value. * @param ms A numeric value equal to the milliseconds value. */ setMinutes(min: number, sec?: number, ms?: number): number; /** * Sets the minutes value in the Date object using Universal Coordinated Time (UTC). - * @param min A numeric value equal to the minutes value. - * @param sec A numeric value equal to the seconds value. + * @param min A numeric value equal to the minutes value. + * @param sec A numeric value equal to the seconds value. * @param ms A numeric value equal to the milliseconds value. */ setUTCMinutes(min: number, sec?: number, ms?: number): number; @@ -731,7 +743,7 @@ interface Date { * Sets the hour value in the Date object using local time. * @param hours A numeric value equal to the hours value. * @param min A numeric value equal to the minutes value. - * @param sec A numeric value equal to the seconds value. + * @param sec A numeric value equal to the seconds value. * @param ms A numeric value equal to the milliseconds value. */ setHours(hours: number, min?: number, sec?: number, ms?: number): number; @@ -739,23 +751,23 @@ interface Date { * Sets the hours value in the Date object using Universal Coordinated Time (UTC). * @param hours A numeric value equal to the hours value. * @param min A numeric value equal to the minutes value. - * @param sec A numeric value equal to the seconds value. + * @param sec A numeric value equal to the seconds value. * @param ms A numeric value equal to the milliseconds value. */ setUTCHours(hours: number, min?: number, sec?: number, ms?: number): number; /** - * Sets the numeric day-of-the-month value of the Date object using local time. + * Sets the numeric day-of-the-month value of the Date object using local time. * @param date A numeric value equal to the day of the month. */ setDate(date: number): number; - /** + /** * Sets the numeric day of the month in the Date object using Universal Coordinated Time (UTC). - * @param date A numeric value equal to the day of the month. + * @param date A numeric value equal to the day of the month. */ setUTCDate(date: number): number; - /** - * Sets the month value in the Date object using local time. - * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively. + /** + * Sets the month value in the Date object using local time. + * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively. * @param date A numeric value representing the day of the month. If this value is not supplied, the value from a call to the getDate method is used. */ setMonth(month: number, date?: number): number; @@ -800,7 +812,7 @@ interface DateConstructor { */ parse(s: string): number; /** - * Returns the number of milliseconds between midnight, January 1, 1970 Universal Coordinated Time (UTC) (or GMT) and the specified date. + * Returns the number of milliseconds between midnight, January 1, 1970 Universal Coordinated Time (UTC) (or GMT) and the specified date. * @param year The full year designation is required for cross-century date accuracy. If year is between 0 and 99 is used, then year is assumed to be 1900 + year. * @param month The month as an number between 0 and 11 (January to December). * @param date The date as an number between 1 and 31. @@ -826,13 +838,13 @@ interface RegExpExecArray extends Array { } interface RegExp { - /** + /** * Executes a search on a string using a regular expression pattern, and returns an array containing the results of that search. * @param string The String object or string literal on which to perform the search. */ exec(string: string): RegExpExecArray; - /** + /** * Returns a Boolean value that indicates whether or not a pattern exists in a searched string. * @param string String on which to perform the search. */ @@ -959,8 +971,8 @@ interface JSON { /** * Converts a JavaScript Object Notation (JSON) string into an object. * @param text A valid JSON string. - * @param reviver A function that transforms the results. This function is called for each member of the object. - * If a member contains nested objects, the nested objects are transformed before the parent object is. + * @param reviver A function that transforms the results. This function is called for each member of the object. + * If a member contains nested objects, the nested objects are transformed before the parent object is. */ parse(text: string, reviver?: (key: any, value: any) => any): any; /** @@ -1040,14 +1052,14 @@ interface Array { */ join(separator?: string): string; /** - * Reverses the elements in an Array. + * Reverses the elements in an Array. */ reverse(): T[]; /** * Removes the first element from an array and returns it. */ shift(): T; - /** + /** * Returns a section of an array. * @param start The beginning of the specified portion of the array. * @param end The end of the specified portion of the array. @@ -1110,21 +1122,21 @@ interface Array { /** * Performs the specified action for each element in an array. - * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array. + * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void; /** * Calls a defined callback function on each element of an array, and returns an array that contains the results. - * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array. + * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; /** - * Returns the elements of an array that meet the condition specified in a callback function. - * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array. + * Returns the elements of an array that meet the condition specified in a callback function. + * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ filter(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): T[]; @@ -1142,15 +1154,15 @@ interface Array { */ reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; - /** + /** * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. + * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T; - /** + /** * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. + * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U; @@ -1205,10 +1217,10 @@ interface ArrayLike { /** - * Represents a raw buffer of binary data, which is used to store data for the - * different typed arrays. ArrayBuffers cannot be read from or written to directly, - * but can be passed to a typed array or DataView Object to interpret the raw - * buffer as needed. + * Represents a raw buffer of binary data, which is used to store data for the + * different typed arrays. ArrayBuffers cannot be read from or written to directly, + * but can be passed to a typed array or DataView Object to interpret the raw + * buffer as needed. */ interface ArrayBuffer { /** @@ -1231,7 +1243,7 @@ declare var ArrayBuffer: ArrayBufferConstructor; interface ArrayBufferView { /** - * The ArrayBuffer instance referenced by the array. + * The ArrayBuffer instance referenced by the array. */ buffer: ArrayBuffer; @@ -1251,124 +1263,124 @@ interface DataView { byteLength: number; byteOffset: number; /** - * Gets the Float32 value at the specified byte offset from the start of the view. There is - * no alignment constraint; multi-byte values may be fetched from any offset. + * Gets the Float32 value at the specified byte offset from the start of the view. There is + * no alignment constraint; multi-byte values may be fetched from any offset. * @param byteOffset The place in the buffer at which the value should be retrieved. */ getFloat32(byteOffset: number, littleEndian?: boolean): number; /** * Gets the Float64 value at the specified byte offset from the start of the view. There is - * no alignment constraint; multi-byte values may be fetched from any offset. + * no alignment constraint; multi-byte values may be fetched from any offset. * @param byteOffset The place in the buffer at which the value should be retrieved. */ getFloat64(byteOffset: number, littleEndian?: boolean): number; /** - * Gets the Int8 value at the specified byte offset from the start of the view. There is - * no alignment constraint; multi-byte values may be fetched from any offset. + * Gets the Int8 value at the specified byte offset from the start of the view. There is + * no alignment constraint; multi-byte values may be fetched from any offset. * @param byteOffset The place in the buffer at which the value should be retrieved. */ getInt8(byteOffset: number): number; /** - * Gets the Int16 value at the specified byte offset from the start of the view. There is - * no alignment constraint; multi-byte values may be fetched from any offset. + * Gets the Int16 value at the specified byte offset from the start of the view. There is + * no alignment constraint; multi-byte values may be fetched from any offset. * @param byteOffset The place in the buffer at which the value should be retrieved. */ getInt16(byteOffset: number, littleEndian?: boolean): number; /** - * Gets the Int32 value at the specified byte offset from the start of the view. There is - * no alignment constraint; multi-byte values may be fetched from any offset. + * Gets the Int32 value at the specified byte offset from the start of the view. There is + * no alignment constraint; multi-byte values may be fetched from any offset. * @param byteOffset The place in the buffer at which the value should be retrieved. */ getInt32(byteOffset: number, littleEndian?: boolean): number; /** - * Gets the Uint8 value at the specified byte offset from the start of the view. There is - * no alignment constraint; multi-byte values may be fetched from any offset. + * Gets the Uint8 value at the specified byte offset from the start of the view. There is + * no alignment constraint; multi-byte values may be fetched from any offset. * @param byteOffset The place in the buffer at which the value should be retrieved. */ getUint8(byteOffset: number): number; /** - * Gets the Uint16 value at the specified byte offset from the start of the view. There is - * no alignment constraint; multi-byte values may be fetched from any offset. + * Gets the Uint16 value at the specified byte offset from the start of the view. There is + * no alignment constraint; multi-byte values may be fetched from any offset. * @param byteOffset The place in the buffer at which the value should be retrieved. */ getUint16(byteOffset: number, littleEndian?: boolean): number; /** - * Gets the Uint32 value at the specified byte offset from the start of the view. There is - * no alignment constraint; multi-byte values may be fetched from any offset. + * Gets the Uint32 value at the specified byte offset from the start of the view. There is + * no alignment constraint; multi-byte values may be fetched from any offset. * @param byteOffset The place in the buffer at which the value should be retrieved. */ getUint32(byteOffset: number, littleEndian?: boolean): number; /** - * Stores an Float32 value at the specified byte offset from the start of the view. + * Stores an Float32 value at the specified byte offset from the start of the view. * @param byteOffset The place in the buffer at which the value should be set. * @param value The value to set. - * @param littleEndian If false or undefined, a big-endian value should be written, + * @param littleEndian If false or undefined, a big-endian value should be written, * otherwise a little-endian value should be written. */ setFloat32(byteOffset: number, value: number, littleEndian?: boolean): void; /** - * Stores an Float64 value at the specified byte offset from the start of the view. + * Stores an Float64 value at the specified byte offset from the start of the view. * @param byteOffset The place in the buffer at which the value should be set. * @param value The value to set. - * @param littleEndian If false or undefined, a big-endian value should be written, + * @param littleEndian If false or undefined, a big-endian value should be written, * otherwise a little-endian value should be written. */ setFloat64(byteOffset: number, value: number, littleEndian?: boolean): void; /** - * Stores an Int8 value at the specified byte offset from the start of the view. + * Stores an Int8 value at the specified byte offset from the start of the view. * @param byteOffset The place in the buffer at which the value should be set. * @param value The value to set. */ setInt8(byteOffset: number, value: number): void; /** - * Stores an Int16 value at the specified byte offset from the start of the view. + * Stores an Int16 value at the specified byte offset from the start of the view. * @param byteOffset The place in the buffer at which the value should be set. * @param value The value to set. - * @param littleEndian If false or undefined, a big-endian value should be written, + * @param littleEndian If false or undefined, a big-endian value should be written, * otherwise a little-endian value should be written. */ setInt16(byteOffset: number, value: number, littleEndian?: boolean): void; /** - * Stores an Int32 value at the specified byte offset from the start of the view. + * Stores an Int32 value at the specified byte offset from the start of the view. * @param byteOffset The place in the buffer at which the value should be set. * @param value The value to set. - * @param littleEndian If false or undefined, a big-endian value should be written, + * @param littleEndian If false or undefined, a big-endian value should be written, * otherwise a little-endian value should be written. */ setInt32(byteOffset: number, value: number, littleEndian?: boolean): void; /** - * Stores an Uint8 value at the specified byte offset from the start of the view. + * Stores an Uint8 value at the specified byte offset from the start of the view. * @param byteOffset The place in the buffer at which the value should be set. * @param value The value to set. */ setUint8(byteOffset: number, value: number): void; /** - * Stores an Uint16 value at the specified byte offset from the start of the view. + * Stores an Uint16 value at the specified byte offset from the start of the view. * @param byteOffset The place in the buffer at which the value should be set. * @param value The value to set. - * @param littleEndian If false or undefined, a big-endian value should be written, + * @param littleEndian If false or undefined, a big-endian value should be written, * otherwise a little-endian value should be written. */ setUint16(byteOffset: number, value: number, littleEndian?: boolean): void; /** - * Stores an Uint32 value at the specified byte offset from the start of the view. + * Stores an Uint32 value at the specified byte offset from the start of the view. * @param byteOffset The place in the buffer at which the value should be set. * @param value The value to set. - * @param littleEndian If false or undefined, a big-endian value should be written, + * @param littleEndian If false or undefined, a big-endian value should be written, * otherwise a little-endian value should be written. */ setUint32(byteOffset: number, value: number, littleEndian?: boolean): void; @@ -1380,17 +1392,17 @@ interface DataViewConstructor { declare var DataView: DataViewConstructor; /** - * A typed array of 8-bit integer values. The contents are initialized to 0. If the requested + * A typed array of 8-bit integer values. The contents are initialized to 0. If the requested * number of bytes could not be allocated an exception is raised. */ interface Int8Array { /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; /** - * The ArrayBuffer instance referenced by the array. + * The ArrayBuffer instance referenced by the array. */ buffer: ArrayBuffer; @@ -1404,21 +1416,21 @@ interface Int8Array { */ byteOffset: number; - /** + /** * Returns the this object after copying a section of the array identified by start and end * to the same array starting at position target - * @param target If target is negative, it is treated as length+target where length is the - * length of the array. - * @param start If start is negative, it is treated as length+start. If end is negative, it + * @param target If target is negative, it is treated as length+target where length is the + * length of the array. + * @param start If start is negative, it is treated as length+start. If end is negative, it * is treated as length+end. - * @param end If not specified, length of the this object is used as its default value. + * @param end If not specified, length of the this object is used as its default value. */ copyWithin(target: number, start: number, end?: number): Int8Array; /** * Determines whether all the members of an array satisfy the specified test. - * @param callbackfn A function that accepts up to three arguments. The every method calls - * the callbackfn function for each element in array1 until the callbackfn returns false, + * @param callbackfn A function that accepts up to three arguments. The every method calls + * the callbackfn function for each element in array1 until the callbackfn returns false, * or until the end of the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. @@ -1428,49 +1440,49 @@ interface Int8Array { /** * Returns the this object after filling the section identified by start and end with value * @param value value to fill array section with - * @param start index to start filling the array at. If start is negative, it is treated as - * length+start where length is the length of the array. - * @param end index to stop filling the array at. If end is negative, it is treated as + * @param start index to start filling the array at. If start is negative, it is treated as + * length+start where length is the length of the array. + * @param end index to stop filling the array at. If end is negative, it is treated as * length+end. */ fill(value: number, start?: number, end?: number): Int8Array; /** - * Returns the elements of an array that meet the condition specified in a callback function. - * @param callbackfn A function that accepts up to three arguments. The filter method calls - * the callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * Returns the elements of an array that meet the condition specified in a callback function. + * @param callbackfn A function that accepts up to three arguments. The filter method calls + * the callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ filter(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): Int8Array; - /** - * Returns the value of the first element in the array where predicate is true, and undefined + /** + * Returns the value of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; - /** - * Returns the index of the first element in the array where predicate is true, and undefined + /** + * Returns the index of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ findIndex(predicate: (value: number) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. - * @param callbackfn A function that accepts up to three arguments. forEach calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. forEach calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ forEach(callbackfn: (value: number, index: number, array: Int8Array) => void, thisArg?: any): void; @@ -1485,7 +1497,7 @@ interface Int8Array { /** * Adds all the elements of an array separated by the specified separator string. - * @param separator A string used to separate one element of an array from the next in the + * @param separator A string used to separate one element of an array from the next in the * resulting String. If omitted, the array elements are separated with a comma. */ join(separator?: string): string; @@ -1493,7 +1505,7 @@ interface Int8Array { /** * Returns the index of the last occurrence of a value in an array. * @param searchElement The value to locate in the array. - * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the + * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the * search starts at index 0. */ lastIndexOf(searchElement: number, fromIndex?: number): number; @@ -1504,65 +1516,65 @@ interface Int8Array { length: number; /** - * Calls a defined callback function on each element of an array, and returns an array that + * Calls a defined callback function on each element of an array, and returns an array that * contains the results. - * @param callbackfn A function that accepts up to three arguments. The map method calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. The map method calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ map(callbackfn: (value: number, index: number, array: Int8Array) => number, thisArg?: any): Int8Array; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue?: number): number; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an argument + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, initialValue: U): U; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an + * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue?: number): number; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, initialValue: U): U; /** - * Reverses the elements in an Array. + * Reverses the elements in an Array. */ reverse(): Int8Array; @@ -1580,7 +1592,7 @@ interface Int8Array { */ set(array: ArrayLike, offset?: number): void; - /** + /** * Returns a section of an array. * @param start The beginning of the specified portion of the array. * @param end The end of the specified portion of the array. @@ -1589,31 +1601,31 @@ interface Int8Array { /** * Determines whether the specified callback function returns true for any element of an array. - * @param callbackfn A function that accepts up to three arguments. The some method calls the - * callbackfn function for each element in array1 until the callbackfn returns true, or until + * @param callbackfn A function that accepts up to three arguments. The some method calls the + * callbackfn function for each element in array1 until the callbackfn returns true, or until * the end of the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ some(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): boolean; /** * Sorts an array. - * @param compareFn The name of the function used to determine the order of the elements. If + * @param compareFn The name of the function used to determine the order of the elements. If * omitted, the elements are sorted in ascending, ASCII character order. */ sort(compareFn?: (a: number, b: number) => number): Int8Array; /** * Gets a new Int8Array view of the ArrayBuffer store for this array, referencing the elements - * at begin, inclusive, up to end, exclusive. + * at begin, inclusive, up to end, exclusive. * @param begin The index of the beginning of the array. * @param end The index of the end of the array. */ subarray(begin: number, end?: number): Int8Array; /** - * Converts a number to a string by using the current locale. + * Converts a number to a string by using the current locale. */ toLocaleString(): string; @@ -1631,7 +1643,7 @@ interface Int8ArrayConstructor { new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Int8Array; /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; @@ -1640,7 +1652,7 @@ interface Int8ArrayConstructor { * @param items A set of elements to include in the new array object. */ of(...items: number[]): Int8Array; - + /** * Creates an array from an array-like or iterable object. * @param arrayLike An array-like or iterable object to convert to an array. @@ -1653,17 +1665,17 @@ interface Int8ArrayConstructor { declare var Int8Array: Int8ArrayConstructor; /** - * A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the + * A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the * requested number of bytes could not be allocated an exception is raised. */ interface Uint8Array { /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; /** - * The ArrayBuffer instance referenced by the array. + * The ArrayBuffer instance referenced by the array. */ buffer: ArrayBuffer; @@ -1677,21 +1689,21 @@ interface Uint8Array { */ byteOffset: number; - /** + /** * Returns the this object after copying a section of the array identified by start and end * to the same array starting at position target - * @param target If target is negative, it is treated as length+target where length is the - * length of the array. - * @param start If start is negative, it is treated as length+start. If end is negative, it + * @param target If target is negative, it is treated as length+target where length is the + * length of the array. + * @param start If start is negative, it is treated as length+start. If end is negative, it * is treated as length+end. - * @param end If not specified, length of the this object is used as its default value. + * @param end If not specified, length of the this object is used as its default value. */ copyWithin(target: number, start: number, end?: number): Uint8Array; /** * Determines whether all the members of an array satisfy the specified test. - * @param callbackfn A function that accepts up to three arguments. The every method calls - * the callbackfn function for each element in array1 until the callbackfn returns false, + * @param callbackfn A function that accepts up to three arguments. The every method calls + * the callbackfn function for each element in array1 until the callbackfn returns false, * or until the end of the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. @@ -1701,49 +1713,49 @@ interface Uint8Array { /** * Returns the this object after filling the section identified by start and end with value * @param value value to fill array section with - * @param start index to start filling the array at. If start is negative, it is treated as - * length+start where length is the length of the array. - * @param end index to stop filling the array at. If end is negative, it is treated as + * @param start index to start filling the array at. If start is negative, it is treated as + * length+start where length is the length of the array. + * @param end index to stop filling the array at. If end is negative, it is treated as * length+end. */ fill(value: number, start?: number, end?: number): Uint8Array; /** - * Returns the elements of an array that meet the condition specified in a callback function. - * @param callbackfn A function that accepts up to three arguments. The filter method calls - * the callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * Returns the elements of an array that meet the condition specified in a callback function. + * @param callbackfn A function that accepts up to three arguments. The filter method calls + * the callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ filter(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): Uint8Array; - /** - * Returns the value of the first element in the array where predicate is true, and undefined + /** + * Returns the value of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; - /** - * Returns the index of the first element in the array where predicate is true, and undefined + /** + * Returns the index of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ findIndex(predicate: (value: number) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. - * @param callbackfn A function that accepts up to three arguments. forEach calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. forEach calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ forEach(callbackfn: (value: number, index: number, array: Uint8Array) => void, thisArg?: any): void; @@ -1758,7 +1770,7 @@ interface Uint8Array { /** * Adds all the elements of an array separated by the specified separator string. - * @param separator A string used to separate one element of an array from the next in the + * @param separator A string used to separate one element of an array from the next in the * resulting String. If omitted, the array elements are separated with a comma. */ join(separator?: string): string; @@ -1766,7 +1778,7 @@ interface Uint8Array { /** * Returns the index of the last occurrence of a value in an array. * @param searchElement The value to locate in the array. - * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the + * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the * search starts at index 0. */ lastIndexOf(searchElement: number, fromIndex?: number): number; @@ -1777,65 +1789,65 @@ interface Uint8Array { length: number; /** - * Calls a defined callback function on each element of an array, and returns an array that + * Calls a defined callback function on each element of an array, and returns an array that * contains the results. - * @param callbackfn A function that accepts up to three arguments. The map method calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. The map method calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ map(callbackfn: (value: number, index: number, array: Uint8Array) => number, thisArg?: any): Uint8Array; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue?: number): number; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an argument + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U): U; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an + * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue?: number): number; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U): U; /** - * Reverses the elements in an Array. + * Reverses the elements in an Array. */ reverse(): Uint8Array; @@ -1853,7 +1865,7 @@ interface Uint8Array { */ set(array: ArrayLike, offset?: number): void; - /** + /** * Returns a section of an array. * @param start The beginning of the specified portion of the array. * @param end The end of the specified portion of the array. @@ -1862,31 +1874,31 @@ interface Uint8Array { /** * Determines whether the specified callback function returns true for any element of an array. - * @param callbackfn A function that accepts up to three arguments. The some method calls the - * callbackfn function for each element in array1 until the callbackfn returns true, or until + * @param callbackfn A function that accepts up to three arguments. The some method calls the + * callbackfn function for each element in array1 until the callbackfn returns true, or until * the end of the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ some(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): boolean; /** * Sorts an array. - * @param compareFn The name of the function used to determine the order of the elements. If + * @param compareFn The name of the function used to determine the order of the elements. If * omitted, the elements are sorted in ascending, ASCII character order. */ sort(compareFn?: (a: number, b: number) => number): Uint8Array; /** * Gets a new Uint8Array view of the ArrayBuffer store for this array, referencing the elements - * at begin, inclusive, up to end, exclusive. + * at begin, inclusive, up to end, exclusive. * @param begin The index of the beginning of the array. * @param end The index of the end of the array. */ subarray(begin: number, end?: number): Uint8Array; /** - * Converts a number to a string by using the current locale. + * Converts a number to a string by using the current locale. */ toLocaleString(): string; @@ -1905,7 +1917,7 @@ interface Uint8ArrayConstructor { new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Uint8Array; /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; @@ -1914,7 +1926,7 @@ interface Uint8ArrayConstructor { * @param items A set of elements to include in the new array object. */ of(...items: number[]): Uint8Array; - + /** * Creates an array from an array-like or iterable object. * @param arrayLike An array-like or iterable object to convert to an array. @@ -1927,17 +1939,17 @@ interface Uint8ArrayConstructor { declare var Uint8Array: Uint8ArrayConstructor; /** - * A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0. + * A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0. * If the requested number of bytes could not be allocated an exception is raised. */ interface Uint8ClampedArray { /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; /** - * The ArrayBuffer instance referenced by the array. + * The ArrayBuffer instance referenced by the array. */ buffer: ArrayBuffer; @@ -1951,21 +1963,21 @@ interface Uint8ClampedArray { */ byteOffset: number; - /** + /** * Returns the this object after copying a section of the array identified by start and end * to the same array starting at position target - * @param target If target is negative, it is treated as length+target where length is the - * length of the array. - * @param start If start is negative, it is treated as length+start. If end is negative, it + * @param target If target is negative, it is treated as length+target where length is the + * length of the array. + * @param start If start is negative, it is treated as length+start. If end is negative, it * is treated as length+end. - * @param end If not specified, length of the this object is used as its default value. + * @param end If not specified, length of the this object is used as its default value. */ copyWithin(target: number, start: number, end?: number): Uint8ClampedArray; /** * Determines whether all the members of an array satisfy the specified test. - * @param callbackfn A function that accepts up to three arguments. The every method calls - * the callbackfn function for each element in array1 until the callbackfn returns false, + * @param callbackfn A function that accepts up to three arguments. The every method calls + * the callbackfn function for each element in array1 until the callbackfn returns false, * or until the end of the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. @@ -1975,49 +1987,49 @@ interface Uint8ClampedArray { /** * Returns the this object after filling the section identified by start and end with value * @param value value to fill array section with - * @param start index to start filling the array at. If start is negative, it is treated as - * length+start where length is the length of the array. - * @param end index to stop filling the array at. If end is negative, it is treated as + * @param start index to start filling the array at. If start is negative, it is treated as + * length+start where length is the length of the array. + * @param end index to stop filling the array at. If end is negative, it is treated as * length+end. */ fill(value: number, start?: number, end?: number): Uint8ClampedArray; /** - * Returns the elements of an array that meet the condition specified in a callback function. - * @param callbackfn A function that accepts up to three arguments. The filter method calls - * the callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * Returns the elements of an array that meet the condition specified in a callback function. + * @param callbackfn A function that accepts up to three arguments. The filter method calls + * the callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ filter(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg?: any): Uint8ClampedArray; - /** - * Returns the value of the first element in the array where predicate is true, and undefined + /** + * Returns the value of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; - /** - * Returns the index of the first element in the array where predicate is true, and undefined + /** + * Returns the index of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ findIndex(predicate: (value: number) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. - * @param callbackfn A function that accepts up to three arguments. forEach calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. forEach calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ forEach(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => void, thisArg?: any): void; @@ -2032,7 +2044,7 @@ interface Uint8ClampedArray { /** * Adds all the elements of an array separated by the specified separator string. - * @param separator A string used to separate one element of an array from the next in the + * @param separator A string used to separate one element of an array from the next in the * resulting String. If omitted, the array elements are separated with a comma. */ join(separator?: string): string; @@ -2040,7 +2052,7 @@ interface Uint8ClampedArray { /** * Returns the index of the last occurrence of a value in an array. * @param searchElement The value to locate in the array. - * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the + * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the * search starts at index 0. */ lastIndexOf(searchElement: number, fromIndex?: number): number; @@ -2051,65 +2063,65 @@ interface Uint8ClampedArray { length: number; /** - * Calls a defined callback function on each element of an array, and returns an array that + * Calls a defined callback function on each element of an array, and returns an array that * contains the results. - * @param callbackfn A function that accepts up to three arguments. The map method calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. The map method calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ map(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => number, thisArg?: any): Uint8ClampedArray; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number, initialValue?: number): number; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an argument + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U, initialValue: U): U; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an + * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number, initialValue?: number): number; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U, initialValue: U): U; /** - * Reverses the elements in an Array. + * Reverses the elements in an Array. */ reverse(): Uint8ClampedArray; @@ -2127,7 +2139,7 @@ interface Uint8ClampedArray { */ set(array: Uint8ClampedArray, offset?: number): void; - /** + /** * Returns a section of an array. * @param start The beginning of the specified portion of the array. * @param end The end of the specified portion of the array. @@ -2136,31 +2148,31 @@ interface Uint8ClampedArray { /** * Determines whether the specified callback function returns true for any element of an array. - * @param callbackfn A function that accepts up to three arguments. The some method calls the - * callbackfn function for each element in array1 until the callbackfn returns true, or until + * @param callbackfn A function that accepts up to three arguments. The some method calls the + * callbackfn function for each element in array1 until the callbackfn returns true, or until * the end of the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ some(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg?: any): boolean; /** * Sorts an array. - * @param compareFn The name of the function used to determine the order of the elements. If + * @param compareFn The name of the function used to determine the order of the elements. If * omitted, the elements are sorted in ascending, ASCII character order. */ sort(compareFn?: (a: number, b: number) => number): Uint8ClampedArray; /** * Gets a new Uint8ClampedArray view of the ArrayBuffer store for this array, referencing the elements - * at begin, inclusive, up to end, exclusive. + * at begin, inclusive, up to end, exclusive. * @param begin The index of the beginning of the array. * @param end The index of the end of the array. */ subarray(begin: number, end?: number): Uint8ClampedArray; /** - * Converts a number to a string by using the current locale. + * Converts a number to a string by using the current locale. */ toLocaleString(): string; @@ -2179,7 +2191,7 @@ interface Uint8ClampedArrayConstructor { new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Uint8ClampedArray; /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; @@ -2200,17 +2212,17 @@ interface Uint8ClampedArrayConstructor { declare var Uint8ClampedArray: Uint8ClampedArrayConstructor; /** - * A typed array of 16-bit signed integer values. The contents are initialized to 0. If the + * A typed array of 16-bit signed integer values. The contents are initialized to 0. If the * requested number of bytes could not be allocated an exception is raised. */ interface Int16Array { /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; /** - * The ArrayBuffer instance referenced by the array. + * The ArrayBuffer instance referenced by the array. */ buffer: ArrayBuffer; @@ -2224,21 +2236,21 @@ interface Int16Array { */ byteOffset: number; - /** + /** * Returns the this object after copying a section of the array identified by start and end * to the same array starting at position target - * @param target If target is negative, it is treated as length+target where length is the - * length of the array. - * @param start If start is negative, it is treated as length+start. If end is negative, it + * @param target If target is negative, it is treated as length+target where length is the + * length of the array. + * @param start If start is negative, it is treated as length+start. If end is negative, it * is treated as length+end. - * @param end If not specified, length of the this object is used as its default value. + * @param end If not specified, length of the this object is used as its default value. */ copyWithin(target: number, start: number, end?: number): Int16Array; /** * Determines whether all the members of an array satisfy the specified test. - * @param callbackfn A function that accepts up to three arguments. The every method calls - * the callbackfn function for each element in array1 until the callbackfn returns false, + * @param callbackfn A function that accepts up to three arguments. The every method calls + * the callbackfn function for each element in array1 until the callbackfn returns false, * or until the end of the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. @@ -2248,49 +2260,49 @@ interface Int16Array { /** * Returns the this object after filling the section identified by start and end with value * @param value value to fill array section with - * @param start index to start filling the array at. If start is negative, it is treated as - * length+start where length is the length of the array. - * @param end index to stop filling the array at. If end is negative, it is treated as + * @param start index to start filling the array at. If start is negative, it is treated as + * length+start where length is the length of the array. + * @param end index to stop filling the array at. If end is negative, it is treated as * length+end. */ fill(value: number, start?: number, end?: number): Int16Array; /** - * Returns the elements of an array that meet the condition specified in a callback function. - * @param callbackfn A function that accepts up to three arguments. The filter method calls - * the callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * Returns the elements of an array that meet the condition specified in a callback function. + * @param callbackfn A function that accepts up to three arguments. The filter method calls + * the callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ filter(callbackfn: (value: number, index: number, array: Int16Array) => boolean, thisArg?: any): Int16Array; - /** - * Returns the value of the first element in the array where predicate is true, and undefined + /** + * Returns the value of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; - /** - * Returns the index of the first element in the array where predicate is true, and undefined + /** + * Returns the index of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ findIndex(predicate: (value: number) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. - * @param callbackfn A function that accepts up to three arguments. forEach calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. forEach calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ forEach(callbackfn: (value: number, index: number, array: Int16Array) => void, thisArg?: any): void; @@ -2305,7 +2317,7 @@ interface Int16Array { /** * Adds all the elements of an array separated by the specified separator string. - * @param separator A string used to separate one element of an array from the next in the + * @param separator A string used to separate one element of an array from the next in the * resulting String. If omitted, the array elements are separated with a comma. */ join(separator?: string): string; @@ -2313,7 +2325,7 @@ interface Int16Array { /** * Returns the index of the last occurrence of a value in an array. * @param searchElement The value to locate in the array. - * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the + * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the * search starts at index 0. */ lastIndexOf(searchElement: number, fromIndex?: number): number; @@ -2324,65 +2336,65 @@ interface Int16Array { length: number; /** - * Calls a defined callback function on each element of an array, and returns an array that + * Calls a defined callback function on each element of an array, and returns an array that * contains the results. - * @param callbackfn A function that accepts up to three arguments. The map method calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. The map method calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ map(callbackfn: (value: number, index: number, array: Int16Array) => number, thisArg?: any): Int16Array; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, initialValue?: number): number; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an argument + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int16Array) => U, initialValue: U): U; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an + * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, initialValue?: number): number; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int16Array) => U, initialValue: U): U; /** - * Reverses the elements in an Array. + * Reverses the elements in an Array. */ reverse(): Int16Array; @@ -2400,7 +2412,7 @@ interface Int16Array { */ set(array: ArrayLike, offset?: number): void; - /** + /** * Returns a section of an array. * @param start The beginning of the specified portion of the array. * @param end The end of the specified portion of the array. @@ -2409,31 +2421,31 @@ interface Int16Array { /** * Determines whether the specified callback function returns true for any element of an array. - * @param callbackfn A function that accepts up to three arguments. The some method calls the - * callbackfn function for each element in array1 until the callbackfn returns true, or until + * @param callbackfn A function that accepts up to three arguments. The some method calls the + * callbackfn function for each element in array1 until the callbackfn returns true, or until * the end of the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ some(callbackfn: (value: number, index: number, array: Int16Array) => boolean, thisArg?: any): boolean; /** * Sorts an array. - * @param compareFn The name of the function used to determine the order of the elements. If + * @param compareFn The name of the function used to determine the order of the elements. If * omitted, the elements are sorted in ascending, ASCII character order. */ sort(compareFn?: (a: number, b: number) => number): Int16Array; /** * Gets a new Int16Array view of the ArrayBuffer store for this array, referencing the elements - * at begin, inclusive, up to end, exclusive. + * at begin, inclusive, up to end, exclusive. * @param begin The index of the beginning of the array. * @param end The index of the end of the array. */ subarray(begin: number, end?: number): Int16Array; /** - * Converts a number to a string by using the current locale. + * Converts a number to a string by using the current locale. */ toLocaleString(): string; @@ -2452,7 +2464,7 @@ interface Int16ArrayConstructor { new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Int16Array; /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; @@ -2461,7 +2473,7 @@ interface Int16ArrayConstructor { * @param items A set of elements to include in the new array object. */ of(...items: number[]): Int16Array; - + /** * Creates an array from an array-like or iterable object. * @param arrayLike An array-like or iterable object to convert to an array. @@ -2474,17 +2486,17 @@ interface Int16ArrayConstructor { declare var Int16Array: Int16ArrayConstructor; /** - * A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the + * A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the * requested number of bytes could not be allocated an exception is raised. */ interface Uint16Array { /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; /** - * The ArrayBuffer instance referenced by the array. + * The ArrayBuffer instance referenced by the array. */ buffer: ArrayBuffer; @@ -2498,21 +2510,21 @@ interface Uint16Array { */ byteOffset: number; - /** + /** * Returns the this object after copying a section of the array identified by start and end * to the same array starting at position target - * @param target If target is negative, it is treated as length+target where length is the - * length of the array. - * @param start If start is negative, it is treated as length+start. If end is negative, it + * @param target If target is negative, it is treated as length+target where length is the + * length of the array. + * @param start If start is negative, it is treated as length+start. If end is negative, it * is treated as length+end. - * @param end If not specified, length of the this object is used as its default value. + * @param end If not specified, length of the this object is used as its default value. */ copyWithin(target: number, start: number, end?: number): Uint16Array; /** * Determines whether all the members of an array satisfy the specified test. - * @param callbackfn A function that accepts up to three arguments. The every method calls - * the callbackfn function for each element in array1 until the callbackfn returns false, + * @param callbackfn A function that accepts up to three arguments. The every method calls + * the callbackfn function for each element in array1 until the callbackfn returns false, * or until the end of the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. @@ -2522,49 +2534,49 @@ interface Uint16Array { /** * Returns the this object after filling the section identified by start and end with value * @param value value to fill array section with - * @param start index to start filling the array at. If start is negative, it is treated as - * length+start where length is the length of the array. - * @param end index to stop filling the array at. If end is negative, it is treated as + * @param start index to start filling the array at. If start is negative, it is treated as + * length+start where length is the length of the array. + * @param end index to stop filling the array at. If end is negative, it is treated as * length+end. */ fill(value: number, start?: number, end?: number): Uint16Array; /** - * Returns the elements of an array that meet the condition specified in a callback function. - * @param callbackfn A function that accepts up to three arguments. The filter method calls - * the callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * Returns the elements of an array that meet the condition specified in a callback function. + * @param callbackfn A function that accepts up to three arguments. The filter method calls + * the callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ filter(callbackfn: (value: number, index: number, array: Uint16Array) => boolean, thisArg?: any): Uint16Array; - /** - * Returns the value of the first element in the array where predicate is true, and undefined + /** + * Returns the value of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; - /** - * Returns the index of the first element in the array where predicate is true, and undefined + /** + * Returns the index of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ findIndex(predicate: (value: number) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. - * @param callbackfn A function that accepts up to three arguments. forEach calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. forEach calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ forEach(callbackfn: (value: number, index: number, array: Uint16Array) => void, thisArg?: any): void; @@ -2579,7 +2591,7 @@ interface Uint16Array { /** * Adds all the elements of an array separated by the specified separator string. - * @param separator A string used to separate one element of an array from the next in the + * @param separator A string used to separate one element of an array from the next in the * resulting String. If omitted, the array elements are separated with a comma. */ join(separator?: string): string; @@ -2587,7 +2599,7 @@ interface Uint16Array { /** * Returns the index of the last occurrence of a value in an array. * @param searchElement The value to locate in the array. - * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the + * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the * search starts at index 0. */ lastIndexOf(searchElement: number, fromIndex?: number): number; @@ -2598,65 +2610,65 @@ interface Uint16Array { length: number; /** - * Calls a defined callback function on each element of an array, and returns an array that + * Calls a defined callback function on each element of an array, and returns an array that * contains the results. - * @param callbackfn A function that accepts up to three arguments. The map method calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. The map method calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ map(callbackfn: (value: number, index: number, array: Uint16Array) => number, thisArg?: any): Uint16Array; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, initialValue?: number): number; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an argument + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U, initialValue: U): U; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an + * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, initialValue?: number): number; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U, initialValue: U): U; /** - * Reverses the elements in an Array. + * Reverses the elements in an Array. */ reverse(): Uint16Array; @@ -2674,7 +2686,7 @@ interface Uint16Array { */ set(array: ArrayLike, offset?: number): void; - /** + /** * Returns a section of an array. * @param start The beginning of the specified portion of the array. * @param end The end of the specified portion of the array. @@ -2683,31 +2695,31 @@ interface Uint16Array { /** * Determines whether the specified callback function returns true for any element of an array. - * @param callbackfn A function that accepts up to three arguments. The some method calls the - * callbackfn function for each element in array1 until the callbackfn returns true, or until + * @param callbackfn A function that accepts up to three arguments. The some method calls the + * callbackfn function for each element in array1 until the callbackfn returns true, or until * the end of the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ some(callbackfn: (value: number, index: number, array: Uint16Array) => boolean, thisArg?: any): boolean; /** * Sorts an array. - * @param compareFn The name of the function used to determine the order of the elements. If + * @param compareFn The name of the function used to determine the order of the elements. If * omitted, the elements are sorted in ascending, ASCII character order. */ sort(compareFn?: (a: number, b: number) => number): Uint16Array; /** * Gets a new Uint16Array view of the ArrayBuffer store for this array, referencing the elements - * at begin, inclusive, up to end, exclusive. + * at begin, inclusive, up to end, exclusive. * @param begin The index of the beginning of the array. * @param end The index of the end of the array. */ subarray(begin: number, end?: number): Uint16Array; /** - * Converts a number to a string by using the current locale. + * Converts a number to a string by using the current locale. */ toLocaleString(): string; @@ -2726,7 +2738,7 @@ interface Uint16ArrayConstructor { new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Uint16Array; /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; @@ -2735,7 +2747,7 @@ interface Uint16ArrayConstructor { * @param items A set of elements to include in the new array object. */ of(...items: number[]): Uint16Array; - + /** * Creates an array from an array-like or iterable object. * @param arrayLike An array-like or iterable object to convert to an array. @@ -2747,17 +2759,17 @@ interface Uint16ArrayConstructor { } declare var Uint16Array: Uint16ArrayConstructor; /** - * A typed array of 32-bit signed integer values. The contents are initialized to 0. If the + * A typed array of 32-bit signed integer values. The contents are initialized to 0. If the * requested number of bytes could not be allocated an exception is raised. */ interface Int32Array { /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; /** - * The ArrayBuffer instance referenced by the array. + * The ArrayBuffer instance referenced by the array. */ buffer: ArrayBuffer; @@ -2771,21 +2783,21 @@ interface Int32Array { */ byteOffset: number; - /** + /** * Returns the this object after copying a section of the array identified by start and end * to the same array starting at position target - * @param target If target is negative, it is treated as length+target where length is the - * length of the array. - * @param start If start is negative, it is treated as length+start. If end is negative, it + * @param target If target is negative, it is treated as length+target where length is the + * length of the array. + * @param start If start is negative, it is treated as length+start. If end is negative, it * is treated as length+end. - * @param end If not specified, length of the this object is used as its default value. + * @param end If not specified, length of the this object is used as its default value. */ copyWithin(target: number, start: number, end?: number): Int32Array; /** * Determines whether all the members of an array satisfy the specified test. - * @param callbackfn A function that accepts up to three arguments. The every method calls - * the callbackfn function for each element in array1 until the callbackfn returns false, + * @param callbackfn A function that accepts up to three arguments. The every method calls + * the callbackfn function for each element in array1 until the callbackfn returns false, * or until the end of the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. @@ -2795,49 +2807,49 @@ interface Int32Array { /** * Returns the this object after filling the section identified by start and end with value * @param value value to fill array section with - * @param start index to start filling the array at. If start is negative, it is treated as - * length+start where length is the length of the array. - * @param end index to stop filling the array at. If end is negative, it is treated as + * @param start index to start filling the array at. If start is negative, it is treated as + * length+start where length is the length of the array. + * @param end index to stop filling the array at. If end is negative, it is treated as * length+end. */ fill(value: number, start?: number, end?: number): Int32Array; /** - * Returns the elements of an array that meet the condition specified in a callback function. - * @param callbackfn A function that accepts up to three arguments. The filter method calls - * the callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * Returns the elements of an array that meet the condition specified in a callback function. + * @param callbackfn A function that accepts up to three arguments. The filter method calls + * the callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ filter(callbackfn: (value: number, index: number, array: Int32Array) => boolean, thisArg?: any): Int32Array; - /** - * Returns the value of the first element in the array where predicate is true, and undefined + /** + * Returns the value of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; - /** - * Returns the index of the first element in the array where predicate is true, and undefined + /** + * Returns the index of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ findIndex(predicate: (value: number) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. - * @param callbackfn A function that accepts up to three arguments. forEach calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. forEach calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ forEach(callbackfn: (value: number, index: number, array: Int32Array) => void, thisArg?: any): void; @@ -2852,7 +2864,7 @@ interface Int32Array { /** * Adds all the elements of an array separated by the specified separator string. - * @param separator A string used to separate one element of an array from the next in the + * @param separator A string used to separate one element of an array from the next in the * resulting String. If omitted, the array elements are separated with a comma. */ join(separator?: string): string; @@ -2860,7 +2872,7 @@ interface Int32Array { /** * Returns the index of the last occurrence of a value in an array. * @param searchElement The value to locate in the array. - * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the + * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the * search starts at index 0. */ lastIndexOf(searchElement: number, fromIndex?: number): number; @@ -2871,65 +2883,65 @@ interface Int32Array { length: number; /** - * Calls a defined callback function on each element of an array, and returns an array that + * Calls a defined callback function on each element of an array, and returns an array that * contains the results. - * @param callbackfn A function that accepts up to three arguments. The map method calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. The map method calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ map(callbackfn: (value: number, index: number, array: Int32Array) => number, thisArg?: any): Int32Array; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, initialValue?: number): number; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an argument + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int32Array) => U, initialValue: U): U; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an + * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, initialValue?: number): number; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int32Array) => U, initialValue: U): U; /** - * Reverses the elements in an Array. + * Reverses the elements in an Array. */ reverse(): Int32Array; @@ -2947,7 +2959,7 @@ interface Int32Array { */ set(array: ArrayLike, offset?: number): void; - /** + /** * Returns a section of an array. * @param start The beginning of the specified portion of the array. * @param end The end of the specified portion of the array. @@ -2956,31 +2968,31 @@ interface Int32Array { /** * Determines whether the specified callback function returns true for any element of an array. - * @param callbackfn A function that accepts up to three arguments. The some method calls the - * callbackfn function for each element in array1 until the callbackfn returns true, or until + * @param callbackfn A function that accepts up to three arguments. The some method calls the + * callbackfn function for each element in array1 until the callbackfn returns true, or until * the end of the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ some(callbackfn: (value: number, index: number, array: Int32Array) => boolean, thisArg?: any): boolean; /** * Sorts an array. - * @param compareFn The name of the function used to determine the order of the elements. If + * @param compareFn The name of the function used to determine the order of the elements. If * omitted, the elements are sorted in ascending, ASCII character order. */ sort(compareFn?: (a: number, b: number) => number): Int32Array; /** * Gets a new Int32Array view of the ArrayBuffer store for this array, referencing the elements - * at begin, inclusive, up to end, exclusive. + * at begin, inclusive, up to end, exclusive. * @param begin The index of the beginning of the array. * @param end The index of the end of the array. */ subarray(begin: number, end?: number): Int32Array; /** - * Converts a number to a string by using the current locale. + * Converts a number to a string by using the current locale. */ toLocaleString(): string; @@ -2999,7 +3011,7 @@ interface Int32ArrayConstructor { new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Int32Array; /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; @@ -3008,7 +3020,7 @@ interface Int32ArrayConstructor { * @param items A set of elements to include in the new array object. */ of(...items: number[]): Int32Array; - + /** * Creates an array from an array-like or iterable object. * @param arrayLike An array-like or iterable object to convert to an array. @@ -3020,17 +3032,17 @@ interface Int32ArrayConstructor { declare var Int32Array: Int32ArrayConstructor; /** - * A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the + * A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the * requested number of bytes could not be allocated an exception is raised. */ interface Uint32Array { /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; /** - * The ArrayBuffer instance referenced by the array. + * The ArrayBuffer instance referenced by the array. */ buffer: ArrayBuffer; @@ -3044,21 +3056,21 @@ interface Uint32Array { */ byteOffset: number; - /** + /** * Returns the this object after copying a section of the array identified by start and end * to the same array starting at position target - * @param target If target is negative, it is treated as length+target where length is the - * length of the array. - * @param start If start is negative, it is treated as length+start. If end is negative, it + * @param target If target is negative, it is treated as length+target where length is the + * length of the array. + * @param start If start is negative, it is treated as length+start. If end is negative, it * is treated as length+end. - * @param end If not specified, length of the this object is used as its default value. + * @param end If not specified, length of the this object is used as its default value. */ copyWithin(target: number, start: number, end?: number): Uint32Array; /** * Determines whether all the members of an array satisfy the specified test. - * @param callbackfn A function that accepts up to three arguments. The every method calls - * the callbackfn function for each element in array1 until the callbackfn returns false, + * @param callbackfn A function that accepts up to three arguments. The every method calls + * the callbackfn function for each element in array1 until the callbackfn returns false, * or until the end of the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. @@ -3068,49 +3080,49 @@ interface Uint32Array { /** * Returns the this object after filling the section identified by start and end with value * @param value value to fill array section with - * @param start index to start filling the array at. If start is negative, it is treated as - * length+start where length is the length of the array. - * @param end index to stop filling the array at. If end is negative, it is treated as + * @param start index to start filling the array at. If start is negative, it is treated as + * length+start where length is the length of the array. + * @param end index to stop filling the array at. If end is negative, it is treated as * length+end. */ fill(value: number, start?: number, end?: number): Uint32Array; /** - * Returns the elements of an array that meet the condition specified in a callback function. - * @param callbackfn A function that accepts up to three arguments. The filter method calls - * the callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * Returns the elements of an array that meet the condition specified in a callback function. + * @param callbackfn A function that accepts up to three arguments. The filter method calls + * the callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ filter(callbackfn: (value: number, index: number, array: Uint32Array) => boolean, thisArg?: any): Uint32Array; - /** - * Returns the value of the first element in the array where predicate is true, and undefined + /** + * Returns the value of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; - /** - * Returns the index of the first element in the array where predicate is true, and undefined + /** + * Returns the index of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ findIndex(predicate: (value: number) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. - * @param callbackfn A function that accepts up to three arguments. forEach calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. forEach calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ forEach(callbackfn: (value: number, index: number, array: Uint32Array) => void, thisArg?: any): void; @@ -3125,7 +3137,7 @@ interface Uint32Array { /** * Adds all the elements of an array separated by the specified separator string. - * @param separator A string used to separate one element of an array from the next in the + * @param separator A string used to separate one element of an array from the next in the * resulting String. If omitted, the array elements are separated with a comma. */ join(separator?: string): string; @@ -3133,7 +3145,7 @@ interface Uint32Array { /** * Returns the index of the last occurrence of a value in an array. * @param searchElement The value to locate in the array. - * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the + * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the * search starts at index 0. */ lastIndexOf(searchElement: number, fromIndex?: number): number; @@ -3144,65 +3156,65 @@ interface Uint32Array { length: number; /** - * Calls a defined callback function on each element of an array, and returns an array that + * Calls a defined callback function on each element of an array, and returns an array that * contains the results. - * @param callbackfn A function that accepts up to three arguments. The map method calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. The map method calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ map(callbackfn: (value: number, index: number, array: Uint32Array) => number, thisArg?: any): Uint32Array; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, initialValue?: number): number; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an argument + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U, initialValue: U): U; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an + * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, initialValue?: number): number; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U, initialValue: U): U; /** - * Reverses the elements in an Array. + * Reverses the elements in an Array. */ reverse(): Uint32Array; @@ -3220,7 +3232,7 @@ interface Uint32Array { */ set(array: ArrayLike, offset?: number): void; - /** + /** * Returns a section of an array. * @param start The beginning of the specified portion of the array. * @param end The end of the specified portion of the array. @@ -3229,31 +3241,31 @@ interface Uint32Array { /** * Determines whether the specified callback function returns true for any element of an array. - * @param callbackfn A function that accepts up to three arguments. The some method calls the - * callbackfn function for each element in array1 until the callbackfn returns true, or until + * @param callbackfn A function that accepts up to three arguments. The some method calls the + * callbackfn function for each element in array1 until the callbackfn returns true, or until * the end of the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ some(callbackfn: (value: number, index: number, array: Uint32Array) => boolean, thisArg?: any): boolean; /** * Sorts an array. - * @param compareFn The name of the function used to determine the order of the elements. If + * @param compareFn The name of the function used to determine the order of the elements. If * omitted, the elements are sorted in ascending, ASCII character order. */ sort(compareFn?: (a: number, b: number) => number): Uint32Array; /** * Gets a new Uint32Array view of the ArrayBuffer store for this array, referencing the elements - * at begin, inclusive, up to end, exclusive. + * at begin, inclusive, up to end, exclusive. * @param begin The index of the beginning of the array. * @param end The index of the end of the array. */ subarray(begin: number, end?: number): Uint32Array; /** - * Converts a number to a string by using the current locale. + * Converts a number to a string by using the current locale. */ toLocaleString(): string; @@ -3272,7 +3284,7 @@ interface Uint32ArrayConstructor { new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Uint32Array; /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; @@ -3281,7 +3293,7 @@ interface Uint32ArrayConstructor { * @param items A set of elements to include in the new array object. */ of(...items: number[]): Uint32Array; - + /** * Creates an array from an array-like or iterable object. * @param arrayLike An array-like or iterable object to convert to an array. @@ -3298,12 +3310,12 @@ declare var Uint32Array: Uint32ArrayConstructor; */ interface Float32Array { /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; /** - * The ArrayBuffer instance referenced by the array. + * The ArrayBuffer instance referenced by the array. */ buffer: ArrayBuffer; @@ -3317,21 +3329,21 @@ interface Float32Array { */ byteOffset: number; - /** + /** * Returns the this object after copying a section of the array identified by start and end * to the same array starting at position target - * @param target If target is negative, it is treated as length+target where length is the - * length of the array. - * @param start If start is negative, it is treated as length+start. If end is negative, it + * @param target If target is negative, it is treated as length+target where length is the + * length of the array. + * @param start If start is negative, it is treated as length+start. If end is negative, it * is treated as length+end. - * @param end If not specified, length of the this object is used as its default value. + * @param end If not specified, length of the this object is used as its default value. */ copyWithin(target: number, start: number, end?: number): Float32Array; /** * Determines whether all the members of an array satisfy the specified test. - * @param callbackfn A function that accepts up to three arguments. The every method calls - * the callbackfn function for each element in array1 until the callbackfn returns false, + * @param callbackfn A function that accepts up to three arguments. The every method calls + * the callbackfn function for each element in array1 until the callbackfn returns false, * or until the end of the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. @@ -3341,49 +3353,49 @@ interface Float32Array { /** * Returns the this object after filling the section identified by start and end with value * @param value value to fill array section with - * @param start index to start filling the array at. If start is negative, it is treated as - * length+start where length is the length of the array. - * @param end index to stop filling the array at. If end is negative, it is treated as + * @param start index to start filling the array at. If start is negative, it is treated as + * length+start where length is the length of the array. + * @param end index to stop filling the array at. If end is negative, it is treated as * length+end. */ fill(value: number, start?: number, end?: number): Float32Array; /** - * Returns the elements of an array that meet the condition specified in a callback function. - * @param callbackfn A function that accepts up to three arguments. The filter method calls - * the callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * Returns the elements of an array that meet the condition specified in a callback function. + * @param callbackfn A function that accepts up to three arguments. The filter method calls + * the callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ filter(callbackfn: (value: number, index: number, array: Float32Array) => boolean, thisArg?: any): Float32Array; - /** - * Returns the value of the first element in the array where predicate is true, and undefined + /** + * Returns the value of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; - /** - * Returns the index of the first element in the array where predicate is true, and undefined + /** + * Returns the index of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ findIndex(predicate: (value: number) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. - * @param callbackfn A function that accepts up to three arguments. forEach calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. forEach calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ forEach(callbackfn: (value: number, index: number, array: Float32Array) => void, thisArg?: any): void; @@ -3398,7 +3410,7 @@ interface Float32Array { /** * Adds all the elements of an array separated by the specified separator string. - * @param separator A string used to separate one element of an array from the next in the + * @param separator A string used to separate one element of an array from the next in the * resulting String. If omitted, the array elements are separated with a comma. */ join(separator?: string): string; @@ -3406,7 +3418,7 @@ interface Float32Array { /** * Returns the index of the last occurrence of a value in an array. * @param searchElement The value to locate in the array. - * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the + * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the * search starts at index 0. */ lastIndexOf(searchElement: number, fromIndex?: number): number; @@ -3417,65 +3429,65 @@ interface Float32Array { length: number; /** - * Calls a defined callback function on each element of an array, and returns an array that + * Calls a defined callback function on each element of an array, and returns an array that * contains the results. - * @param callbackfn A function that accepts up to three arguments. The map method calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. The map method calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ map(callbackfn: (value: number, index: number, array: Float32Array) => number, thisArg?: any): Float32Array; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, initialValue?: number): number; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an argument + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float32Array) => U, initialValue: U): U; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an + * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, initialValue?: number): number; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float32Array) => U, initialValue: U): U; /** - * Reverses the elements in an Array. + * Reverses the elements in an Array. */ reverse(): Float32Array; @@ -3493,7 +3505,7 @@ interface Float32Array { */ set(array: ArrayLike, offset?: number): void; - /** + /** * Returns a section of an array. * @param start The beginning of the specified portion of the array. * @param end The end of the specified portion of the array. @@ -3502,31 +3514,31 @@ interface Float32Array { /** * Determines whether the specified callback function returns true for any element of an array. - * @param callbackfn A function that accepts up to three arguments. The some method calls the - * callbackfn function for each element in array1 until the callbackfn returns true, or until + * @param callbackfn A function that accepts up to three arguments. The some method calls the + * callbackfn function for each element in array1 until the callbackfn returns true, or until * the end of the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ some(callbackfn: (value: number, index: number, array: Float32Array) => boolean, thisArg?: any): boolean; /** * Sorts an array. - * @param compareFn The name of the function used to determine the order of the elements. If + * @param compareFn The name of the function used to determine the order of the elements. If * omitted, the elements are sorted in ascending, ASCII character order. */ sort(compareFn?: (a: number, b: number) => number): Float32Array; /** * Gets a new Float32Array view of the ArrayBuffer store for this array, referencing the elements - * at begin, inclusive, up to end, exclusive. + * at begin, inclusive, up to end, exclusive. * @param begin The index of the beginning of the array. * @param end The index of the end of the array. */ subarray(begin: number, end?: number): Float32Array; /** - * Converts a number to a string by using the current locale. + * Converts a number to a string by using the current locale. */ toLocaleString(): string; @@ -3545,7 +3557,7 @@ interface Float32ArrayConstructor { new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Float32Array; /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; @@ -3554,7 +3566,7 @@ interface Float32ArrayConstructor { * @param items A set of elements to include in the new array object. */ of(...items: number[]): Float32Array; - + /** * Creates an array from an array-like or iterable object. * @param arrayLike An array-like or iterable object to convert to an array. @@ -3567,17 +3579,17 @@ interface Float32ArrayConstructor { declare var Float32Array: Float32ArrayConstructor; /** - * A typed array of 64-bit float values. The contents are initialized to 0. If the requested + * A typed array of 64-bit float values. The contents are initialized to 0. If the requested * number of bytes could not be allocated an exception is raised. */ interface Float64Array { /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; /** - * The ArrayBuffer instance referenced by the array. + * The ArrayBuffer instance referenced by the array. */ buffer: ArrayBuffer; @@ -3591,21 +3603,21 @@ interface Float64Array { */ byteOffset: number; - /** + /** * Returns the this object after copying a section of the array identified by start and end * to the same array starting at position target - * @param target If target is negative, it is treated as length+target where length is the - * length of the array. - * @param start If start is negative, it is treated as length+start. If end is negative, it + * @param target If target is negative, it is treated as length+target where length is the + * length of the array. + * @param start If start is negative, it is treated as length+start. If end is negative, it * is treated as length+end. - * @param end If not specified, length of the this object is used as its default value. + * @param end If not specified, length of the this object is used as its default value. */ copyWithin(target: number, start: number, end?: number): Float64Array; /** * Determines whether all the members of an array satisfy the specified test. - * @param callbackfn A function that accepts up to three arguments. The every method calls - * the callbackfn function for each element in array1 until the callbackfn returns false, + * @param callbackfn A function that accepts up to three arguments. The every method calls + * the callbackfn function for each element in array1 until the callbackfn returns false, * or until the end of the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. @@ -3615,49 +3627,49 @@ interface Float64Array { /** * Returns the this object after filling the section identified by start and end with value * @param value value to fill array section with - * @param start index to start filling the array at. If start is negative, it is treated as - * length+start where length is the length of the array. - * @param end index to stop filling the array at. If end is negative, it is treated as + * @param start index to start filling the array at. If start is negative, it is treated as + * length+start where length is the length of the array. + * @param end index to stop filling the array at. If end is negative, it is treated as * length+end. */ fill(value: number, start?: number, end?: number): Float64Array; /** - * Returns the elements of an array that meet the condition specified in a callback function. - * @param callbackfn A function that accepts up to three arguments. The filter method calls - * the callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * Returns the elements of an array that meet the condition specified in a callback function. + * @param callbackfn A function that accepts up to three arguments. The filter method calls + * the callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ filter(callbackfn: (value: number, index: number, array: Float64Array) => boolean, thisArg?: any): Float64Array; - /** - * Returns the value of the first element in the array where predicate is true, and undefined + /** + * Returns the value of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number; - /** - * Returns the index of the first element in the array where predicate is true, and undefined + /** + * Returns the index of the first element in the array where predicate is true, and undefined * otherwise. - * @param predicate find calls predicate once for each element of the array, in ascending - * order, until it finds one where predicate returns true. If such an element is found, find + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find * immediately returns that element value. Otherwise, find returns undefined. - * @param thisArg If provided, it will be used as the this value for each invocation of + * @param thisArg If provided, it will be used as the this value for each invocation of * predicate. If it is not provided, undefined is used instead. */ findIndex(predicate: (value: number) => boolean, thisArg?: any): number; /** * Performs the specified action for each element in an array. - * @param callbackfn A function that accepts up to three arguments. forEach calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. forEach calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ forEach(callbackfn: (value: number, index: number, array: Float64Array) => void, thisArg?: any): void; @@ -3672,7 +3684,7 @@ interface Float64Array { /** * Adds all the elements of an array separated by the specified separator string. - * @param separator A string used to separate one element of an array from the next in the + * @param separator A string used to separate one element of an array from the next in the * resulting String. If omitted, the array elements are separated with a comma. */ join(separator?: string): string; @@ -3680,7 +3692,7 @@ interface Float64Array { /** * Returns the index of the last occurrence of a value in an array. * @param searchElement The value to locate in the array. - * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the + * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the * search starts at index 0. */ lastIndexOf(searchElement: number, fromIndex?: number): number; @@ -3691,65 +3703,65 @@ interface Float64Array { length: number; /** - * Calls a defined callback function on each element of an array, and returns an array that + * Calls a defined callback function on each element of an array, and returns an array that * contains the results. - * @param callbackfn A function that accepts up to three arguments. The map method calls the - * callbackfn function one time for each element in the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param callbackfn A function that accepts up to three arguments. The map method calls the + * callbackfn function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ map(callbackfn: (value: number, index: number, array: Float64Array) => number, thisArg?: any): Float64Array; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, initialValue?: number): number; /** - * Calls the specified callback function for all the elements in an array. The return value of - * the callback function is the accumulated result, and is provided as an argument in the next + * Calls the specified callback function for all the elements in an array. The return value of + * the callback function is the accumulated result, and is provided as an argument in the next * call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduce method calls the + * @param callbackfn A function that accepts up to four arguments. The reduce method calls the * callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an argument + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float64Array) => U, initialValue: U): U; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. - * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start - * the accumulation. The first call to the callbackfn function provides this value as an + * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start + * the accumulation. The first call to the callbackfn function provides this value as an * argument instead of an array value. */ reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, initialValue?: number): number; - /** - * Calls the specified callback function for all the elements in an array, in descending order. - * The return value of the callback function is the accumulated result, and is provided as an + /** + * Calls the specified callback function for all the elements in an array, in descending order. + * The return value of the callback function is the accumulated result, and is provided as an * argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls - * the callbackfn function one time for each element in the array. - * @param initialValue If initialValue is specified, it is used as the initial value to start + * the callbackfn function one time for each element in the array. + * @param initialValue If initialValue is specified, it is used as the initial value to start * the accumulation. The first call to the callbackfn function provides this value as an argument * instead of an array value. */ reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float64Array) => U, initialValue: U): U; /** - * Reverses the elements in an Array. + * Reverses the elements in an Array. */ reverse(): Float64Array; @@ -3767,7 +3779,7 @@ interface Float64Array { */ set(array: ArrayLike, offset?: number): void; - /** + /** * Returns a section of an array. * @param start The beginning of the specified portion of the array. * @param end The end of the specified portion of the array. @@ -3776,31 +3788,31 @@ interface Float64Array { /** * Determines whether the specified callback function returns true for any element of an array. - * @param callbackfn A function that accepts up to three arguments. The some method calls the - * callbackfn function for each element in array1 until the callbackfn returns true, or until + * @param callbackfn A function that accepts up to three arguments. The some method calls the + * callbackfn function for each element in array1 until the callbackfn returns true, or until * the end of the array. - * @param thisArg An object to which the this keyword can refer in the callbackfn function. + * @param thisArg An object to which the this keyword can refer in the callbackfn function. * If thisArg is omitted, undefined is used as the this value. */ some(callbackfn: (value: number, index: number, array: Float64Array) => boolean, thisArg?: any): boolean; /** * Sorts an array. - * @param compareFn The name of the function used to determine the order of the elements. If + * @param compareFn The name of the function used to determine the order of the elements. If * omitted, the elements are sorted in ascending, ASCII character order. */ sort(compareFn?: (a: number, b: number) => number): Float64Array; /** * Gets a new Float64Array view of the ArrayBuffer store for this array, referencing the elements - * at begin, inclusive, up to end, exclusive. + * at begin, inclusive, up to end, exclusive. * @param begin The index of the beginning of the array. * @param end The index of the end of the array. */ subarray(begin: number, end?: number): Float64Array; /** - * Converts a number to a string by using the current locale. + * Converts a number to a string by using the current locale. */ toLocaleString(): string; @@ -3819,7 +3831,7 @@ interface Float64ArrayConstructor { new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Float64Array; /** - * The size in bytes of each element in the array. + * The size in bytes of each element in the array. */ BYTES_PER_ELEMENT: number; @@ -3828,7 +3840,7 @@ interface Float64ArrayConstructor { * @param items A set of elements to include in the new array object. */ of(...items: number[]): Float64Array; - + /** * Creates an array from an array-like or iterable object. * @param arrayLike An array-like or iterable object to convert to an array. @@ -3839,7 +3851,7 @@ interface Float64ArrayConstructor { } declare var Float64Array: Float64ArrayConstructor; ///////////////////////////// -/// ECMAScript Internationalization API +/// ECMAScript Internationalization API ///////////////////////////// declare module Intl { @@ -3982,14 +3994,14 @@ interface String { interface Number { /** - * Converts a number to a string by using the current or specified locale. + * Converts a number to a string by using the current or specified locale. * @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ toLocaleString(locales?: string[], options?: Intl.NumberFormatOptions): string; /** - * Converts a number to a string by using the current or specified locale. + * Converts a number to a string by using the current or specified locale. * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ @@ -3998,41 +4010,41 @@ interface Number { interface Date { /** - * Converts a date and time to a string by using the current or specified locale. + * Converts a date and time to a string by using the current or specified locale. * @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ toLocaleString(locales?: string[], options?: Intl.DateTimeFormatOptions): string; /** - * Converts a date to a string by using the current or specified locale. + * Converts a date to a string by using the current or specified locale. * @param locales An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ toLocaleDateString(locales?: string[], options?: Intl.DateTimeFormatOptions): string; /** - * Converts a time to a string by using the current or specified locale. + * Converts a time to a string by using the current or specified locale. * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ toLocaleTimeString(locale?: string[], options?: Intl.DateTimeFormatOptions): string; - + /** - * Converts a date and time to a string by using the current or specified locale. + * Converts a date and time to a string by using the current or specified locale. * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ toLocaleString(locale?: string, options?: Intl.DateTimeFormatOptions): string; - + /** - * Converts a date to a string by using the current or specified locale. + * Converts a date to a string by using the current or specified locale. * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ toLocaleDateString(locale?: string, options?: Intl.DateTimeFormatOptions): string; /** - * Converts a time to a string by using the current or specified locale. + * Converts a time to a string by using the current or specified locale. * @param locale Locale tag. If you omit this parameter, the default locale of the JavaScript runtime is used. * @param options An object that contains one or more properties that specify comparison options. */ @@ -5636,7 +5648,7 @@ declare var DeviceRotationRate: { interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEvent { /** - * Sets or gets the URL for the current document. + * Sets or gets the URL for the current document. */ URL: string; /** @@ -5664,7 +5676,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ applets: HTMLCollection; /** - * Deprecated. Sets or retrieves a value that indicates the background color behind the object. + * Deprecated. Sets or retrieves a value that indicates the background color behind the object. */ bgColor: string; /** @@ -5691,19 +5703,19 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ designMode: string; /** - * Sets or retrieves a value that indicates the reading order of the object. + * Sets or retrieves a value that indicates the reading order of the object. */ dir: string; /** - * Gets an object representing the document type declaration associated with the current document. + * Gets an object representing the document type declaration associated with the current document. */ doctype: DocumentType; /** - * Gets a reference to the root node of the document. + * Gets a reference to the root node of the document. */ documentElement: HTMLElement; /** - * Sets or gets the security domain of the document. + * Sets or gets the security domain of the document. */ domain: string; /** @@ -5727,7 +5739,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ images: HTMLCollection; /** - * Gets the implementation object of the current document. + * Gets the implementation object of the current document. */ implementation: DOMImplementation; /** @@ -5735,11 +5747,11 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ inputEncoding: string; /** - * Gets the date that the page was last modified, if the page supplies one. + * Gets the date that the page was last modified, if the page supplies one. */ lastModified: string; /** - * Sets or gets the color of the document links. + * Sets or gets the color of the document links. */ linkColor: string; /** @@ -5747,7 +5759,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ links: HTMLCollection; /** - * Contains information about the current URL. + * Contains information about the current URL. */ location: Location; media: string; @@ -5775,19 +5787,19 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven * @param ev The event. */ onbeforedeactivate: (ev: UIEvent) => any; - /** - * Fires when the object loses the input focus. + /** + * Fires when the object loses the input focus. * @param ev The focus event. */ onblur: (ev: FocusEvent) => any; /** - * Occurs when playback is possible, but would require further buffering. + * Occurs when playback is possible, but would require further buffering. * @param ev The event. */ oncanplay: (ev: Event) => any; oncanplaythrough: (ev: Event) => any; /** - * Fires when the contents of the object or selection have changed. + * Fires when the contents of the object or selection have changed. * @param ev The event. */ onchange: (ev: Event) => any; @@ -5797,7 +5809,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ onclick: (ev: MouseEvent) => any; /** - * Fires when the user clicks the right mouse button in the client area, opening the context menu. + * Fires when the user clicks the right mouse button in the client area, opening the context menu. * @param ev The mouse event. */ oncontextmenu: (ev: PointerEvent) => any; @@ -5821,12 +5833,12 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven * @param ev The event. */ ondragend: (ev: DragEvent) => any; - /** + /** * Fires on the target element when the user drags the object to a valid drop target. * @param ev The drag event. */ ondragenter: (ev: DragEvent) => any; - /** + /** * Fires on the target object when the user moves the mouse out of a valid drop target during a drag operation. * @param ev The drag event. */ @@ -5837,23 +5849,23 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ ondragover: (ev: DragEvent) => any; /** - * Fires on the source object when the user starts to drag a text selection or selected object. + * Fires on the source object when the user starts to drag a text selection or selected object. * @param ev The event. */ ondragstart: (ev: DragEvent) => any; ondrop: (ev: DragEvent) => any; /** - * Occurs when the duration attribute is updated. + * Occurs when the duration attribute is updated. * @param ev The event. */ ondurationchange: (ev: Event) => any; /** - * Occurs when the media element is reset to its initial state. + * Occurs when the media element is reset to its initial state. * @param ev The event. */ onemptied: (ev: Event) => any; /** - * Occurs when the end of playback is reached. + * Occurs when the end of playback is reached. * @param ev The event */ onended: (ev: Event) => any; @@ -5863,7 +5875,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ onerror: (ev: Event) => any; /** - * Fires when the object receives focus. + * Fires when the object receives focus. * @param ev The event. */ onfocus: (ev: FocusEvent) => any; @@ -5886,12 +5898,12 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ onkeyup: (ev: KeyboardEvent) => any; /** - * Fires immediately after the browser loads the object. + * Fires immediately after the browser loads the object. * @param ev The event. */ onload: (ev: Event) => any; /** - * Occurs when media data is loaded at the current playback position. + * Occurs when media data is loaded at the current playback position. * @param ev The event. */ onloadeddata: (ev: Event) => any; @@ -5901,22 +5913,22 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ onloadedmetadata: (ev: Event) => any; /** - * Occurs when Internet Explorer begins looking for media data. + * Occurs when Internet Explorer begins looking for media data. * @param ev The event. */ onloadstart: (ev: Event) => any; /** - * Fires when the user clicks the object with either mouse button. + * Fires when the user clicks the object with either mouse button. * @param ev The mouse event. */ onmousedown: (ev: MouseEvent) => any; /** - * Fires when the user moves the mouse over the object. + * Fires when the user moves the mouse over the object. * @param ev The mouse event. */ onmousemove: (ev: MouseEvent) => any; /** - * Fires when the user moves the mouse pointer outside the boundaries of the object. + * Fires when the user moves the mouse pointer outside the boundaries of the object. * @param ev The mouse event. */ onmouseout: (ev: MouseEvent) => any; @@ -5926,12 +5938,12 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ onmouseover: (ev: MouseEvent) => any; /** - * Fires when the user releases a mouse button while the mouse is over the object. + * Fires when the user releases a mouse button while the mouse is over the object. * @param ev The mouse event. */ onmouseup: (ev: MouseEvent) => any; /** - * Fires when the wheel button is rotated. + * Fires when the wheel button is rotated. * @param ev The mouse event */ onmousewheel: (ev: MouseWheelEvent) => any; @@ -5953,7 +5965,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven onmspointerover: (ev: MSPointerEvent) => any; onmspointerup: (ev: MSPointerEvent) => any; /** - * Occurs when an item is removed from a Jump List of a webpage running in Site Mode. + * Occurs when an item is removed from a Jump List of a webpage running in Site Mode. * @param ev The event. */ onmssitemodejumplistitemremoved: (ev: MSSiteModeEvent) => any; @@ -5968,24 +5980,24 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ onpause: (ev: Event) => any; /** - * Occurs when the play method is requested. + * Occurs when the play method is requested. * @param ev The event. */ onplay: (ev: Event) => any; /** - * Occurs when the audio or video has started playing. + * Occurs when the audio or video has started playing. * @param ev The event. */ onplaying: (ev: Event) => any; onpointerlockchange: (ev: Event) => any; onpointerlockerror: (ev: Event) => any; /** - * Occurs to indicate progress while downloading media data. + * Occurs to indicate progress while downloading media data. * @param ev The event. */ onprogress: (ev: ProgressEvent) => any; /** - * Occurs when the playback rate is increased or decreased. + * Occurs when the playback rate is increased or decreased. * @param ev The event. */ onratechange: (ev: Event) => any; @@ -5995,22 +6007,22 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ onreadystatechange: (ev: ProgressEvent) => any; /** - * Fires when the user resets a form. + * Fires when the user resets a form. * @param ev The event. */ onreset: (ev: Event) => any; /** - * Fires when the user repositions the scroll box in the scroll bar on the object. + * Fires when the user repositions the scroll box in the scroll bar on the object. * @param ev The event. */ onscroll: (ev: UIEvent) => any; /** - * Occurs when the seek operation ends. + * Occurs when the seek operation ends. * @param ev The event. */ onseeked: (ev: Event) => any; /** - * Occurs when the current playback position is moved. + * Occurs when the current playback position is moved. * @param ev The event. */ onseeking: (ev: Event) => any; @@ -6021,7 +6033,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven onselect: (ev: UIEvent) => any; onselectstart: (ev: Event) => any; /** - * Occurs when the download has stopped. + * Occurs when the download has stopped. * @param ev The event. */ onstalled: (ev: Event) => any; @@ -6032,7 +6044,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven onstop: (ev: Event) => any; onsubmit: (ev: Event) => any; /** - * Occurs if the load operation has been intentionally halted. + * Occurs if the load operation has been intentionally halted. * @param ev The event. */ onsuspend: (ev: Event) => any; @@ -6051,7 +6063,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ onvolumechange: (ev: Event) => any; /** - * Occurs when playback stops because the next frame of a video resource is not available. + * Occurs when playback stops because the next frame of a video resource is not available. * @param ev The event. */ onwaiting: (ev: Event) => any; @@ -6085,7 +6097,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ title: string; visibilityState: string; - /** + /** * Sets or gets the color of the links that the user has visited. */ vlinkColor: string; @@ -6300,7 +6312,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven createExpression(expression: string, resolver: XPathNSResolver): XPathExpression; createNSResolver(nodeResolver: Node): XPathNSResolver; /** - * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document. + * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document. * @param root The root element or node to start traversing on. * @param whatToShow The type of nodes or elements to appear in the node list * @param filter A custom NodeFilter function to use. For more information, see filter. Use null for no filter. @@ -6309,11 +6321,11 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven createNodeIterator(root: Node, whatToShow?: number, filter?: NodeFilter, entityReferenceExpansion?: boolean): NodeIterator; createProcessingInstruction(target: string, data: string): ProcessingInstruction; /** - * Returns an empty range object that has both of its boundary points positioned at the beginning of the document. + * Returns an empty range object that has both of its boundary points positioned at the beginning of the document. */ createRange(): Range; /** - * Creates a text string from the specified value. + * Creates a text string from the specified value. * @param data String that specifies the nodeValue property of the text node. */ createTextNode(data: string): Text; @@ -6328,7 +6340,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ createTreeWalker(root: Node, whatToShow?: number, filter?: NodeFilter, entityReferenceExpansion?: boolean): TreeWalker; /** - * Returns the element for the specified x coordinate and the specified y coordinate. + * Returns the element for the specified x coordinate and the specified y coordinate. * @param x The x-offset * @param y The y-offset */ @@ -6561,7 +6573,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven * @param replace Specifies whether the existing entry for the document is replaced in the history list. */ open(url?: string, name?: string, features?: string, replace?: boolean): Document; - /** + /** * Returns a Boolean value that indicates whether a specified command can be successfully executed using execCommand, given the current state of the document. * @param commandId Specifies a command identifier. */ @@ -6583,7 +6595,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven queryCommandSupported(commandId: string): boolean; /** * Retrieves the string associated with a command. - * @param commandId String that contains the identifier of a command. This can be any command identifier given in the list of Command Identifiers. + * @param commandId String that contains the identifier of a command. This can be any command identifier given in the list of Command Identifiers. */ queryCommandText(commandId: string): string; /** @@ -6599,12 +6611,12 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven webkitCancelFullScreen(): void; webkitExitFullscreen(): void; /** - * Writes one or more HTML expressions to a document in the specified window. + * Writes one or more HTML expressions to a document in the specified window. * @param content Specifies the text and HTML tags to write. */ write(...content: string[]): void; /** - * Writes one or more HTML expressions, followed by a carriage return, to a document in the specified window. + * Writes one or more HTML expressions, followed by a carriage return, to a document in the specified window. * @param content The text and HTML tags to write. */ writeln(...content: string[]): void; @@ -7312,12 +7324,12 @@ interface HTMLAnchorElement extends HTMLElement { */ target: string; /** - * Retrieves or sets the text of the object as a string. + * Retrieves or sets the text of the object as a string. */ text: string; type: string; urn: string; - /** + /** * Returns a string representation of an object. */ toString(): string; @@ -7418,7 +7430,7 @@ interface HTMLAreaElement extends HTMLElement { */ host: string; /** - * Sets or retrieves the host name part of the location or URL. + * Sets or retrieves the host name part of the location or URL. */ hostname: string; /** @@ -7454,7 +7466,7 @@ interface HTMLAreaElement extends HTMLElement { * Sets or retrieves the window or frame at which to target content. */ target: string; - /** + /** * Returns a string representation of an object. */ toString(): string; @@ -7737,7 +7749,7 @@ interface HTMLButtonElement extends HTMLElement { * Overrides the target attribute on a form element. */ formTarget: string; - /** + /** * Sets or retrieves the name of the object. */ name: string; @@ -7754,7 +7766,7 @@ interface HTMLButtonElement extends HTMLElement { * Returns a ValidityState object that represents the validity states of an element. */ validity: ValidityState; - /** + /** * Sets or retrieves the default or selected value of the control. */ value: string; @@ -7888,7 +7900,7 @@ declare var HTMLDirectoryElement: { interface HTMLDivElement extends HTMLElement { /** - * Sets or retrieves how the object is aligned with adjacent text. + * Sets or retrieves how the object is aligned with adjacent text. */ align: string; /** @@ -9034,7 +9046,7 @@ interface HTMLInputElement extends HTMLElement { */ files: FileList; /** - * Retrieves a reference to the form that the object is embedded in. + * Retrieves a reference to the form that the object is embedded in. */ form: HTMLFormElement; /** @@ -9204,7 +9216,7 @@ interface HTMLIsIndexElement extends HTMLElement { */ action: string; /** - * Retrieves a reference to the form that the object is embedded in. + * Retrieves a reference to the form that the object is embedded in. */ form: HTMLFormElement; prompt: string; @@ -9763,7 +9775,7 @@ interface HTMLMetaElement extends HTMLElement { */ scheme: string; /** - * Sets or retrieves the URL property that will be loaded after the specified time has elapsed. + * Sets or retrieves the URL property that will be loaded after the specified time has elapsed. */ url: string; } @@ -10009,7 +10021,7 @@ declare var HTMLOptionElement: { interface HTMLParagraphElement extends HTMLElement { /** - * Sets or retrieves how the object is aligned with adjacent text. + * Sets or retrieves how the object is aligned with adjacent text. */ align: string; clear: string; @@ -10128,10 +10140,10 @@ interface HTMLScriptElement extends HTMLElement { */ defer: boolean; /** - * Sets or retrieves the event for which the script is written. + * Sets or retrieves the event for which the script is written. */ event: string; - /** + /** * Sets or retrieves the object that is bound to the event script. */ htmlFor: string; @@ -10140,7 +10152,7 @@ interface HTMLScriptElement extends HTMLElement { */ src: string; /** - * Retrieves or sets the text of the object as a string. + * Retrieves or sets the text of the object as a string. */ text: string; /** @@ -10161,7 +10173,7 @@ interface HTMLSelectElement extends HTMLElement { autofocus: boolean; disabled: boolean; /** - * Retrieves a reference to the form that the object is embedded in. + * Retrieves a reference to the form that the object is embedded in. */ form: HTMLFormElement; /** @@ -10186,7 +10198,7 @@ interface HTMLSelectElement extends HTMLElement { */ selectedIndex: number; /** - * Sets or retrieves the number of rows in the list box. + * Sets or retrieves the number of rows in the list box. */ size: number; /** @@ -10212,7 +10224,7 @@ interface HTMLSelectElement extends HTMLElement { /** * Adds an element to the areas, controlRange, or options collection. * @param element Variant of type Number that specifies the index position in the collection where the element is placed. If no value is given, the method places the element at the end of the collection. - * @param before Variant of type Object that specifies an element to insert before, or null to append the object to the collection. + * @param before Variant of type Object that specifies an element to insert before, or null to append the object to the collection. */ add(element: HTMLElement, before?: HTMLElement | number): void; /** @@ -10404,7 +10416,7 @@ interface HTMLTableElement extends HTMLElement { */ border: string; /** - * Sets or retrieves the border color of the object. + * Sets or retrieves the border color of the object. */ borderColor: any; /** @@ -10693,7 +10705,7 @@ declare var HTMLTextAreaElement: { interface HTMLTitleElement extends HTMLElement { /** - * Retrieves or sets the text of the object as a string. + * Retrieves or sets the text of the object as a string. */ text: string; } @@ -16980,9 +16992,9 @@ declare function addEventListener(type: "waiting", listener: (ev: Event) => any, declare function addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void; declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; ///////////////////////////// -/// WorkerGlobalScope APIs +/// WorkerGlobalScope APIs ///////////////////////////// -// These are only available in a Web Worker +// These are only available in a Web Worker declare function importScripts(...urls: string[]): void; @@ -17015,7 +17027,7 @@ interface TextStreamBase { /** * Closes a text stream. - * It is not necessary to close standard streams; they close automatically when the process ends. If + * It is not necessary to close standard streams; they close automatically when the process ends. If * you close a standard stream, be aware that any other pointers to that standard stream become invalid. */ Close(): void; From 0fe0ff79436201727fce6b47ccb923d21d145ad8 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Mon, 13 Nov 2017 10:55:33 -0800 Subject: [PATCH 137/138] Add test --- .../reference/tsxFragmentChildrenCheck.js | 68 +++++++++++++++++++ .../tsxFragmentChildrenCheck.symbols | 58 ++++++++++++++++ .../reference/tsxFragmentChildrenCheck.types | 68 +++++++++++++++++++ .../compiler/tsxFragmentChildrenCheck.ts | 34 ++++++++++ 4 files changed, 228 insertions(+) create mode 100644 tests/baselines/reference/tsxFragmentChildrenCheck.js create mode 100644 tests/baselines/reference/tsxFragmentChildrenCheck.symbols create mode 100644 tests/baselines/reference/tsxFragmentChildrenCheck.types create mode 100644 tests/cases/compiler/tsxFragmentChildrenCheck.ts diff --git a/tests/baselines/reference/tsxFragmentChildrenCheck.js b/tests/baselines/reference/tsxFragmentChildrenCheck.js new file mode 100644 index 00000000000..bca4527cffe --- /dev/null +++ b/tests/baselines/reference/tsxFragmentChildrenCheck.js @@ -0,0 +1,68 @@ +//// [tests/cases/compiler/tsxFragmentChildrenCheck.ts] //// + +//// [my-component.tsx] +declare var React: any; + +export function MyComponent(props: any) { + return my component; +} + +//// [file1.tsx] +import * as React from 'react' +import { MyComponent } from './my-component' + +const MY_STRING: string = 'Ceci n\'est pas une string.' +const MY_CLASSNAME: string = 'jeclass' + +class RenderString extends React.PureComponent { + render() { + return ( + <> + + { MY_STRING } + + + ) + } +} + +export default RenderString + +//// [my-component.js] +"use strict"; +exports.__esModule = true; +function MyComponent(props) { + return React.createElement("span", null, "my component"); +} +exports.MyComponent = MyComponent; +//// [file1.js] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +var React = require("react"); +var my_component_1 = require("./my-component"); +var MY_STRING = 'Ceci n\'est pas une string.'; +var MY_CLASSNAME = 'jeclass'; +var RenderString = /** @class */ (function (_super) { + __extends(RenderString, _super); + function RenderString() { + return _super !== null && _super.apply(this, arguments) || this; + } + RenderString.prototype.render = function () { + return (React.createElement(React.Fragment, null, + React.createElement(my_component_1.MyComponent, null), + React.createElement("span", null, MY_STRING), + React.createElement("span", { className: MY_CLASSNAME }))); + }; + return RenderString; +}(React.PureComponent)); +exports["default"] = RenderString; diff --git a/tests/baselines/reference/tsxFragmentChildrenCheck.symbols b/tests/baselines/reference/tsxFragmentChildrenCheck.symbols new file mode 100644 index 00000000000..cb00046a233 --- /dev/null +++ b/tests/baselines/reference/tsxFragmentChildrenCheck.symbols @@ -0,0 +1,58 @@ +=== tests/cases/compiler/my-component.tsx === +declare var React: any; +>React : Symbol(React, Decl(my-component.tsx, 0, 11)) + +export function MyComponent(props: any) { +>MyComponent : Symbol(MyComponent, Decl(my-component.tsx, 0, 23)) +>props : Symbol(props, Decl(my-component.tsx, 2, 28)) + + return my component; +>span : Symbol(JSX.IntrinsicElements.span, Decl(react.d.ts, 2461, 51)) +>span : Symbol(JSX.IntrinsicElements.span, Decl(react.d.ts, 2461, 51)) +} + +=== tests/cases/compiler/file1.tsx === +import * as React from 'react' +>React : Symbol(React, Decl(file1.tsx, 0, 6)) + +import { MyComponent } from './my-component' +>MyComponent : Symbol(MyComponent, Decl(file1.tsx, 1, 8)) + +const MY_STRING: string = 'Ceci n\'est pas une string.' +>MY_STRING : Symbol(MY_STRING, Decl(file1.tsx, 3, 5)) + +const MY_CLASSNAME: string = 'jeclass' +>MY_CLASSNAME : Symbol(MY_CLASSNAME, Decl(file1.tsx, 4, 5)) + +class RenderString extends React.PureComponent { +>RenderString : Symbol(RenderString, Decl(file1.tsx, 4, 38)) +>React.PureComponent : Symbol(React.PureComponent, Decl(react.d.ts, 180, 5)) +>React : Symbol(React, Decl(file1.tsx, 0, 6)) +>PureComponent : Symbol(React.PureComponent, Decl(react.d.ts, 180, 5)) + + render() { +>render : Symbol(RenderString.render, Decl(file1.tsx, 6, 58)) + + return ( + <> + +>MyComponent : Symbol(MyComponent, Decl(file1.tsx, 1, 8)) + + { MY_STRING } +>span : Symbol(JSX.IntrinsicElements.span, Decl(react.d.ts, 2461, 51)) +>MY_STRING : Symbol(MY_STRING, Decl(file1.tsx, 3, 5)) +>span : Symbol(JSX.IntrinsicElements.span, Decl(react.d.ts, 2461, 51)) + + +>span : Symbol(JSX.IntrinsicElements.span, Decl(react.d.ts, 2461, 51)) +>className : Symbol(className, Decl(file1.tsx, 12, 13)) +>MY_CLASSNAME : Symbol(MY_CLASSNAME, Decl(file1.tsx, 4, 5)) + + + ) + } +} + +export default RenderString +>RenderString : Symbol(RenderString, Decl(file1.tsx, 4, 38)) + diff --git a/tests/baselines/reference/tsxFragmentChildrenCheck.types b/tests/baselines/reference/tsxFragmentChildrenCheck.types new file mode 100644 index 00000000000..c746b4012fb --- /dev/null +++ b/tests/baselines/reference/tsxFragmentChildrenCheck.types @@ -0,0 +1,68 @@ +=== tests/cases/compiler/my-component.tsx === +declare var React: any; +>React : any + +export function MyComponent(props: any) { +>MyComponent : (props: any) => JSX.Element +>props : any + + return my component; +>my component : JSX.Element +>span : any +>span : any +} + +=== tests/cases/compiler/file1.tsx === +import * as React from 'react' +>React : typeof React + +import { MyComponent } from './my-component' +>MyComponent : (props: any) => JSX.Element + +const MY_STRING: string = 'Ceci n\'est pas une string.' +>MY_STRING : string +>'Ceci n\'est pas une string.' : "Ceci n'est pas une string." + +const MY_CLASSNAME: string = 'jeclass' +>MY_CLASSNAME : string +>'jeclass' : "jeclass" + +class RenderString extends React.PureComponent { +>RenderString : RenderString +>React.PureComponent : React.PureComponent +>React : typeof React +>PureComponent : typeof React.PureComponent + + render() { +>render : () => JSX.Element + + return ( +>( <> { MY_STRING } ) : JSX.Element + + <> +><> { MY_STRING } : JSX.Element + + +> : JSX.Element +>MyComponent : (props: any) => JSX.Element + + { MY_STRING } +>{ MY_STRING } : JSX.Element +>span : any +>MY_STRING : string +>span : any + + +> : JSX.Element +>span : any +>className : string +>MY_CLASSNAME : string + + + ) + } +} + +export default RenderString +>RenderString : RenderString + diff --git a/tests/cases/compiler/tsxFragmentChildrenCheck.ts b/tests/cases/compiler/tsxFragmentChildrenCheck.ts new file mode 100644 index 00000000000..f49835404b4 --- /dev/null +++ b/tests/cases/compiler/tsxFragmentChildrenCheck.ts @@ -0,0 +1,34 @@ +// @jsx: react +// @noUnusedLocals: true +// @noLib: true +// @skipLibCheck: true +// @libFiles: react.d.ts,lib.d.ts + +// @Filename: my-component.tsx +declare var React: any; + +export function MyComponent(props: any) { + return my component; +} + +// @Filename: file1.tsx + +import * as React from 'react' +import { MyComponent } from './my-component' + +const MY_STRING: string = 'Ceci n\'est pas une string.' +const MY_CLASSNAME: string = 'jeclass' + +class RenderString extends React.PureComponent { + render() { + return ( + <> + + { MY_STRING } + + + ) + } +} + +export default RenderString \ No newline at end of file From 4c26426a6931a96d7b311d2c9310d4192ac11842 Mon Sep 17 00:00:00 2001 From: uniqueiniquity Date: Mon, 13 Nov 2017 11:06:05 -0800 Subject: [PATCH 138/138] Update baseline --- tests/baselines/reference/jsxFactoryAndFragment.errors.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/baselines/reference/jsxFactoryAndFragment.errors.txt b/tests/baselines/reference/jsxFactoryAndFragment.errors.txt index d5dcffb152a..bec2ea5cc0f 100644 --- a/tests/baselines/reference/jsxFactoryAndFragment.errors.txt +++ b/tests/baselines/reference/jsxFactoryAndFragment.errors.txt @@ -1,8 +1,9 @@ tests/cases/compiler/jsxFactoryAndFragment.tsx(3,1): error TS17016: JSX fragment is not supported when using --jsxFactory tests/cases/compiler/jsxFactoryAndFragment.tsx(4,1): error TS17016: JSX fragment is not supported when using --jsxFactory +tests/cases/compiler/jsxFactoryAndFragment.tsx(4,17): error TS17016: JSX fragment is not supported when using --jsxFactory -==== tests/cases/compiler/jsxFactoryAndFragment.tsx (2 errors) ==== +==== tests/cases/compiler/jsxFactoryAndFragment.tsx (3 errors) ==== declare var h: any; <>; @@ -10,4 +11,6 @@ tests/cases/compiler/jsxFactoryAndFragment.tsx(4,1): error TS17016: JSX fragment !!! error TS17016: JSX fragment is not supported when using --jsxFactory <>1<>2.12.2; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS17016: JSX fragment is not supported when using --jsxFactory + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS17016: JSX fragment is not supported when using --jsxFactory \ No newline at end of file