From 8890dcb7ca81857678b110a1586f3642d1447ee2 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Wed, 26 Aug 2020 19:38:07 -0400 Subject: [PATCH 1/7] Cherry-pick PR #40118 into release-4.0 (#40134) Component commits: e1f4f9cfc8 Fix tuple name homogeneity check Co-authored-by: Wesley Wigham --- src/compiler/checker.ts | 7 ++-- .../namedTupleMembersErrors.errors.txt | 34 +++++++++++++------ .../reference/namedTupleMembersErrors.js | 6 ++++ .../reference/namedTupleMembersErrors.symbols | 31 +++++++++++------ .../reference/namedTupleMembersErrors.types | 9 +++++ .../tuple/named/namedTupleMembersErrors.ts | 3 ++ 6 files changed, 63 insertions(+), 27 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 43e9b4e5a67e0..78cbe465e0d45 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31041,13 +31041,10 @@ namespace ts { function checkTupleType(node: TupleTypeNode) { const elementTypes = node.elements; let seenOptionalElement = false; - let seenNamedElement = false; + const hasNamedElement = some(elementTypes, isNamedTupleMember); for (let i = 0; i < elementTypes.length; i++) { const e = elementTypes[i]; - if (e.kind === SyntaxKind.NamedTupleMember) { - seenNamedElement = true; - } - else if (seenNamedElement) { + if (e.kind !== SyntaxKind.NamedTupleMember && hasNamedElement) { grammarErrorOnNode(e, Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names); break; } diff --git a/tests/baselines/reference/namedTupleMembersErrors.errors.txt b/tests/baselines/reference/namedTupleMembersErrors.errors.txt index af37194d193c7..4f971f984a44a 100644 --- a/tests/baselines/reference/namedTupleMembersErrors.errors.txt +++ b/tests/baselines/reference/namedTupleMembersErrors.errors.txt @@ -1,28 +1,40 @@ tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(1,41): error TS5084: Tuple members must all have names or all not have names. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(3,32): error TS5084: Tuple members must all have names or all not have names. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(5,32): error TS5084: Tuple members must all have names or all not have names. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(7,29): error TS5086: A labeled tuple element is declared as optional with a question mark after the name and before the colon, rather than after the type. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(9,46): error TS5087: A labeled tuple element is declared as rest with a `...` before the name, rather than before the type. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(11,49): error TS5087: A labeled tuple element is declared as rest with a `...` before the name, rather than before the type. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(11,52): error TS8020: JSDoc types can only be used inside documentation comments. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(13,39): error TS5085: A tuple member cannot be both optional and rest. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(15,44): error TS2574: A rest element type must be an array type. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(17,13): error TS2456: Type alias 'RecusiveRestUnlabeled' circularly references itself. -tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(18,13): error TS2456: Type alias 'RecusiveRest' circularly references itself. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(2,25): error TS5084: Tuple members must all have names or all not have names. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(4,32): error TS5084: Tuple members must all have names or all not have names. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(5,22): error TS5084: Tuple members must all have names or all not have names. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(7,32): error TS5084: Tuple members must all have names or all not have names. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(8,22): error TS5084: Tuple members must all have names or all not have names. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(10,29): error TS5086: A labeled tuple element is declared as optional with a question mark after the name and before the colon, rather than after the type. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(12,46): error TS5087: A labeled tuple element is declared as rest with a `...` before the name, rather than before the type. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(14,49): error TS5087: A labeled tuple element is declared as rest with a `...` before the name, rather than before the type. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(14,52): error TS8020: JSDoc types can only be used inside documentation comments. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(16,39): error TS5085: A tuple member cannot be both optional and rest. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(18,44): error TS2574: A rest element type must be an array type. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(20,13): error TS2456: Type alias 'RecusiveRestUnlabeled' circularly references itself. +tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts(21,13): error TS2456: Type alias 'RecusiveRest' circularly references itself. -==== tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts (11 errors) ==== +==== tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts (14 errors) ==== export type Segment1 = [length: number, number]; // partially named, disallowed ~~~~~~ !!! error TS5084: Tuple members must all have names or all not have names. + export type Segment2 = [number, size: number]; // partially named, disallowed + ~~~~~~ +!!! error TS5084: Tuple members must all have names or all not have names. export type List = [item: any, ...any]; // partially named, disallowed ~~~~~~ !!! error TS5084: Tuple members must all have names or all not have names. + export type List2 = [any, ...remainder: any]; // partially named, disallowed + ~~~ +!!! error TS5084: Tuple members must all have names or all not have names. export type Pair = [item: any, any?]; // partially named, disallowed ~~~~ !!! error TS5084: Tuple members must all have names or all not have names. + export type Pair2 = [any, last?: any]; // partially named, disallowed + ~~~ +!!! error TS5084: Tuple members must all have names or all not have names. export type Opt = [element: string?]; // question mark on element disallowed ~~~~~~~ diff --git a/tests/baselines/reference/namedTupleMembersErrors.js b/tests/baselines/reference/namedTupleMembersErrors.js index 5b277b3efe05c..a436e61cd0ca1 100644 --- a/tests/baselines/reference/namedTupleMembersErrors.js +++ b/tests/baselines/reference/namedTupleMembersErrors.js @@ -1,9 +1,12 @@ //// [namedTupleMembersErrors.ts] export type Segment1 = [length: number, number]; // partially named, disallowed +export type Segment2 = [number, size: number]; // partially named, disallowed export type List = [item: any, ...any]; // partially named, disallowed +export type List2 = [any, ...remainder: any]; // partially named, disallowed export type Pair = [item: any, any?]; // partially named, disallowed +export type Pair2 = [any, last?: any]; // partially named, disallowed export type Opt = [element: string?]; // question mark on element disallowed @@ -26,8 +29,11 @@ exports.__esModule = true; //// [namedTupleMembersErrors.d.ts] export declare type Segment1 = [length: number, number]; +export declare type Segment2 = [number, size: number]; export declare type List = [item: any, ...any]; +export declare type List2 = [any, ...remainder: any]; export declare type Pair = [item: any, any?]; +export declare type Pair2 = [any, last?: any]; export declare type Opt = [element: string?]; export declare type Trailing = [first: string, rest: ...string[]]; export declare type OptTrailing = [first: string, rest: ...?string[]]; diff --git a/tests/baselines/reference/namedTupleMembersErrors.symbols b/tests/baselines/reference/namedTupleMembersErrors.symbols index 613bf86cddd0e..6040512d2da27 100644 --- a/tests/baselines/reference/namedTupleMembersErrors.symbols +++ b/tests/baselines/reference/namedTupleMembersErrors.symbols @@ -2,32 +2,41 @@ export type Segment1 = [length: number, number]; // partially named, disallowed >Segment1 : Symbol(Segment1, Decl(namedTupleMembersErrors.ts, 0, 0)) +export type Segment2 = [number, size: number]; // partially named, disallowed +>Segment2 : Symbol(Segment2, Decl(namedTupleMembersErrors.ts, 0, 48)) + export type List = [item: any, ...any]; // partially named, disallowed ->List : Symbol(List, Decl(namedTupleMembersErrors.ts, 0, 48)) +>List : Symbol(List, Decl(namedTupleMembersErrors.ts, 1, 46)) + +export type List2 = [any, ...remainder: any]; // partially named, disallowed +>List2 : Symbol(List2, Decl(namedTupleMembersErrors.ts, 3, 39)) export type Pair = [item: any, any?]; // partially named, disallowed ->Pair : Symbol(Pair, Decl(namedTupleMembersErrors.ts, 2, 39)) +>Pair : Symbol(Pair, Decl(namedTupleMembersErrors.ts, 4, 45)) + +export type Pair2 = [any, last?: any]; // partially named, disallowed +>Pair2 : Symbol(Pair2, Decl(namedTupleMembersErrors.ts, 6, 37)) export type Opt = [element: string?]; // question mark on element disallowed ->Opt : Symbol(Opt, Decl(namedTupleMembersErrors.ts, 4, 37)) +>Opt : Symbol(Opt, Decl(namedTupleMembersErrors.ts, 7, 38)) export type Trailing = [first: string, rest: ...string[]]; // dots on element disallowed ->Trailing : Symbol(Trailing, Decl(namedTupleMembersErrors.ts, 6, 37)) +>Trailing : Symbol(Trailing, Decl(namedTupleMembersErrors.ts, 9, 37)) export type OptTrailing = [first: string, rest: ...string[]?]; // dots+question on element disallowed ->OptTrailing : Symbol(OptTrailing, Decl(namedTupleMembersErrors.ts, 8, 58)) +>OptTrailing : Symbol(OptTrailing, Decl(namedTupleMembersErrors.ts, 11, 58)) export type OptRest = [first: string, ...rest?: string[]]; // rest+optional disallowed ->OptRest : Symbol(OptRest, Decl(namedTupleMembersErrors.ts, 10, 62)) +>OptRest : Symbol(OptRest, Decl(namedTupleMembersErrors.ts, 13, 62)) export type NonArrayRest = [first: string, ...rest: number]; // non-arraylike rest, disallowed ->NonArrayRest : Symbol(NonArrayRest, Decl(namedTupleMembersErrors.ts, 12, 58)) +>NonArrayRest : Symbol(NonArrayRest, Decl(namedTupleMembersErrors.ts, 15, 58)) export type RecusiveRestUnlabeled = [string, ...RecusiveRestUnlabeled]; ->RecusiveRestUnlabeled : Symbol(RecusiveRestUnlabeled, Decl(namedTupleMembersErrors.ts, 14, 60)) ->RecusiveRestUnlabeled : Symbol(RecusiveRestUnlabeled, Decl(namedTupleMembersErrors.ts, 14, 60)) +>RecusiveRestUnlabeled : Symbol(RecusiveRestUnlabeled, Decl(namedTupleMembersErrors.ts, 17, 60)) +>RecusiveRestUnlabeled : Symbol(RecusiveRestUnlabeled, Decl(namedTupleMembersErrors.ts, 17, 60)) export type RecusiveRest = [first: string, ...rest: RecusiveRest]; // marked as incorrect, same as above ->RecusiveRest : Symbol(RecusiveRest, Decl(namedTupleMembersErrors.ts, 16, 71)) ->RecusiveRest : Symbol(RecusiveRest, Decl(namedTupleMembersErrors.ts, 16, 71)) +>RecusiveRest : Symbol(RecusiveRest, Decl(namedTupleMembersErrors.ts, 19, 71)) +>RecusiveRest : Symbol(RecusiveRest, Decl(namedTupleMembersErrors.ts, 19, 71)) diff --git a/tests/baselines/reference/namedTupleMembersErrors.types b/tests/baselines/reference/namedTupleMembersErrors.types index 761437dac55d7..0ae16d3b68353 100644 --- a/tests/baselines/reference/namedTupleMembersErrors.types +++ b/tests/baselines/reference/namedTupleMembersErrors.types @@ -2,12 +2,21 @@ export type Segment1 = [length: number, number]; // partially named, disallowed >Segment1 : Segment1 +export type Segment2 = [number, size: number]; // partially named, disallowed +>Segment2 : Segment2 + export type List = [item: any, ...any]; // partially named, disallowed >List : [any, ...any[]] +export type List2 = [any, ...remainder: any]; // partially named, disallowed +>List2 : [any, ...any[]] + export type Pair = [item: any, any?]; // partially named, disallowed >Pair : Pair +export type Pair2 = [any, last?: any]; // partially named, disallowed +>Pair2 : Pair2 + export type Opt = [element: string?]; // question mark on element disallowed >Opt : Opt diff --git a/tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts b/tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts index 75eb3d3deca24..6a1f5a0537085 100644 --- a/tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts +++ b/tests/cases/conformance/types/tuple/named/namedTupleMembersErrors.ts @@ -1,10 +1,13 @@ // @declaration: true export type Segment1 = [length: number, number]; // partially named, disallowed +export type Segment2 = [number, size: number]; // partially named, disallowed export type List = [item: any, ...any]; // partially named, disallowed +export type List2 = [any, ...remainder: any]; // partially named, disallowed export type Pair = [item: any, any?]; // partially named, disallowed +export type Pair2 = [any, last?: any]; // partially named, disallowed export type Opt = [element: string?]; // question mark on element disallowed From 3e7a8e7e45aed722d7955e35e9fbac14ea75958a Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Tue, 8 Sep 2020 13:52:13 -0400 Subject: [PATCH 2/7] Cherry-pick PR #40348 into release-4.0 (#40349) Component commits: 3b332792a6 Fix call hierarchy item serialization and server tests Co-authored-by: Andrew Branch --- src/harness/client.ts | 5 +- src/server/session.ts | 1 + ...archyContainerNameServer.callHierarchy.txt | 165 ++++++++++++++++++ .../callHierarchyContainerNameServer.ts | 40 +++++ 4 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/callHierarchyContainerNameServer.callHierarchy.txt create mode 100644 tests/cases/fourslash/server/callHierarchyContainerNameServer.ts diff --git a/src/harness/client.ts b/src/harness/client.ts index 32db9e92a7a17..27411ba1f0c65 100644 --- a/src/harness/client.ts +++ b/src/harness/client.ts @@ -757,6 +757,7 @@ namespace ts.server { name: item.name, kind: item.kind, kindModifiers: item.kindModifiers, + containerName: item.containerName, span: this.decodeSpan(item.span, item.file), selectionSpan: this.decodeSpan(item.selectionSpan, item.file) }; @@ -778,7 +779,7 @@ namespace ts.server { provideCallHierarchyIncomingCalls(fileName: string, position: number) { const args = this.createFileLocationRequestArgs(fileName, position); - const request = this.processRequest(CommandNames.PrepareCallHierarchy, args); + const request = this.processRequest(CommandNames.ProvideCallHierarchyIncomingCalls, args); const response = this.processResponse(request); return response.body.map(item => this.convertCallHierarchyIncomingCall(item)); } @@ -792,7 +793,7 @@ namespace ts.server { provideCallHierarchyOutgoingCalls(fileName: string, position: number) { const args = this.createFileLocationRequestArgs(fileName, position); - const request = this.processRequest(CommandNames.PrepareCallHierarchy, args); + const request = this.processRequest(CommandNames.ProvideCallHierarchyOutgoingCalls, args); const response = this.processResponse(request); return response.body.map(item => this.convertCallHierarchyOutgoingCall(fileName, item)); } diff --git a/src/server/session.ts b/src/server/session.ts index 491b0bf3f7f12..e05c605e68ed7 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -2408,6 +2408,7 @@ namespace ts.server { kind: item.kind, kindModifiers: item.kindModifiers, file: item.file, + containerName: item.containerName, span: toProtocolTextSpan(item.span, scriptInfo), selectionSpan: toProtocolTextSpan(item.selectionSpan, scriptInfo) }; diff --git a/tests/baselines/reference/callHierarchyContainerNameServer.callHierarchy.txt b/tests/baselines/reference/callHierarchyContainerNameServer.callHierarchy.txt new file mode 100644 index 0000000000000..583fa14f605d7 --- /dev/null +++ b/tests/baselines/reference/callHierarchyContainerNameServer.callHierarchy.txt @@ -0,0 +1,165 @@ +╭ name: f +├ kind: function +├ file: /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts +├ span: +│ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:1:1-1:16 +│ │ 1: function f() {} +│ │ ^^^^^^^^^^^^^^^ +│ ╰ +├ selectionSpan: +│ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:1:10-1:11 +│ │ 1: function f() {} +│ │ ^ +│ ╰ +├ incoming: +│ ╭ from: +│ │ ╭ name: sameName +│ │ ├ kind: method +│ │ ├ containerName: A +│ │ ├ file: /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts +│ │ ├ span: +│ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:4:3-6:4 +│ │ │ │ 4: static sameName() { +│ │ │ │ ^^^^^^^^^^^^^^^^^^^ +│ │ │ │ 5: f(); +│ │ │ │ ^^^^^^^^ +│ │ │ │ 6: } +│ │ │ │ ^^^ +│ │ │ ╰ +│ │ ├ selectionSpan: +│ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:4:10-4:18 +│ │ │ │ 4: static sameName() { +│ │ │ │ ^^^^^^^^ +│ │ │ ╰ +│ │ ├ incoming: +│ │ │ ╭ from: +│ │ │ │ ╭ name: sameName +│ │ │ │ ├ kind: method +│ │ │ │ ├ containerName: B +│ │ │ │ ├ file: /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts +│ │ │ │ ├ span: +│ │ │ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:10:3-12:4 +│ │ │ │ │ │ 10: sameName() { +│ │ │ │ │ │ ^^^^^^^^^^^^ +│ │ │ │ │ │ 11: A.sameName(); +│ │ │ │ │ │ ^^^^^^^^^^^^^^^^^ +│ │ │ │ │ │ 12: } +│ │ │ │ │ │ ^^^ +│ │ │ │ │ ╰ +│ │ │ │ ├ selectionSpan: +│ │ │ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:10:3-10:11 +│ │ │ │ │ │ 10: sameName() { +│ │ │ │ │ │ ^^^^^^^^ +│ │ │ │ │ ╰ +│ │ │ │ ├ incoming: +│ │ │ │ │ ╭ from: +│ │ │ │ │ │ ╭ name: sameName +│ │ │ │ │ │ ├ kind: getter +│ │ │ │ │ │ ├ containerName: Obj +│ │ │ │ │ │ ├ file: /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts +│ │ │ │ │ │ ├ span: +│ │ │ │ │ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:16:3-18:4 +│ │ │ │ │ │ │ │ 16: get sameName() { +│ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^ +│ │ │ │ │ │ │ │ 17: return new B().sameName; +│ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +│ │ │ │ │ │ │ │ 18: } +│ │ │ │ │ │ │ │ ^^^ +│ │ │ │ │ │ │ ╰ +│ │ │ │ │ │ ├ selectionSpan: +│ │ │ │ │ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:16:7-16:15 +│ │ │ │ │ │ │ │ 16: get sameName() { +│ │ │ │ │ │ │ │ ^^^^^^^^ +│ │ │ │ │ │ │ ╰ +│ │ │ │ │ │ ├ incoming: +│ │ │ │ │ │ │ ╭ from: +│ │ │ │ │ │ │ │ ╭ name: sameName +│ │ │ │ │ │ │ │ ├ kind: function +│ │ │ │ │ │ │ │ ├ containerName: Foo +│ │ │ │ │ │ │ │ ├ file: /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts +│ │ │ │ │ │ │ │ ├ span: +│ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:22:3-24:4 +│ │ │ │ │ │ │ │ │ │ 22: function sameName() { +│ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^^^^^ +│ │ │ │ │ │ │ │ │ │ 23: return Obj.sameName; +│ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^^^^^^^^ +│ │ │ │ │ │ │ │ │ │ 24: } +│ │ │ │ │ │ │ │ │ │ ^^^ +│ │ │ │ │ │ │ │ │ ╰ +│ │ │ │ │ │ │ │ ├ selectionSpan: +│ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:22:12-22:20 +│ │ │ │ │ │ │ │ │ │ 22: function sameName() { +│ │ │ │ │ │ │ │ │ │ ^^^^^^^^ +│ │ │ │ │ │ │ │ │ ╰ +│ │ │ │ │ │ │ │ ├ incoming: +│ │ │ │ │ │ │ │ │ ╭ from: +│ │ │ │ │ │ │ │ │ │ ╭ name: C +│ │ │ │ │ │ │ │ │ │ ├ kind: class +│ │ │ │ │ │ │ │ │ │ ├ containerName: Foo +│ │ │ │ │ │ │ │ │ │ ├ file: /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts +│ │ │ │ │ │ │ │ │ │ ├ span: +│ │ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:26:3-30:4 +│ │ │ │ │ │ │ │ │ │ │ │ 26: export class C { +│ │ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^ +│ │ │ │ │ │ │ │ │ │ │ │ 27: constructor() { +│ │ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^^^ +│ │ │ │ │ │ │ │ │ │ │ │ 28: sameName(); +│ │ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^ +│ │ │ │ │ │ │ │ │ │ │ │ 29: } +│ │ │ │ │ │ │ │ │ │ │ │ ^^^^^ +│ │ │ │ │ │ │ │ │ │ │ │ 30: } +│ │ │ │ │ │ │ │ │ │ │ │ ^^^ +│ │ │ │ │ │ │ │ │ │ │ ╰ +│ │ │ │ │ │ │ │ │ │ ├ selectionSpan: +│ │ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:26:16-26:17 +│ │ │ │ │ │ │ │ │ │ │ │ 26: export class C { +│ │ │ │ │ │ │ │ │ │ │ │ ^ +│ │ │ │ │ │ │ │ │ │ │ ╰ +│ │ │ │ │ │ │ │ │ │ ├ incoming: +│ │ │ │ │ │ │ │ │ │ │ ╭ from: +│ │ │ │ │ │ │ │ │ │ │ │ ╭ name: sameName +│ │ │ │ │ │ │ │ │ │ │ │ ├ kind: function +│ │ │ │ │ │ │ │ │ │ │ │ ├ containerName: Bar +│ │ │ │ │ │ │ │ │ │ │ │ ├ file: /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts +│ │ │ │ │ │ │ │ │ │ │ │ ├ span: +│ │ │ │ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:34:20-34:37 +│ │ │ │ │ │ │ │ │ │ │ │ │ │ 34: const sameName = () => new Foo.C(); +│ │ │ │ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^^^^^^^^^^ +│ │ │ │ │ │ │ │ │ │ │ │ │ ╰ +│ │ │ │ │ │ │ │ │ │ │ │ ├ selectionSpan: +│ │ │ │ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:34:9-34:17 +│ │ │ │ │ │ │ │ │ │ │ │ │ │ 34: const sameName = () => new Foo.C(); +│ │ │ │ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^ +│ │ │ │ │ │ │ │ │ │ │ │ │ ╰ +│ │ │ │ │ │ │ │ │ │ │ │ ╰ incoming: none +│ │ │ │ │ │ │ │ │ │ │ ├ fromSpans: +│ │ │ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:34:34-34:35 +│ │ │ │ │ │ │ │ │ │ │ │ │ 34: const sameName = () => new Foo.C(); +│ │ │ │ │ │ │ │ │ │ │ │ │ ^ +│ │ │ │ │ │ │ │ │ │ ╰ ╰ ╰ +│ │ │ │ │ │ │ │ │ ├ fromSpans: +│ │ │ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:28:7-28:15 +│ │ │ │ │ │ │ │ │ │ │ 28: sameName(); +│ │ │ │ │ │ │ │ │ │ │ ^^^^^^^^ +│ │ │ │ │ │ │ │ ╰ ╰ ╰ +│ │ │ │ │ │ │ ├ fromSpans: +│ │ │ │ │ │ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:23:16-23:24 +│ │ │ │ │ │ │ │ │ 23: return Obj.sameName; +│ │ │ │ │ │ │ │ │ ^^^^^^^^ +│ │ │ │ │ │ ╰ ╰ ╰ +│ │ │ │ │ ├ fromSpans: +│ │ │ │ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:17:20-17:28 +│ │ │ │ │ │ │ 17: return new B().sameName; +│ │ │ │ │ │ │ ^^^^^^^^ +│ │ │ │ ╰ ╰ ╰ +│ │ │ ├ fromSpans: +│ │ │ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:11:7-11:15 +│ │ │ │ │ 11: A.sameName(); +│ │ │ │ │ ^^^^^^^^ +│ │ ╰ ╰ ╰ +│ ├ fromSpans: +│ │ ╭ /tests/cases/fourslash/server/callHierarchyContainerNameServer.ts:5:5-5:6 +│ │ │ 5: f(); +│ │ │ ^ +│ ╰ ╰ +╰ outgoing: none diff --git a/tests/cases/fourslash/server/callHierarchyContainerNameServer.ts b/tests/cases/fourslash/server/callHierarchyContainerNameServer.ts new file mode 100644 index 0000000000000..8957d21e851c4 --- /dev/null +++ b/tests/cases/fourslash/server/callHierarchyContainerNameServer.ts @@ -0,0 +1,40 @@ +/// + +////function /**/f() {} +//// +////class A { +//// static sameName() { +//// f(); +//// } +////} +//// +////class B { +//// sameName() { +//// A.sameName(); +//// } +////} +//// +////const Obj = { +//// get sameName() { +//// return new B().sameName; +//// } +////}; +//// +////namespace Foo { +//// function sameName() { +//// return Obj.sameName; +//// } +//// +//// export class C { +//// constructor() { +//// sameName(); +//// } +//// } +////} +//// +////module Foo.Bar { +//// const sameName = () => new Foo.C(); +////} + +goTo.marker(); +verify.baselineCallHierarchy(); From 657576ae7c9da142bdbbe43e64d425fa292124fe Mon Sep 17 00:00:00 2001 From: Brandon Cheng Date: Fri, 14 Aug 2020 14:13:19 -0400 Subject: [PATCH 3/7] Set stackTraceLimit to 0 in fileSystemEntryExists The exception thrown by Node.js's fs.statSync function contains a stack trace that can be expensive to compute. Since this exception isn't used by fileSystemEntryExists, we can safely set Error.stackTraceLimit to 0 without a change in behavior. --- A significant performance improvement was noticed with this change while profiling tsserver on packages within a proprietary monorepo. Specifically, my team saw high self time percentages for Node.js's uvException and handleErrorFromBinding internal functions. These functions are executed within fs.statSync when it fails to find the given path. https://user-images.githubusercontent.com/906558/90183227-220cb800-dd81-11ea-8d61-f41f89481f46.png fs.statSync: https://github.com/nodejs/node/blob/v14.4.0/lib/fs.js#L1030-L1037 handleErrorFromBinding: https://github.com/nodejs/node/blob/v14.4.0/lib/internal/fs/utils.js#L254-L269 uvException: https://github.com/nodejs/node/blob/v14.4.0/lib/internal/errors.js#L390-L443 ## Measurements After adding Error.stackTraceLimit = 0, we saw: - For a large configured project with 12,565 files, tsserver reached the projectLoadingFinish event 48.78% faster. (~46.786s vs ~31.447s) - For a medium project with 7,064 files, tsserver was 25.75% faster. (~20.897s vs ~16.618s) - For a small project with 796 files, tsserver was only a negligible 3.00% faster. (~3.545s vs ~3.442) Measurements were taken on macOS 10.15.6, Node.js 14.4.0, and a recent master commit of TypeScript (610fa28d). The average of 3 runs before and after this change were taken. I would normally include .cpuprofile and isolate-*-*-*.log files, but can't post them publicly in this case. If there's any other summaries the TypeScript team would be curious about I can report them. ## fs.statSync Misses Within our monorepo, the fs.statSync misses were mostly searches for alternative file extensions of module imports. - For node_modules imports, a lot of .ts/.tsx lookups failed until the .d.ts file was found. - Within projects with a lot of JSX files, .ts files were looked for before finding the .tsx version. - In the medium scale project mentioned above, a total of 38,515 non-existent files were queried during createProgram. --- src/compiler/sys.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 1662a7ef31096..efa51678f4da0 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -1662,6 +1662,11 @@ namespace ts { } function fileSystemEntryExists(path: string, entryKind: FileSystemEntryKind): boolean { + // Since the error thrown by fs.statSync isn't used, we can avoid collecting a stack trace to improve + // the CPU time performance. + const originalStackTraceLimit = Error.stackTraceLimit; + Error.stackTraceLimit = 0; + try { const stat = _fs.statSync(path); switch (entryKind) { @@ -1673,6 +1678,9 @@ namespace ts { catch (e) { return false; } + finally { + Error.stackTraceLimit = originalStackTraceLimit; + } } function fileExists(path: string): boolean { From 65b84e707e118b802ad41ca164debd15f4915a95 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Mon, 14 Sep 2020 20:08:51 -0400 Subject: [PATCH 4/7] Cherry-pick PR #40273 into release-4.0 (#40303) Component commits: 2c0e01aa94 Fix misplaced comma in auto imported specifier Co-authored-by: Andrew Branch --- src/services/codefixes/importFixes.ts | 2 +- .../importNameCodeFix_trailingComma.ts | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/importNameCodeFix_trailingComma.ts diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 2adcba0a9eec0..291dbdf55144f 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -700,7 +700,7 @@ namespace ts.codefix { } else if (existingSpecifiers?.length) { for (const spec of newSpecifiers) { - changes.insertNodeAtEndOfList(sourceFile, existingSpecifiers, spec); + changes.insertNodeInListAfter(sourceFile, last(existingSpecifiers), spec, existingSpecifiers); } } else { diff --git a/tests/cases/fourslash/importNameCodeFix_trailingComma.ts b/tests/cases/fourslash/importNameCodeFix_trailingComma.ts new file mode 100644 index 0000000000000..2717ff10822fb --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFix_trailingComma.ts @@ -0,0 +1,24 @@ +/// + +// Bug #40219 only happens when existing import specifiers are unsorted. + +// @Filename: index.ts +//// import { +//// T2, +//// T1, +//// } from "./types"; +//// +//// const x: T3/**/ + +// @Filename: types.ts +//// export type T1 = 0; +//// export type T2 = 0; +//// export type T3 = 0; + +verify.importFixAtPosition([`import { + T2, + T1, + T3, +} from "./types"; + +const x: T3`]); From e3301f7294c759be4141f4a49b691fe2614f93ef Mon Sep 17 00:00:00 2001 From: Jesse Trinity Date: Wed, 16 Sep 2020 18:41:02 +0000 Subject: [PATCH 5/7] Cherry-pick PR #39924 into release-4.0 Component commits: 45d9eb5e3c place first import after header d35d719dab don't insert before non-header --- src/services/textChanges.ts | 4 +-- src/services/utilities.ts | 5 ++- .../importNameCodeFix_HeaderComment1.ts | 26 +++++++++++++++ .../importNameCodeFix_HeaderComment2.ts | 32 +++++++++++++++++++ 4 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 tests/cases/fourslash/importNameCodeFix_HeaderComment1.ts create mode 100644 tests/cases/fourslash/importNameCodeFix_HeaderComment2.ts diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 023a34c05663f..131cb029c6537 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -384,8 +384,8 @@ namespace ts.textChanges { } } - public insertNodeBefore(sourceFile: SourceFile, before: Node, newNode: Node, blankLineBetween = false): void { - this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}), newNode, this.getOptionsForInsertNodeBefore(before, newNode, blankLineBetween)); + public insertNodeBefore(sourceFile: SourceFile, before: Node, newNode: Node, blankLineBetween = false, options: ConfigurableStartEnd = {}): void { + this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, options), newNode, this.getOptionsForInsertNodeBefore(before, newNode, blankLineBetween)); } public insertModifierBefore(sourceFile: SourceFile, modifier: SyntaxKind, before: Node): void { diff --git a/src/services/utilities.ts b/src/services/utilities.ts index baa70bf1df84f..1daf9a1305a6f 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1913,7 +1913,10 @@ namespace ts { for (const newImport of sortedNewImports) { const insertionIndex = OrganizeImports.getImportDeclarationInsertionIndex(existingImportStatements, newImport); if (insertionIndex === 0) { - changes.insertNodeBefore(sourceFile, existingImportStatements[0], newImport, /*blankLineBetween*/ false); + // If the first import is top-of-file, insert after the leading comment which is likely the header. + const options = existingImportStatements[0] === sourceFile.statements[0] ? + { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude } : {}; + changes.insertNodeBefore(sourceFile, existingImportStatements[0], newImport, /*blankLineBetween*/ false, options); } else { const prevImport = existingImportStatements[insertionIndex - 1]; diff --git a/tests/cases/fourslash/importNameCodeFix_HeaderComment1.ts b/tests/cases/fourslash/importNameCodeFix_HeaderComment1.ts new file mode 100644 index 0000000000000..d3263217b2faa --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFix_HeaderComment1.ts @@ -0,0 +1,26 @@ +/// + +// @Filename: /a.ts +////export const foo = 0; + +// @Filename: /b.ts +////export const bar = 0; + +// @Filename: /c.ts +/////*-------------------- +//// * Copyright Header +//// *--------------------*/ +//// +////import { bar } from "./b"; +////foo; + +goTo.file("/c.ts"); +verify.importFixAtPosition([ +`/*-------------------- + * Copyright Header + *--------------------*/ + +import { foo } from "./a"; +import { bar } from "./b"; +foo;`, +]); diff --git a/tests/cases/fourslash/importNameCodeFix_HeaderComment2.ts b/tests/cases/fourslash/importNameCodeFix_HeaderComment2.ts new file mode 100644 index 0000000000000..994d770ff24c5 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFix_HeaderComment2.ts @@ -0,0 +1,32 @@ +/// + +// @Filename: /a.ts +////export const foo = 0; + +// @Filename: /b.ts +////export const bar = 0; + +// @Filename: /c.ts +/////*-------------------- +//// * Copyright Header +//// *--------------------*/ +//// +////const afterHeader = 1; +//// +////// non-header comment +////import { bar } from "./b"; +////foo; + +goTo.file("/c.ts"); +verify.importFixAtPosition([ +`/*-------------------- + * Copyright Header + *--------------------*/ + +const afterHeader = 1; + +import { foo } from "./a"; +// non-header comment +import { bar } from "./b"; +foo;`, +]); From 2eb5deae4bafe169ec1d2ecf66999003574164bb Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Fri, 18 Sep 2020 00:43:07 +0000 Subject: [PATCH 6/7] Update LKG --- lib/tsc.js | 12 +++++++----- lib/tsserver.js | 27 ++++++++++++++++++--------- lib/tsserverlibrary.js | 27 ++++++++++++++++++--------- lib/typescript.js | 26 +++++++++++++++++--------- lib/typescriptServices.js | 26 +++++++++++++++++--------- lib/typingsInstaller.js | 14 +++++++++----- 6 files changed, 86 insertions(+), 46 deletions(-) diff --git a/lib/tsc.js b/lib/tsc.js index 25cb130021d8e..0bfe86476efc1 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -3836,6 +3836,8 @@ var ts; return ts.matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries, realpath); } function fileSystemEntryExists(path, entryKind) { + var originalStackTraceLimit = Error.stackTraceLimit; + Error.stackTraceLimit = 0; try { var stat = _fs.statSync(path); switch (entryKind) { @@ -3847,6 +3849,9 @@ var ts; catch (e) { return false; } + finally { + Error.stackTraceLimit = originalStackTraceLimit; + } } function fileExists(path) { return fileSystemEntryExists(path, 0); @@ -58916,13 +58921,10 @@ var ts; function checkTupleType(node) { var elementTypes = node.elements; var seenOptionalElement = false; - var seenNamedElement = false; + var hasNamedElement = ts.some(elementTypes, ts.isNamedTupleMember); for (var i = 0; i < elementTypes.length; i++) { var e = elementTypes[i]; - if (e.kind === 191) { - seenNamedElement = true; - } - else if (seenNamedElement) { + if (e.kind !== 191 && hasNamedElement) { grammarErrorOnNode(e, ts.Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names); break; } diff --git a/lib/tsserver.js b/lib/tsserver.js index 2d18544a00660..e6406772d74f8 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -6174,6 +6174,10 @@ var ts; return ts.matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries, realpath); } function fileSystemEntryExists(path, entryKind) { + // Since the error thrown by fs.statSync isn't used, we can avoid collecting a stack trace to improve + // the CPU time performance. + var originalStackTraceLimit = Error.stackTraceLimit; + Error.stackTraceLimit = 0; try { var stat = _fs.statSync(path); switch (entryKind) { @@ -6185,6 +6189,9 @@ var ts; catch (e) { return false; } + finally { + Error.stackTraceLimit = originalStackTraceLimit; + } } function fileExists(path) { return fileSystemEntryExists(path, 0 /* File */); @@ -70542,13 +70549,10 @@ var ts; function checkTupleType(node) { var elementTypes = node.elements; var seenOptionalElement = false; - var seenNamedElement = false; + var hasNamedElement = ts.some(elementTypes, ts.isNamedTupleMember); for (var i = 0; i < elementTypes.length; i++) { var e = elementTypes[i]; - if (e.kind === 191 /* NamedTupleMember */) { - seenNamedElement = true; - } - else if (seenNamedElement) { + if (e.kind !== 191 /* NamedTupleMember */ && hasNamedElement) { grammarErrorOnNode(e, ts.Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names); break; } @@ -112398,7 +112402,10 @@ var ts; var newImport = sortedNewImports_1[_i]; var insertionIndex = ts.OrganizeImports.getImportDeclarationInsertionIndex(existingImportStatements, newImport); if (insertionIndex === 0) { - changes.insertNodeBefore(sourceFile, existingImportStatements[0], newImport, /*blankLineBetween*/ false); + // If the first import is top-of-file, insert after the leading comment which is likely the header. + var options = existingImportStatements[0] === sourceFile.statements[0] ? + { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude } : {}; + changes.insertNodeBefore(sourceFile, existingImportStatements[0], newImport, /*blankLineBetween*/ false, options); } else { var prevImport = existingImportStatements[insertionIndex - 1]; @@ -129526,9 +129533,10 @@ var ts; this.insertNodeAt(sourceFile, parameters.pos, newParam); } }; - ChangeTracker.prototype.insertNodeBefore = function (sourceFile, before, newNode, blankLineBetween) { + ChangeTracker.prototype.insertNodeBefore = function (sourceFile, before, newNode, blankLineBetween, options) { if (blankLineBetween === void 0) { blankLineBetween = false; } - this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}), newNode, this.getOptionsForInsertNodeBefore(before, newNode, blankLineBetween)); + if (options === void 0) { options = {}; } + this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, options), newNode, this.getOptionsForInsertNodeBefore(before, newNode, blankLineBetween)); }; ChangeTracker.prototype.insertModifierBefore = function (sourceFile, modifier, before) { var pos = before.getStart(sourceFile); @@ -133396,7 +133404,7 @@ var ts; else if (existingSpecifiers === null || existingSpecifiers === void 0 ? void 0 : existingSpecifiers.length) { for (var _b = 0, newSpecifiers_2 = newSpecifiers; _b < newSpecifiers_2.length; _b++) { var spec = newSpecifiers_2[_b]; - changes.insertNodeAtEndOfList(sourceFile, existingSpecifiers, spec); + changes.insertNodeInListAfter(sourceFile, ts.last(existingSpecifiers), spec, existingSpecifiers); } } else { @@ -154869,6 +154877,7 @@ var ts; kind: item.kind, kindModifiers: item.kindModifiers, file: item.file, + containerName: item.containerName, span: toProtocolTextSpan(item.span, scriptInfo), selectionSpan: toProtocolTextSpan(item.selectionSpan, scriptInfo) }; diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js index 16a7a7b21ea02..66ea06329ee45 100644 --- a/lib/tsserverlibrary.js +++ b/lib/tsserverlibrary.js @@ -6368,6 +6368,10 @@ var ts; return ts.matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries, realpath); } function fileSystemEntryExists(path, entryKind) { + // Since the error thrown by fs.statSync isn't used, we can avoid collecting a stack trace to improve + // the CPU time performance. + var originalStackTraceLimit = Error.stackTraceLimit; + Error.stackTraceLimit = 0; try { var stat = _fs.statSync(path); switch (entryKind) { @@ -6379,6 +6383,9 @@ var ts; catch (e) { return false; } + finally { + Error.stackTraceLimit = originalStackTraceLimit; + } } function fileExists(path) { return fileSystemEntryExists(path, 0 /* File */); @@ -70736,13 +70743,10 @@ var ts; function checkTupleType(node) { var elementTypes = node.elements; var seenOptionalElement = false; - var seenNamedElement = false; + var hasNamedElement = ts.some(elementTypes, ts.isNamedTupleMember); for (var i = 0; i < elementTypes.length; i++) { var e = elementTypes[i]; - if (e.kind === 191 /* NamedTupleMember */) { - seenNamedElement = true; - } - else if (seenNamedElement) { + if (e.kind !== 191 /* NamedTupleMember */ && hasNamedElement) { grammarErrorOnNode(e, ts.Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names); break; } @@ -112965,7 +112969,10 @@ var ts; var newImport = sortedNewImports_1[_i]; var insertionIndex = ts.OrganizeImports.getImportDeclarationInsertionIndex(existingImportStatements, newImport); if (insertionIndex === 0) { - changes.insertNodeBefore(sourceFile, existingImportStatements[0], newImport, /*blankLineBetween*/ false); + // If the first import is top-of-file, insert after the leading comment which is likely the header. + var options = existingImportStatements[0] === sourceFile.statements[0] ? + { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude } : {}; + changes.insertNodeBefore(sourceFile, existingImportStatements[0], newImport, /*blankLineBetween*/ false, options); } else { var prevImport = existingImportStatements[insertionIndex - 1]; @@ -130093,9 +130100,10 @@ var ts; this.insertNodeAt(sourceFile, parameters.pos, newParam); } }; - ChangeTracker.prototype.insertNodeBefore = function (sourceFile, before, newNode, blankLineBetween) { + ChangeTracker.prototype.insertNodeBefore = function (sourceFile, before, newNode, blankLineBetween, options) { if (blankLineBetween === void 0) { blankLineBetween = false; } - this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}), newNode, this.getOptionsForInsertNodeBefore(before, newNode, blankLineBetween)); + if (options === void 0) { options = {}; } + this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, options), newNode, this.getOptionsForInsertNodeBefore(before, newNode, blankLineBetween)); }; ChangeTracker.prototype.insertModifierBefore = function (sourceFile, modifier, before) { var pos = before.getStart(sourceFile); @@ -133963,7 +133971,7 @@ var ts; else if (existingSpecifiers === null || existingSpecifiers === void 0 ? void 0 : existingSpecifiers.length) { for (var _b = 0, newSpecifiers_2 = newSpecifiers; _b < newSpecifiers_2.length; _b++) { var spec = newSpecifiers_2[_b]; - changes.insertNodeAtEndOfList(sourceFile, existingSpecifiers, spec); + changes.insertNodeInListAfter(sourceFile, ts.last(existingSpecifiers), spec, existingSpecifiers); } } else { @@ -155063,6 +155071,7 @@ var ts; kind: item.kind, kindModifiers: item.kindModifiers, file: item.file, + containerName: item.containerName, span: toProtocolTextSpan(item.span, scriptInfo), selectionSpan: toProtocolTextSpan(item.selectionSpan, scriptInfo) }; diff --git a/lib/typescript.js b/lib/typescript.js index 70d7dd8323d41..ba3893320b6df 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -6368,6 +6368,10 @@ var ts; return ts.matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries, realpath); } function fileSystemEntryExists(path, entryKind) { + // Since the error thrown by fs.statSync isn't used, we can avoid collecting a stack trace to improve + // the CPU time performance. + var originalStackTraceLimit = Error.stackTraceLimit; + Error.stackTraceLimit = 0; try { var stat = _fs.statSync(path); switch (entryKind) { @@ -6379,6 +6383,9 @@ var ts; catch (e) { return false; } + finally { + Error.stackTraceLimit = originalStackTraceLimit; + } } function fileExists(path) { return fileSystemEntryExists(path, 0 /* File */); @@ -70736,13 +70743,10 @@ var ts; function checkTupleType(node) { var elementTypes = node.elements; var seenOptionalElement = false; - var seenNamedElement = false; + var hasNamedElement = ts.some(elementTypes, ts.isNamedTupleMember); for (var i = 0; i < elementTypes.length; i++) { var e = elementTypes[i]; - if (e.kind === 191 /* NamedTupleMember */) { - seenNamedElement = true; - } - else if (seenNamedElement) { + if (e.kind !== 191 /* NamedTupleMember */ && hasNamedElement) { grammarErrorOnNode(e, ts.Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names); break; } @@ -112965,7 +112969,10 @@ var ts; var newImport = sortedNewImports_1[_i]; var insertionIndex = ts.OrganizeImports.getImportDeclarationInsertionIndex(existingImportStatements, newImport); if (insertionIndex === 0) { - changes.insertNodeBefore(sourceFile, existingImportStatements[0], newImport, /*blankLineBetween*/ false); + // If the first import is top-of-file, insert after the leading comment which is likely the header. + var options = existingImportStatements[0] === sourceFile.statements[0] ? + { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude } : {}; + changes.insertNodeBefore(sourceFile, existingImportStatements[0], newImport, /*blankLineBetween*/ false, options); } else { var prevImport = existingImportStatements[insertionIndex - 1]; @@ -130093,9 +130100,10 @@ var ts; this.insertNodeAt(sourceFile, parameters.pos, newParam); } }; - ChangeTracker.prototype.insertNodeBefore = function (sourceFile, before, newNode, blankLineBetween) { + ChangeTracker.prototype.insertNodeBefore = function (sourceFile, before, newNode, blankLineBetween, options) { if (blankLineBetween === void 0) { blankLineBetween = false; } - this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}), newNode, this.getOptionsForInsertNodeBefore(before, newNode, blankLineBetween)); + if (options === void 0) { options = {}; } + this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, options), newNode, this.getOptionsForInsertNodeBefore(before, newNode, blankLineBetween)); }; ChangeTracker.prototype.insertModifierBefore = function (sourceFile, modifier, before) { var pos = before.getStart(sourceFile); @@ -133963,7 +133971,7 @@ var ts; else if (existingSpecifiers === null || existingSpecifiers === void 0 ? void 0 : existingSpecifiers.length) { for (var _b = 0, newSpecifiers_2 = newSpecifiers; _b < newSpecifiers_2.length; _b++) { var spec = newSpecifiers_2[_b]; - changes.insertNodeAtEndOfList(sourceFile, existingSpecifiers, spec); + changes.insertNodeInListAfter(sourceFile, ts.last(existingSpecifiers), spec, existingSpecifiers); } } else { diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index ab017e67a7373..2927e7e29e523 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -6368,6 +6368,10 @@ var ts; return ts.matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries, realpath); } function fileSystemEntryExists(path, entryKind) { + // Since the error thrown by fs.statSync isn't used, we can avoid collecting a stack trace to improve + // the CPU time performance. + var originalStackTraceLimit = Error.stackTraceLimit; + Error.stackTraceLimit = 0; try { var stat = _fs.statSync(path); switch (entryKind) { @@ -6379,6 +6383,9 @@ var ts; catch (e) { return false; } + finally { + Error.stackTraceLimit = originalStackTraceLimit; + } } function fileExists(path) { return fileSystemEntryExists(path, 0 /* File */); @@ -70736,13 +70743,10 @@ var ts; function checkTupleType(node) { var elementTypes = node.elements; var seenOptionalElement = false; - var seenNamedElement = false; + var hasNamedElement = ts.some(elementTypes, ts.isNamedTupleMember); for (var i = 0; i < elementTypes.length; i++) { var e = elementTypes[i]; - if (e.kind === 191 /* NamedTupleMember */) { - seenNamedElement = true; - } - else if (seenNamedElement) { + if (e.kind !== 191 /* NamedTupleMember */ && hasNamedElement) { grammarErrorOnNode(e, ts.Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names); break; } @@ -112965,7 +112969,10 @@ var ts; var newImport = sortedNewImports_1[_i]; var insertionIndex = ts.OrganizeImports.getImportDeclarationInsertionIndex(existingImportStatements, newImport); if (insertionIndex === 0) { - changes.insertNodeBefore(sourceFile, existingImportStatements[0], newImport, /*blankLineBetween*/ false); + // If the first import is top-of-file, insert after the leading comment which is likely the header. + var options = existingImportStatements[0] === sourceFile.statements[0] ? + { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude } : {}; + changes.insertNodeBefore(sourceFile, existingImportStatements[0], newImport, /*blankLineBetween*/ false, options); } else { var prevImport = existingImportStatements[insertionIndex - 1]; @@ -130093,9 +130100,10 @@ var ts; this.insertNodeAt(sourceFile, parameters.pos, newParam); } }; - ChangeTracker.prototype.insertNodeBefore = function (sourceFile, before, newNode, blankLineBetween) { + ChangeTracker.prototype.insertNodeBefore = function (sourceFile, before, newNode, blankLineBetween, options) { if (blankLineBetween === void 0) { blankLineBetween = false; } - this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}), newNode, this.getOptionsForInsertNodeBefore(before, newNode, blankLineBetween)); + if (options === void 0) { options = {}; } + this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, options), newNode, this.getOptionsForInsertNodeBefore(before, newNode, blankLineBetween)); }; ChangeTracker.prototype.insertModifierBefore = function (sourceFile, modifier, before) { var pos = before.getStart(sourceFile); @@ -133963,7 +133971,7 @@ var ts; else if (existingSpecifiers === null || existingSpecifiers === void 0 ? void 0 : existingSpecifiers.length) { for (var _b = 0, newSpecifiers_2 = newSpecifiers; _b < newSpecifiers_2.length; _b++) { var spec = newSpecifiers_2[_b]; - changes.insertNodeAtEndOfList(sourceFile, existingSpecifiers, spec); + changes.insertNodeInListAfter(sourceFile, ts.last(existingSpecifiers), spec, existingSpecifiers); } } else { diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js index f3f435d157c2b..1078c7cc03f86 100644 --- a/lib/typingsInstaller.js +++ b/lib/typingsInstaller.js @@ -6163,6 +6163,10 @@ var ts; return ts.matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries, realpath); } function fileSystemEntryExists(path, entryKind) { + // Since the error thrown by fs.statSync isn't used, we can avoid collecting a stack trace to improve + // the CPU time performance. + var originalStackTraceLimit = Error.stackTraceLimit; + Error.stackTraceLimit = 0; try { var stat = _fs.statSync(path); switch (entryKind) { @@ -6174,6 +6178,9 @@ var ts; catch (e) { return false; } + finally { + Error.stackTraceLimit = originalStackTraceLimit; + } } function fileExists(path) { return fileSystemEntryExists(path, 0 /* File */); @@ -70531,13 +70538,10 @@ var ts; function checkTupleType(node) { var elementTypes = node.elements; var seenOptionalElement = false; - var seenNamedElement = false; + var hasNamedElement = ts.some(elementTypes, ts.isNamedTupleMember); for (var i = 0; i < elementTypes.length; i++) { var e = elementTypes[i]; - if (e.kind === 191 /* NamedTupleMember */) { - seenNamedElement = true; - } - else if (seenNamedElement) { + if (e.kind !== 191 /* NamedTupleMember */ && hasNamedElement) { grammarErrorOnNode(e, ts.Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names); break; } From fee3bfbe91b7582f42e2f49814b87353f67e63f4 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Fri, 18 Sep 2020 17:46:05 +0000 Subject: [PATCH 7/7] Bump version to 4.0.3 and LKG --- lib/tsc.js | 2 +- lib/tsserver.js | 2 +- lib/tsserverlibrary.js | 2 +- lib/typescript.js | 2 +- lib/typescriptServices.js | 2 +- lib/typingsInstaller.js | 2 +- package.json | 2 +- src/compiler/corePublic.ts | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/tsc.js b/lib/tsc.js index 0bfe86476efc1..94ebc43d97e95 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -67,7 +67,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) { var ts; (function (ts) { ts.versionMajorMinor = "4.0"; - ts.version = "4.0.2"; + ts.version = "4.0.3"; var NativeCollections; (function (NativeCollections) { function tryGetNativeMap() { diff --git a/lib/tsserver.js b/lib/tsserver.js index e6406772d74f8..4a3a80c72bbd3 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -94,7 +94,7 @@ var ts; // If changing the text in this section, be sure to test `configurePrerelease` too. ts.versionMajorMinor = "4.0"; /** The version of the TypeScript compiler release */ - ts.version = "4.0.2"; + ts.version = "4.0.3"; /* @internal */ var Comparison; (function (Comparison) { diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js index 66ea06329ee45..19d76c21007c7 100644 --- a/lib/tsserverlibrary.js +++ b/lib/tsserverlibrary.js @@ -288,7 +288,7 @@ var ts; // If changing the text in this section, be sure to test `configurePrerelease` too. ts.versionMajorMinor = "4.0"; /** The version of the TypeScript compiler release */ - ts.version = "4.0.2"; + ts.version = "4.0.3"; /* @internal */ var Comparison; (function (Comparison) { diff --git a/lib/typescript.js b/lib/typescript.js index ba3893320b6df..67d0024d107e6 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -288,7 +288,7 @@ var ts; // If changing the text in this section, be sure to test `configurePrerelease` too. ts.versionMajorMinor = "4.0"; /** The version of the TypeScript compiler release */ - ts.version = "4.0.2"; + ts.version = "4.0.3"; /* @internal */ var Comparison; (function (Comparison) { diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index 2927e7e29e523..2852ef52b1d67 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -288,7 +288,7 @@ var ts; // If changing the text in this section, be sure to test `configurePrerelease` too. ts.versionMajorMinor = "4.0"; /** The version of the TypeScript compiler release */ - ts.version = "4.0.2"; + ts.version = "4.0.3"; /* @internal */ var Comparison; (function (Comparison) { diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js index 1078c7cc03f86..d12214a7b1bb3 100644 --- a/lib/typingsInstaller.js +++ b/lib/typingsInstaller.js @@ -83,7 +83,7 @@ var ts; // If changing the text in this section, be sure to test `configurePrerelease` too. ts.versionMajorMinor = "4.0"; /** The version of the TypeScript compiler release */ - ts.version = "4.0.2"; + ts.version = "4.0.3"; /* @internal */ var Comparison; (function (Comparison) { diff --git a/package.json b/package.json index 06cd98e164add..c929b609c604c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "typescript", "author": "Microsoft Corp.", "homepage": "https://www.typescriptlang.org/", - "version": "4.0.2", + "version": "4.0.3", "license": "Apache-2.0", "description": "TypeScript is a language for application scale JavaScript development", "keywords": [ diff --git a/src/compiler/corePublic.ts b/src/compiler/corePublic.ts index 1001709ba1db3..acf2b33f88d6c 100644 --- a/src/compiler/corePublic.ts +++ b/src/compiler/corePublic.ts @@ -3,7 +3,7 @@ namespace ts { // If changing the text in this section, be sure to test `configurePrerelease` too. export const versionMajorMinor = "4.0"; /** The version of the TypeScript compiler release */ - export const version = "4.0.2" as string; + export const version = "4.0.3" as string; /** * Type of objects whose values are all of the same type.