diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9f77641faf5cc..ca042094d25df 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -44696,7 +44696,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return node.parent.kind === SyntaxKind.TypeReference; } - function isHeritageClauseElementIdentifier(node: Node): boolean { + function isInNameOfExpressionWithTypeArguments(node: Node): boolean { while (node.parent.kind === SyntaxKind.PropertyAccessExpression) { node = node.parent; } @@ -44822,11 +44822,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { name = name.parent as QualifiedName | PropertyAccessEntityNameExpression | JSDocMemberName; } - if (isHeritageClauseElementIdentifier(name)) { + if (isInNameOfExpressionWithTypeArguments(name)) { let meaning = SymbolFlags.None; - // In an interface or class, we're definitely interested in a type. if (name.parent.kind === SyntaxKind.ExpressionWithTypeArguments) { - meaning = SymbolFlags.Type; + // An 'ExpressionWithTypeArguments' may appear in type space (interface Foo extends Bar), + // value space (return foo), or both(class Foo extends Bar); ensure the meaning matches. + meaning = isPartOfTypeNode(name) ? SymbolFlags.Type : SymbolFlags.Value; // In a class 'extends' clause we are also looking for a value. if (isExpressionWithTypeArgumentsInClassExtendsClause(name.parent)) { diff --git a/src/testRunner/tests.ts b/src/testRunner/tests.ts index f014bae90da21..328328781c1e2 100644 --- a/src/testRunner/tests.ts +++ b/src/testRunner/tests.ts @@ -188,3 +188,4 @@ import "./unittests/tsserver/typingsInstaller"; import "./unittests/tsserver/versionCache"; import "./unittests/tsserver/watchEnvironment"; import "./unittests/debugDeprecation"; +import "./unittests/tsserver/inconsistentErrorInEditor"; \ No newline at end of file diff --git a/src/testRunner/unittests/tsserver/inconsistentErrorInEditor.ts b/src/testRunner/unittests/tsserver/inconsistentErrorInEditor.ts new file mode 100644 index 0000000000000..11d97b0e09528 --- /dev/null +++ b/src/testRunner/unittests/tsserver/inconsistentErrorInEditor.ts @@ -0,0 +1,41 @@ +import * as ts from "../../_namespaces/ts"; +import { + createServerHost, +} from "../virtualFileSystemWithWatch"; +import { + baselineTsserverLogs, + createLoggerWithInMemoryLogs, + createSession, + verifyGetErrRequest, +} from "./helpers"; +describe("unittests:: tsserver:: inconsistentErrorInEditor", () => { + it("should not error", () => { + const host = createServerHost([]); + const session = createSession(host, { canUseEvents: true, noGetErrOnBackgroundUpdate: true, logger: createLoggerWithInMemoryLogs(host) }); + session.executeCommandSeq({ + command: ts.server.protocol.CommandTypes.UpdateOpen, + arguments: { + changedFiles: [], + closedFiles: [], + openFiles: [ + { + file: "^/untitled/ts-nul-authority/Untitled-1", + fileContent: "export function foo() {\r\n /*$*/return bar;\r\n}\r\n\r\nexport function bar(x: T) {\r\n return x;\r\n}\r\n\r\nlet x = foo()(42);", + scriptKindName: "TS" + } + ] + } + }); + session.executeCommandSeq({ + command: ts.server.protocol.CommandTypes.EncodedSemanticClassificationsFull, + arguments: { + file: "^/untitled/ts-nul-authority/Untitled-1", + start: 0, + length: 128, + format: "2020" + } + }); + verifyGetErrRequest({ session, host, files: ["^/untitled/ts-nul-authority/Untitled-1"] }); + baselineTsserverLogs("inconsistentErrorInEditor", "should not error", session); + }); +}); \ No newline at end of file diff --git a/tests/baselines/reference/classExtendingClassLikeType.symbols b/tests/baselines/reference/classExtendingClassLikeType.symbols index 80878edcd5c11..8ef380101c421 100644 --- a/tests/baselines/reference/classExtendingClassLikeType.symbols +++ b/tests/baselines/reference/classExtendingClassLikeType.symbols @@ -16,7 +16,6 @@ interface Base { // Error, no Base constructor function class D0 extends Base { >D0 : Symbol(D0, Decl(classExtendingClassLikeType.ts, 3, 1)) ->Base : Symbol(Base, Decl(classExtendingClassLikeType.ts, 0, 0)) } interface BaseConstructor { diff --git a/tests/baselines/reference/classExtendsEveryObjectType.symbols b/tests/baselines/reference/classExtendsEveryObjectType.symbols index 59c0dceeb81bd..5ea2cfc0a172c 100644 --- a/tests/baselines/reference/classExtendsEveryObjectType.symbols +++ b/tests/baselines/reference/classExtendsEveryObjectType.symbols @@ -7,7 +7,6 @@ interface I { } class C extends I { } // error >C : Symbol(C, Decl(classExtendsEveryObjectType.ts, 2, 1)) ->I : Symbol(I, Decl(classExtendsEveryObjectType.ts, 0, 0)) class C2 extends { foo: string; } { } // error >C2 : Symbol(C2, Decl(classExtendsEveryObjectType.ts, 3, 21)) diff --git a/tests/baselines/reference/classExtendsInterface.symbols b/tests/baselines/reference/classExtendsInterface.symbols index 5840f6342350e..27c611627b5a3 100644 --- a/tests/baselines/reference/classExtendsInterface.symbols +++ b/tests/baselines/reference/classExtendsInterface.symbols @@ -4,7 +4,6 @@ interface Comparable {} class A extends Comparable {} >A : Symbol(A, Decl(classExtendsInterface.ts, 0, 23)) ->Comparable : Symbol(Comparable, Decl(classExtendsInterface.ts, 0, 0)) class B implements Comparable {} >B : Symbol(B, Decl(classExtendsInterface.ts, 1, 29)) @@ -17,7 +16,6 @@ interface Comparable2 {} class A2 extends Comparable2 {} >A2 : Symbol(A2, Decl(classExtendsInterface.ts, 4, 27)) >T : Symbol(T, Decl(classExtendsInterface.ts, 5, 9)) ->Comparable2 : Symbol(Comparable2, Decl(classExtendsInterface.ts, 2, 32)) >T : Symbol(T, Decl(classExtendsInterface.ts, 5, 9)) class B2 implements Comparable2 {} diff --git a/tests/baselines/reference/classExtendsInterfaceInModule.symbols b/tests/baselines/reference/classExtendsInterfaceInModule.symbols index fb3ed5b3e859a..6e7aab45a671f 100644 --- a/tests/baselines/reference/classExtendsInterfaceInModule.symbols +++ b/tests/baselines/reference/classExtendsInterfaceInModule.symbols @@ -11,16 +11,12 @@ module M { } class C1 extends M.I1 {} >C1 : Symbol(C1, Decl(classExtendsInterfaceInModule.ts, 3, 1)) ->M.I1 : Symbol(M.I1, Decl(classExtendsInterfaceInModule.ts, 0, 10)) >M : Symbol(M, Decl(classExtendsInterfaceInModule.ts, 0, 0)) ->I1 : Symbol(M.I1, Decl(classExtendsInterfaceInModule.ts, 0, 10)) class C2 extends M.I2 {} >C2 : Symbol(C2, Decl(classExtendsInterfaceInModule.ts, 4, 24)) >T : Symbol(T, Decl(classExtendsInterfaceInModule.ts, 5, 9)) ->M.I2 : Symbol(M.I2, Decl(classExtendsInterfaceInModule.ts, 1, 24)) >M : Symbol(M, Decl(classExtendsInterfaceInModule.ts, 0, 0)) ->I2 : Symbol(M.I2, Decl(classExtendsInterfaceInModule.ts, 1, 24)) >T : Symbol(T, Decl(classExtendsInterfaceInModule.ts, 5, 9)) module Mod { @@ -36,9 +32,7 @@ module Mod { class D extends Mod.Nested.I {} >D : Symbol(D, Decl(classExtendsInterfaceInModule.ts, 11, 1)) ->Mod.Nested.I : Symbol(Mod.Nested.I, Decl(classExtendsInterfaceInModule.ts, 8, 26)) >Mod.Nested : Symbol(Mod.Nested, Decl(classExtendsInterfaceInModule.ts, 7, 12)) >Mod : Symbol(Mod, Decl(classExtendsInterfaceInModule.ts, 5, 30)) >Nested : Symbol(Mod.Nested, Decl(classExtendsInterfaceInModule.ts, 7, 12)) ->I : Symbol(Mod.Nested.I, Decl(classExtendsInterfaceInModule.ts, 8, 26)) diff --git a/tests/baselines/reference/genericTypeReferenceWithoutTypeArgument2.symbols b/tests/baselines/reference/genericTypeReferenceWithoutTypeArgument2.symbols index 27729d3cbce42..4616344fe825e 100644 --- a/tests/baselines/reference/genericTypeReferenceWithoutTypeArgument2.symbols +++ b/tests/baselines/reference/genericTypeReferenceWithoutTypeArgument2.symbols @@ -61,7 +61,6 @@ var g = function f(x: I): I { var y: I; return y; } class D extends I { >D : Symbol(D, Decl(genericTypeReferenceWithoutTypeArgument2.ts, 17, 51)) ->I : Symbol(I, Decl(genericTypeReferenceWithoutTypeArgument2.ts, 0, 0)) } interface U extends I {} diff --git a/tests/baselines/reference/tsserver/inconsistentErrorInEditor/should-not-error.js b/tests/baselines/reference/tsserver/inconsistentErrorInEditor/should-not-error.js new file mode 100644 index 0000000000000..c75b3c34d40bf --- /dev/null +++ b/tests/baselines/reference/tsserver/inconsistentErrorInEditor/should-not-error.js @@ -0,0 +1,239 @@ +Info 0 [00:00:02.000] Provided types map file "/a/lib/typesMap.json" doesn't exist +Info 1 [00:00:03.000] request: + { + "command": "updateOpen", + "arguments": { + "changedFiles": [], + "closedFiles": [], + "openFiles": [ + { + "file": "^/untitled/ts-nul-authority/Untitled-1", + "fileContent": "export function foo() {\r\n /*$*/return bar;\r\n}\r\n\r\nexport function bar(x: T) {\r\n return x;\r\n}\r\n\r\nlet x = foo()(42);", + "scriptKindName": "TS" + } + ] + }, + "seq": 1, + "type": "request" + } +Before request + +PolledWatches:: + +FsWatches:: + +FsWatchesRecursive:: + +Info 2 [00:00:04.000] Search path: ^/untitled/ts-nul-authority +Info 3 [00:00:05.000] For info: ^/untitled/ts-nul-authority/Untitled-1 :: No config files found. +Info 4 [00:00:06.000] Starting updateGraphWorker: Project: /dev/null/inferredProject1* +Info 5 [00:00:07.000] FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /dev/null/inferredProject1* WatchType: Missing file +Info 6 [00:00:08.000] Finishing updateGraphWorker: Project: /dev/null/inferredProject1* Version: 1 structureChanged: true structureIsReused:: Not Elapsed:: *ms +Info 7 [00:00:09.000] Project '/dev/null/inferredProject1*' (Inferred) +Info 8 [00:00:10.000] Files (1) + ^/untitled/ts-nul-authority/Untitled-1 + + + ^/untitled/ts-nul-authority/Untitled-1 + Root file specified for compilation + +Info 9 [00:00:11.000] ----------------------------------------------- +Info 10 [00:00:12.000] Project '/dev/null/inferredProject1*' (Inferred) +Info 10 [00:00:13.000] Files (1) + +Info 10 [00:00:14.000] ----------------------------------------------- +Info 10 [00:00:15.000] Open files: +Info 10 [00:00:16.000] FileName: ^/untitled/ts-nul-authority/Untitled-1 ProjectRootPath: undefined +Info 10 [00:00:17.000] Projects: /dev/null/inferredProject1* +After request + +PolledWatches:: +/a/lib/lib.d.ts: + {"pollingInterval":500} + +FsWatches:: + +FsWatchesRecursive:: + +Info 10 [00:00:18.000] response: + { + "response": true, + "responseRequired": true + } +Info 11 [00:00:19.000] request: + { + "command": "encodedSemanticClassifications-full", + "arguments": { + "file": "^/untitled/ts-nul-authority/Untitled-1", + "start": 0, + "length": 128, + "format": "2020" + }, + "seq": 2, + "type": "request" + } +Before request + +PolledWatches:: +/a/lib/lib.d.ts: + {"pollingInterval":500} + +FsWatches:: + +FsWatchesRecursive:: + +After request + +PolledWatches:: +/a/lib/lib.d.ts: + {"pollingInterval":500} + +FsWatches:: + +FsWatchesRecursive:: + +Info 12 [00:00:20.000] response: + { + "response": { + "spans": [ + 16, + 3, + 2817, + 20, + 1, + 1281, + 44, + 3, + 2816, + 48, + 1, + 1280, + 74, + 3, + 2817, + 78, + 1, + 1281, + 81, + 1, + 1793, + 84, + 1, + 1280, + 101, + 1, + 1792, + 114, + 1, + 2049, + 118, + 3, + 2816 + ], + "endOfLineState": 0 + }, + "responseRequired": true + } +Info 13 [00:00:21.000] request: + { + "command": "geterr", + "arguments": { + "delay": 0, + "files": [ + "^/untitled/ts-nul-authority/Untitled-1" + ] + }, + "seq": 3, + "type": "request" + } +Before request + +PolledWatches:: +/a/lib/lib.d.ts: + {"pollingInterval":500} + +FsWatches:: + +FsWatchesRecursive:: + +After request + +PolledWatches:: +/a/lib/lib.d.ts: + {"pollingInterval":500} + +FsWatches:: + +FsWatchesRecursive:: + +Info 14 [00:00:22.000] response: + { + "responseRequired": false + } +Before checking timeout queue length (1) and running + +PolledWatches:: +/a/lib/lib.d.ts: + {"pollingInterval":500} + +FsWatches:: + +FsWatchesRecursive:: + +Info 15 [00:00:23.000] event: + {"seq":0,"type":"event","event":"syntaxDiag","body":{"file":"^/untitled/ts-nul-authority/Untitled-1","diagnostics":[]}} +After checking timeout queue length (1) and running + +PolledWatches:: +/a/lib/lib.d.ts: + {"pollingInterval":500} + +FsWatches:: + +FsWatchesRecursive:: + +Before running immediate callbacks and checking length (1) + +PolledWatches:: +/a/lib/lib.d.ts: + {"pollingInterval":500} + +FsWatches:: + +FsWatchesRecursive:: + +Info 16 [00:00:24.000] event: + {"seq":0,"type":"event","event":"semanticDiag","body":{"file":"^/untitled/ts-nul-authority/Untitled-1","diagnostics":[]}} +Before running immediate callbacks and checking length (1) + +PolledWatches:: +/a/lib/lib.d.ts: + {"pollingInterval":500} + +FsWatches:: + +FsWatchesRecursive:: + +Before running immediate callbacks and checking length (1) + +PolledWatches:: +/a/lib/lib.d.ts: + {"pollingInterval":500} + +FsWatches:: + +FsWatchesRecursive:: + +Info 17 [00:00:25.000] event: + {"seq":0,"type":"event","event":"suggestionDiag","body":{"file":"^/untitled/ts-nul-authority/Untitled-1","diagnostics":[{"start":{"line":9,"offset":5},"end":{"line":9,"offset":6},"text":"'x' is declared but its value is never read.","code":6133,"category":"suggestion","reportsUnnecessary":true}]}} +Info 18 [00:00:26.000] event: + {"seq":0,"type":"event","event":"requestCompleted","body":{"request_seq":3}} +Before running immediate callbacks and checking length (1) + +PolledWatches:: +/a/lib/lib.d.ts: + {"pollingInterval":500} + +FsWatches:: + +FsWatchesRecursive::