From 4fdc81aac30187071a6460fcb7d2de83e4d04afb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 10 Jul 2023 09:44:50 +0200 Subject: [PATCH] Fixed an issue with errors not being correctly reported after completion requests in functions within nested calls --- src/compiler/checker.ts | 18 ++- ...terStringCompletionsInNestedCall2.baseline | 121 ++++++++++++++++++ ...rrorAfterStringCompletionsInNestedCall2.ts | 54 ++++++++ 3 files changed, 189 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/typeErrorAfterStringCompletionsInNestedCall2.baseline create mode 100644 tests/cases/fourslash/typeErrorAfterStringCompletionsInNestedCall2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b8bdbacd73f42..69695648ab2ae 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1833,20 +1833,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }; function runWithoutResolvedSignatureCaching(node: Node | undefined, fn: () => T): T { - const cachedSignatures = []; + const cachedResolvedSignatures = []; + const cachedTypes = []; while (node) { - if (isCallLikeExpression(node)) { + if (isCallLikeExpression(node) || isFunctionLike(node)) { const nodeLinks = getNodeLinks(node); const resolvedSignature = nodeLinks.resolvedSignature; - cachedSignatures.push([nodeLinks, resolvedSignature] as const); + cachedResolvedSignatures.push([nodeLinks, resolvedSignature] as const); nodeLinks.resolvedSignature = undefined; } + if (isFunctionLike(node)) { + const symbolLinks = getSymbolLinks(getSymbolOfDeclaration(node)); + const type = symbolLinks.type; + cachedTypes.push([symbolLinks, type] as const); + symbolLinks.type = undefined; + } node = node.parent; } const result = fn(); - for (const [nodeLinks, resolvedSignature] of cachedSignatures) { + for (const [nodeLinks, resolvedSignature] of cachedResolvedSignatures) { nodeLinks.resolvedSignature = resolvedSignature; } + for (const [symbolLinks, type] of cachedTypes) { + symbolLinks.type = type; + } return result; } diff --git a/tests/baselines/reference/typeErrorAfterStringCompletionsInNestedCall2.baseline b/tests/baselines/reference/typeErrorAfterStringCompletionsInNestedCall2.baseline new file mode 100644 index 0000000000000..29cfca778c8f3 --- /dev/null +++ b/tests/baselines/reference/typeErrorAfterStringCompletionsInNestedCall2.baseline @@ -0,0 +1,121 @@ +Syntactic Diagnostics for file '/tests/cases/fourslash/typeErrorAfterStringCompletionsInNestedCall2.ts': + + +==== /tests/cases/fourslash/typeErrorAfterStringCompletionsInNestedCall2.ts (0 errors) ==== + + type ActionFunction< + TExpressionEvent extends { type: string }, + out TEvent extends { type: string } + > = { + ({ event }: { event: TExpressionEvent }): void; + _out_TEvent?: TEvent; + }; + + interface MachineConfig { + types: { + events: TEvent; + }; + on: { + [K in TEvent["type"]]?: ActionFunction< + Extract, + TEvent + >; + }; + } + + declare function raise< + TExpressionEvent extends { type: string }, + TEvent extends { type: string } + >( + resolve: ({ event }: { event: TExpressionEvent }) => TEvent + ): { + ({ event }: { event: TExpressionEvent }): void; + _out_TEvent?: TEvent; + }; + + declare function createMachine( + config: MachineConfig + ): void; + + createMachine({ + types: { + events: {} as { type: "FOO" } | { type: "BAR" }, + }, + on: { + FOO: raise(({ event }) => { + return { + type: "BAR" as const, + }; + }), + }, + }); + +Semantic Diagnostics for file '/tests/cases/fourslash/typeErrorAfterStringCompletionsInNestedCall2.ts': +/tests/cases/fourslash/typeErrorAfterStringCompletionsInNestedCall2.ts(41,5): error TS2322: Type '{ ({ event }: { event: { type: "FOO"; }; }): void; _out_TEvent?: { type: "BARx"; } | undefined; }' is not assignable to type 'ActionFunction<{ type: "FOO"; }, { type: "FOO"; } | { type: "BAR"; }>'. + Types of property '_out_TEvent' are incompatible. + Type '{ type: "BARx"; } | undefined' is not assignable to type '{ type: "FOO"; } | { type: "BAR"; } | undefined'. + Type '{ type: "BARx"; }' is not assignable to type '{ type: "FOO"; } | { type: "BAR"; } | undefined'. + Type '{ type: "BARx"; }' is not assignable to type '{ type: "FOO"; } | { type: "BAR"; }'. + Type '{ type: "BARx"; }' is not assignable to type '{ type: "BAR"; }'. + Types of property 'type' are incompatible. + Type '"BARx"' is not assignable to type '"BAR"'. + + +==== /tests/cases/fourslash/typeErrorAfterStringCompletionsInNestedCall2.ts (1 errors) ==== + + type ActionFunction< + TExpressionEvent extends { type: string }, + out TEvent extends { type: string } + > = { + ({ event }: { event: TExpressionEvent }): void; + _out_TEvent?: TEvent; + }; + + interface MachineConfig { + types: { + events: TEvent; + }; + on: { + [K in TEvent["type"]]?: ActionFunction< + Extract, + TEvent + >; + }; + } + + declare function raise< + TExpressionEvent extends { type: string }, + TEvent extends { type: string } + >( + resolve: ({ event }: { event: TExpressionEvent }) => TEvent + ): { + ({ event }: { event: TExpressionEvent }): void; + _out_TEvent?: TEvent; + }; + + declare function createMachine( + config: MachineConfig + ): void; + + createMachine({ + types: { + events: {} as { type: "FOO" } | { type: "BAR" }, + }, + on: { + FOO: raise(({ event }) => { + ~~~ +!!! error TS2322: Type '{ ({ event }: { event: { type: "FOO"; }; }): void; _out_TEvent?: { type: "BARx"; } | undefined; }' is not assignable to type 'ActionFunction<{ type: "FOO"; }, { type: "FOO"; } | { type: "BAR"; }>'. +!!! error TS2322: Types of property '_out_TEvent' are incompatible. +!!! error TS2322: Type '{ type: "BARx"; } | undefined' is not assignable to type '{ type: "FOO"; } | { type: "BAR"; } | undefined'. +!!! error TS2322: Type '{ type: "BARx"; }' is not assignable to type '{ type: "FOO"; } | { type: "BAR"; } | undefined'. +!!! error TS2322: Type '{ type: "BARx"; }' is not assignable to type '{ type: "FOO"; } | { type: "BAR"; }'. +!!! error TS2322: Type '{ type: "BARx"; }' is not assignable to type '{ type: "BAR"; }'. +!!! error TS2322: Types of property 'type' are incompatible. +!!! error TS2322: Type '"BARx"' is not assignable to type '"BAR"'. +!!! related TS6500 /tests/cases/fourslash/typeErrorAfterStringCompletionsInNestedCall2.ts:14:7: The expected type comes from property 'FOO' which is declared here on type '{ FOO?: ActionFunction<{ type: "FOO"; }, { type: "FOO"; } | { type: "BAR"; }> | undefined; BAR?: ActionFunction<{ type: "BAR"; }, { type: "FOO"; } | { type: "BAR"; }> | undefined; }' + return { + type: "BAR" as const, + }; + }), + }, + }); \ No newline at end of file diff --git a/tests/cases/fourslash/typeErrorAfterStringCompletionsInNestedCall2.ts b/tests/cases/fourslash/typeErrorAfterStringCompletionsInNestedCall2.ts new file mode 100644 index 0000000000000..2bb3bf259ee29 --- /dev/null +++ b/tests/cases/fourslash/typeErrorAfterStringCompletionsInNestedCall2.ts @@ -0,0 +1,54 @@ +/// +// @strict: true +//// +//// type ActionFunction< +//// TExpressionEvent extends { type: string }, +//// out TEvent extends { type: string } +//// > = { +//// ({ event }: { event: TExpressionEvent }): void; +//// _out_TEvent?: TEvent; +//// }; +//// +//// interface MachineConfig { +//// types: { +//// events: TEvent; +//// }; +//// on: { +//// [K in TEvent["type"]]?: ActionFunction< +//// Extract, +//// TEvent +//// >; +//// }; +//// } +//// +//// declare function raise< +//// TExpressionEvent extends { type: string }, +//// TEvent extends { type: string } +//// >( +//// resolve: ({ event }: { event: TExpressionEvent }) => TEvent +//// ): { +//// ({ event }: { event: TExpressionEvent }): void; +//// _out_TEvent?: TEvent; +//// }; +//// +//// declare function createMachine( +//// config: MachineConfig +//// ): void; +//// +//// createMachine({ +//// types: { +//// events: {} as { type: "FOO" } | { type: "BAR" }, +//// }, +//// on: { +//// [|/*error*/FOO|]: raise(({ event }) => { +//// return { +//// type: "BAR/*1*/" as const, +//// }; +//// }), +//// }, +//// }); + +goTo.marker("1"); +edit.insert(`x`) +verify.completions({ exact: ["FOO", "BAR"] }); +verify.baselineSyntacticAndSemanticDiagnostics() \ No newline at end of file