From 8df2f7c1700e80ea8813e44196ca3a22c2d6e0f9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 25 Jul 2025 13:54:01 +0000 Subject: [PATCH 1/5] Initial plan From 655637f6113fbb575286b7aa7cd26cf2860d72c9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 25 Jul 2025 14:08:19 +0000 Subject: [PATCH 2/5] Add test case for isolated declarations function expression issue Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com> --- ...tedDeclarationsFunctionExpressionInCall.ts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/cases/compiler/isolatedDeclarationsFunctionExpressionInCall.ts diff --git a/tests/cases/compiler/isolatedDeclarationsFunctionExpressionInCall.ts b/tests/cases/compiler/isolatedDeclarationsFunctionExpressionInCall.ts new file mode 100644 index 0000000000000..514a9813e6772 --- /dev/null +++ b/tests/cases/compiler/isolatedDeclarationsFunctionExpressionInCall.ts @@ -0,0 +1,21 @@ +// @isolatedDeclarations: true +// @declaration: true + +declare function observer(fn: T): T; +declare function action(fn: T): T; + +export const Component = observer(() => { + return "hello"; +}); + +export const thing = action(function () { + return Component; +}); + +export const arrowWithType = observer((): string => { + return "typed"; +}); + +export const functionWithType = action(function (): typeof Component { + return Component; +}); \ No newline at end of file From 486c12af195cc9505d699e4a1376bb5408da9700 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 25 Jul 2025 14:21:45 +0000 Subject: [PATCH 3/5] Fix isolated declarations to not flag function expressions in call arguments Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com> --- src/compiler/transformers/declarations.ts | 30 +- .../transformers/declarations/diagnostics.ts | 277 +++++++++--------- ...rationsFunctionExpressionInCall.errors.txt | 37 +++ ...tedDeclarationsFunctionExpressionInCall.js | 38 +++ ...clarationsFunctionExpressionInCall.symbols | 49 ++++ ...DeclarationsFunctionExpressionInCall.types | 80 +++++ 6 files changed, 361 insertions(+), 150 deletions(-) create mode 100644 tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.errors.txt create mode 100644 tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.js create mode 100644 tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.symbols create mode 100644 tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.types diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 4b6941dc61f95..51ddab79ae1aa 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -91,9 +91,10 @@ import { isAmbientModule, isArray, isArrayBindingElement, - isBinaryExpression, - isBindingElement, - isBindingPattern, + isBinaryExpression, + isBindingElement, + isBindingPattern, + isCallExpression, isClassDeclaration, isClassElement, isComputedPropertyName, @@ -324,15 +325,20 @@ export function transformDeclarations(context: TransformationContext): Transform } }); } - function reportInferenceFallback(node: Node) { - if (!isolatedDeclarations || isSourceFileJS(currentSourceFile)) return; - if (getSourceFileOfNode(node) !== currentSourceFile) return; // Nested error on a declaration in another file - ignore, will be reemitted if file is in the output file set - if (isVariableDeclaration(node) && resolver.isExpandoFunctionDeclaration(node)) { - reportExpandoFunctionErrors(node); - } - else { - context.addDiagnostic(getIsolatedDeclarationError(node)); - } + function reportInferenceFallback(node: Node) { + if (!isolatedDeclarations || isSourceFileJS(currentSourceFile)) return; + if (getSourceFileOfNode(node) !== currentSourceFile) return; // Nested error on a declaration in another file - ignore, will be reemitted if file is in the output file set + if (isVariableDeclaration(node) && resolver.isExpandoFunctionDeclaration(node)) { + reportExpandoFunctionErrors(node); + } + else { + // Don't report errors for function expressions that are arguments to call expressions + if ((node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction) && + isCallExpression(node.parent)) { + return; + } + context.addDiagnostic(getIsolatedDeclarationError(node)); + } } function handleSymbolAccessibilityError(symbolAccessibilityResult: SymbolAccessibilityResult) { if (symbolAccessibilityResult.accessibility === SymbolAccessibility.Accessible) { diff --git a/src/compiler/transformers/declarations/diagnostics.ts b/src/compiler/transformers/declarations/diagnostics.ts index 873f23cbf7987..e01da0b08ff6f 100644 --- a/src/compiler/transformers/declarations/diagnostics.ts +++ b/src/compiler/transformers/declarations/diagnostics.ts @@ -1,100 +1,101 @@ -import { - addRelatedInfo, - ArrayLiteralExpression, - ArrowFunction, - assertType, - BinaryExpression, - BindingElement, - CallSignatureDeclaration, - ClassExpression, - ComputedPropertyName, - ConstructorDeclaration, - ConstructSignatureDeclaration, - createDiagnosticForNode, - Debug, - Declaration, - DeclarationName, - DiagnosticMessage, - Diagnostics, - DiagnosticWithLocation, - ElementAccessExpression, - EmitResolver, - EntityNameOrEntityNameExpression, - ExportAssignment, - Expression, - ExpressionWithTypeArguments, - findAncestor, - FunctionDeclaration, - FunctionExpression, - FunctionLikeDeclaration, - GetAccessorDeclaration, - getAllAccessorDeclarations, - getNameOfDeclaration, - getTextOfNode, - hasSyntacticModifier, - ImportEqualsDeclaration, - IndexSignatureDeclaration, - isAsExpression, - isBinaryExpression, - isBindingElement, - isCallSignatureDeclaration, - isClassDeclaration, - isConstructorDeclaration, - isConstructSignatureDeclaration, - isElementAccessExpression, - isEntityName, - isEntityNameExpression, - isExportAssignment, - isExpressionWithTypeArguments, - isFunctionDeclaration, - isFunctionLikeDeclaration, - isGetAccessor, - isHeritageClause, - isImportEqualsDeclaration, - isIndexSignatureDeclaration, - isJSDocTypeAlias, - isMethodDeclaration, - isMethodSignature, - isParameter, - isParameterPropertyDeclaration, - isParenthesizedExpression, - isPartOfTypeNode, - isPropertyAccessExpression, - isPropertyDeclaration, - isPropertySignature, - isReturnStatement, - isSetAccessor, - isStatement, - isStatic, - isTypeAliasDeclaration, - isTypeAssertionExpression, - isTypeParameterDeclaration, - isTypeQueryNode, - isVariableDeclaration, - JSDocCallbackTag, - JSDocEnumTag, - JSDocTypedefTag, - MethodDeclaration, - MethodSignature, - ModifierFlags, - NamedDeclaration, - Node, - ParameterDeclaration, - PropertyAccessExpression, - PropertyAssignment, - PropertyDeclaration, - PropertySignature, - QualifiedName, - SetAccessorDeclaration, - ShorthandPropertyAssignment, - SpreadAssignment, - SpreadElement, - SymbolAccessibility, - SymbolAccessibilityResult, - SyntaxKind, - TypeAliasDeclaration, - TypeParameterDeclaration, - VariableDeclaration, +import { + addRelatedInfo, + ArrayLiteralExpression, + ArrowFunction, + assertType, + BinaryExpression, + BindingElement, + CallSignatureDeclaration, + ClassExpression, + ComputedPropertyName, + ConstructorDeclaration, + ConstructSignatureDeclaration, + createDiagnosticForNode, + Debug, + Declaration, + DeclarationName, + DiagnosticMessage, + Diagnostics, + DiagnosticWithLocation, + ElementAccessExpression, + EmitResolver, + EntityNameOrEntityNameExpression, + ExportAssignment, + Expression, + ExpressionWithTypeArguments, + findAncestor, + FunctionDeclaration, + FunctionExpression, + FunctionLikeDeclaration, + GetAccessorDeclaration, + getAllAccessorDeclarations, + getNameOfDeclaration, + getTextOfNode, + hasSyntacticModifier, + ImportEqualsDeclaration, + IndexSignatureDeclaration, + isAsExpression, + isBinaryExpression, + isBindingElement, + isCallExpression, + isCallSignatureDeclaration, + isClassDeclaration, + isConstructorDeclaration, + isConstructSignatureDeclaration, + isElementAccessExpression, + isEntityName, + isEntityNameExpression, + isExportAssignment, + isExpressionWithTypeArguments, + isFunctionDeclaration, + isFunctionLikeDeclaration, + isGetAccessor, + isHeritageClause, + isImportEqualsDeclaration, + isIndexSignatureDeclaration, + isJSDocTypeAlias, + isMethodDeclaration, + isMethodSignature, + isParameter, + isParameterPropertyDeclaration, + isParenthesizedExpression, + isPartOfTypeNode, + isPropertyAccessExpression, + isPropertyDeclaration, + isPropertySignature, + isReturnStatement, + isSetAccessor, + isStatement, + isStatic, + isTypeAliasDeclaration, + isTypeAssertionExpression, + isTypeParameterDeclaration, + isTypeQueryNode, + isVariableDeclaration, + JSDocCallbackTag, + JSDocEnumTag, + JSDocTypedefTag, + MethodDeclaration, + MethodSignature, + ModifierFlags, + NamedDeclaration, + Node, + ParameterDeclaration, + PropertyAccessExpression, + PropertyAssignment, + PropertyDeclaration, + PropertySignature, + QualifiedName, + SetAccessorDeclaration, + ShorthandPropertyAssignment, + SpreadAssignment, + SpreadElement, + SymbolAccessibility, + SymbolAccessibilityResult, + SyntaxKind, + TypeAliasDeclaration, + TypeParameterDeclaration, + VariableDeclaration, } from "../../_namespaces/ts.js"; /** @internal */ @@ -661,47 +662,47 @@ export function createGetIsolatedDeclarationErrors(resolver: EmitResolver): (nod | PropertyAssignment | ClassExpression; - function getDiagnostic(node: Node) { - const heritageClause = findAncestor(node, isHeritageClause); - if (heritageClause) { - return createDiagnosticForNode(node, Diagnostics.Extends_clause_can_t_contain_an_expression_with_isolatedDeclarations); - } - if ((isPartOfTypeNode(node) || isTypeQueryNode(node.parent)) && (isEntityName(node) || isEntityNameExpression(node))) { - return createEntityInTypeNodeError(node); - } - Debug.type(node); - switch (node.kind) { - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - return createAccessorTypeError(node); - case SyntaxKind.ComputedPropertyName: - case SyntaxKind.ShorthandPropertyAssignment: - case SyntaxKind.SpreadAssignment: - return createObjectLiteralError(node); - case SyntaxKind.ArrayLiteralExpression: - case SyntaxKind.SpreadElement: - return createArrayLiteralError(node); - case SyntaxKind.MethodDeclaration: - case SyntaxKind.ConstructSignature: - case SyntaxKind.FunctionExpression: - case SyntaxKind.ArrowFunction: - case SyntaxKind.FunctionDeclaration: - return createReturnTypeError(node); - case SyntaxKind.BindingElement: - return createBindingElementError(node); - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.VariableDeclaration: - return createVariableOrPropertyError(node); - case SyntaxKind.Parameter: - return createParameterError(node); - case SyntaxKind.PropertyAssignment: - return createExpressionError(node.initializer); - case SyntaxKind.ClassExpression: - return createClassExpressionError(node); - default: - assertType(node); - return createExpressionError(node as Expression); - } + function getDiagnostic(node: Node) { + const heritageClause = findAncestor(node, isHeritageClause); + if (heritageClause) { + return createDiagnosticForNode(node, Diagnostics.Extends_clause_can_t_contain_an_expression_with_isolatedDeclarations); + } + if ((isPartOfTypeNode(node) || isTypeQueryNode(node.parent)) && (isEntityName(node) || isEntityNameExpression(node))) { + return createEntityInTypeNodeError(node); + } + Debug.type(node); + switch (node.kind) { + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return createAccessorTypeError(node); + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.SpreadAssignment: + return createObjectLiteralError(node); + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.SpreadElement: + return createArrayLiteralError(node); + case SyntaxKind.MethodDeclaration: + case SyntaxKind.ConstructSignature: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionDeclaration: + return createReturnTypeError(node); + case SyntaxKind.BindingElement: + return createBindingElementError(node); + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.VariableDeclaration: + return createVariableOrPropertyError(node); + case SyntaxKind.Parameter: + return createParameterError(node); + case SyntaxKind.PropertyAssignment: + return createExpressionError(node.initializer); + case SyntaxKind.ClassExpression: + return createClassExpressionError(node); + default: + assertType(node); + return createExpressionError(node as Expression); + } } function findNearestDeclaration(node: Node) { diff --git a/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.errors.txt b/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.errors.txt new file mode 100644 index 0000000000000..fd15b62fdaf83 --- /dev/null +++ b/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.errors.txt @@ -0,0 +1,37 @@ +isolatedDeclarationsFunctionExpressionInCall.ts(4,14): error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +isolatedDeclarationsFunctionExpressionInCall.ts(8,14): error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +isolatedDeclarationsFunctionExpressionInCall.ts(12,14): error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +isolatedDeclarationsFunctionExpressionInCall.ts(16,14): error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. + + +==== isolatedDeclarationsFunctionExpressionInCall.ts (4 errors) ==== + declare function observer(fn: T): T; + declare function action(fn: T): T; + + export const Component = observer(() => { + ~~~~~~~~~ +!!! error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +!!! related TS9027 isolatedDeclarationsFunctionExpressionInCall.ts:4:14: Add a type annotation to the variable Component. + return "hello"; + }); + + export const thing = action(function () { + ~~~~~ +!!! error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +!!! related TS9027 isolatedDeclarationsFunctionExpressionInCall.ts:8:14: Add a type annotation to the variable thing. + return Component; + }); + + export const arrowWithType = observer((): string => { + ~~~~~~~~~~~~~ +!!! error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +!!! related TS9027 isolatedDeclarationsFunctionExpressionInCall.ts:12:14: Add a type annotation to the variable arrowWithType. + return "typed"; + }); + + export const functionWithType = action(function (): typeof Component { + ~~~~~~~~~~~~~~~~ +!!! error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +!!! related TS9027 isolatedDeclarationsFunctionExpressionInCall.ts:16:14: Add a type annotation to the variable functionWithType. + return Component; + }); \ No newline at end of file diff --git a/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.js b/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.js new file mode 100644 index 0000000000000..a564a4355c0b3 --- /dev/null +++ b/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.js @@ -0,0 +1,38 @@ +//// [tests/cases/compiler/isolatedDeclarationsFunctionExpressionInCall.ts] //// + +//// [isolatedDeclarationsFunctionExpressionInCall.ts] +declare function observer(fn: T): T; +declare function action(fn: T): T; + +export const Component = observer(() => { + return "hello"; +}); + +export const thing = action(function () { + return Component; +}); + +export const arrowWithType = observer((): string => { + return "typed"; +}); + +export const functionWithType = action(function (): typeof Component { + return Component; +}); + +//// [isolatedDeclarationsFunctionExpressionInCall.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.functionWithType = exports.arrowWithType = exports.thing = exports.Component = void 0; +exports.Component = observer(function () { + return "hello"; +}); +exports.thing = action(function () { + return exports.Component; +}); +exports.arrowWithType = observer(function () { + return "typed"; +}); +exports.functionWithType = action(function () { + return exports.Component; +}); diff --git a/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.symbols b/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.symbols new file mode 100644 index 0000000000000..f49dd100fd1b0 --- /dev/null +++ b/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.symbols @@ -0,0 +1,49 @@ +//// [tests/cases/compiler/isolatedDeclarationsFunctionExpressionInCall.ts] //// + +=== isolatedDeclarationsFunctionExpressionInCall.ts === +declare function observer(fn: T): T; +>observer : Symbol(observer, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 0)) +>T : Symbol(T, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 26)) +>fn : Symbol(fn, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 29)) +>T : Symbol(T, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 26)) +>T : Symbol(T, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 26)) + +declare function action(fn: T): T; +>action : Symbol(action, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 39)) +>T : Symbol(T, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 1, 24)) +>fn : Symbol(fn, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 1, 27)) +>T : Symbol(T, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 1, 24)) +>T : Symbol(T, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 1, 24)) + +export const Component = observer(() => { +>Component : Symbol(Component, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 3, 12)) +>observer : Symbol(observer, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 0)) + + return "hello"; +}); + +export const thing = action(function () { +>thing : Symbol(thing, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 7, 12)) +>action : Symbol(action, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 39)) + + return Component; +>Component : Symbol(Component, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 3, 12)) + +}); + +export const arrowWithType = observer((): string => { +>arrowWithType : Symbol(arrowWithType, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 11, 12)) +>observer : Symbol(observer, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 0)) + + return "typed"; +}); + +export const functionWithType = action(function (): typeof Component { +>functionWithType : Symbol(functionWithType, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 15, 12)) +>action : Symbol(action, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 0, 39)) +>Component : Symbol(Component, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 3, 12)) + + return Component; +>Component : Symbol(Component, Decl(isolatedDeclarationsFunctionExpressionInCall.ts, 3, 12)) + +}); diff --git a/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.types b/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.types new file mode 100644 index 0000000000000..a56d8aa414490 --- /dev/null +++ b/tests/baselines/reference/isolatedDeclarationsFunctionExpressionInCall.types @@ -0,0 +1,80 @@ +//// [tests/cases/compiler/isolatedDeclarationsFunctionExpressionInCall.ts] //// + +=== isolatedDeclarationsFunctionExpressionInCall.ts === +declare function observer(fn: T): T; +>observer : (fn: T) => T +> : ^ ^^ ^^ ^^^^^ +>fn : T +> : ^ + +declare function action(fn: T): T; +>action : (fn: T) => T +> : ^ ^^ ^^ ^^^^^ +>fn : T +> : ^ + +export const Component = observer(() => { +>Component : () => "hello" +> : ^^^^^^^^^^^^^ +>observer(() => { return "hello";}) : () => "hello" +> : ^^^^^^^^^^^^^ +>observer : (fn: T) => T +> : ^ ^^ ^^ ^^^^^ +>() => { return "hello";} : () => "hello" +> : ^^^^^^^^^^^^^ + + return "hello"; +>"hello" : "hello" +> : ^^^^^^^ + +}); + +export const thing = action(function () { +>thing : () => () => "hello" +> : ^^^^^^^^^^^^^^^^^^^ +>action(function () { return Component;}) : () => () => "hello" +> : ^^^^^^^^^^^^^^^^^^^ +>action : (fn: T) => T +> : ^ ^^ ^^ ^^^^^ +>function () { return Component;} : () => () => "hello" +> : ^^^^^^^^^^^^^^^^^^^ + + return Component; +>Component : () => "hello" +> : ^^^^^^^^^^^^^ + +}); + +export const arrowWithType = observer((): string => { +>arrowWithType : () => string +> : ^^^^^^ +>observer((): string => { return "typed";}) : () => string +> : ^^^^^^ +>observer : (fn: T) => T +> : ^ ^^ ^^ ^^^^^ +>(): string => { return "typed";} : () => string +> : ^^^^^^ + + return "typed"; +>"typed" : "typed" +> : ^^^^^^^ + +}); + +export const functionWithType = action(function (): typeof Component { +>functionWithType : () => typeof Component +> : ^^^^^^ +>action(function (): typeof Component { return Component;}) : () => typeof Component +> : ^^^^^^ +>action : (fn: T) => T +> : ^ ^^ ^^ ^^^^^ +>function (): typeof Component { return Component;} : () => typeof Component +> : ^^^^^^ +>Component : () => "hello" +> : ^^^^^^^^^^^^^ + + return Component; +>Component : () => "hello" +> : ^^^^^^^^^^^^^ + +}); From f163c167b7abed216cd4614512a4f405e7c04770 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 25 Jul 2025 14:25:20 +0000 Subject: [PATCH 4/5] Clean up unused imports and apply formatting Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com> --- src/compiler/transformers/declarations.ts | 38 +-- .../transformers/declarations/diagnostics.ts | 277 +++++++++--------- 2 files changed, 158 insertions(+), 157 deletions(-) diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 51ddab79ae1aa..08a88dc776e6e 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -91,10 +91,10 @@ import { isAmbientModule, isArray, isArrayBindingElement, - isBinaryExpression, - isBindingElement, - isBindingPattern, - isCallExpression, + isBinaryExpression, + isBindingElement, + isBindingPattern, + isCallExpression, isClassDeclaration, isClassElement, isComputedPropertyName, @@ -325,20 +325,22 @@ export function transformDeclarations(context: TransformationContext): Transform } }); } - function reportInferenceFallback(node: Node) { - if (!isolatedDeclarations || isSourceFileJS(currentSourceFile)) return; - if (getSourceFileOfNode(node) !== currentSourceFile) return; // Nested error on a declaration in another file - ignore, will be reemitted if file is in the output file set - if (isVariableDeclaration(node) && resolver.isExpandoFunctionDeclaration(node)) { - reportExpandoFunctionErrors(node); - } - else { - // Don't report errors for function expressions that are arguments to call expressions - if ((node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction) && - isCallExpression(node.parent)) { - return; - } - context.addDiagnostic(getIsolatedDeclarationError(node)); - } + function reportInferenceFallback(node: Node) { + if (!isolatedDeclarations || isSourceFileJS(currentSourceFile)) return; + if (getSourceFileOfNode(node) !== currentSourceFile) return; // Nested error on a declaration in another file - ignore, will be reemitted if file is in the output file set + if (isVariableDeclaration(node) && resolver.isExpandoFunctionDeclaration(node)) { + reportExpandoFunctionErrors(node); + } + else { + // Don't report errors for function expressions that are arguments to call expressions + if ( + (node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction) && + isCallExpression(node.parent) + ) { + return; + } + context.addDiagnostic(getIsolatedDeclarationError(node)); + } } function handleSymbolAccessibilityError(symbolAccessibilityResult: SymbolAccessibilityResult) { if (symbolAccessibilityResult.accessibility === SymbolAccessibility.Accessible) { diff --git a/src/compiler/transformers/declarations/diagnostics.ts b/src/compiler/transformers/declarations/diagnostics.ts index e01da0b08ff6f..873f23cbf7987 100644 --- a/src/compiler/transformers/declarations/diagnostics.ts +++ b/src/compiler/transformers/declarations/diagnostics.ts @@ -1,101 +1,100 @@ -import { - addRelatedInfo, - ArrayLiteralExpression, - ArrowFunction, - assertType, - BinaryExpression, - BindingElement, - CallSignatureDeclaration, - ClassExpression, - ComputedPropertyName, - ConstructorDeclaration, - ConstructSignatureDeclaration, - createDiagnosticForNode, - Debug, - Declaration, - DeclarationName, - DiagnosticMessage, - Diagnostics, - DiagnosticWithLocation, - ElementAccessExpression, - EmitResolver, - EntityNameOrEntityNameExpression, - ExportAssignment, - Expression, - ExpressionWithTypeArguments, - findAncestor, - FunctionDeclaration, - FunctionExpression, - FunctionLikeDeclaration, - GetAccessorDeclaration, - getAllAccessorDeclarations, - getNameOfDeclaration, - getTextOfNode, - hasSyntacticModifier, - ImportEqualsDeclaration, - IndexSignatureDeclaration, - isAsExpression, - isBinaryExpression, - isBindingElement, - isCallExpression, - isCallSignatureDeclaration, - isClassDeclaration, - isConstructorDeclaration, - isConstructSignatureDeclaration, - isElementAccessExpression, - isEntityName, - isEntityNameExpression, - isExportAssignment, - isExpressionWithTypeArguments, - isFunctionDeclaration, - isFunctionLikeDeclaration, - isGetAccessor, - isHeritageClause, - isImportEqualsDeclaration, - isIndexSignatureDeclaration, - isJSDocTypeAlias, - isMethodDeclaration, - isMethodSignature, - isParameter, - isParameterPropertyDeclaration, - isParenthesizedExpression, - isPartOfTypeNode, - isPropertyAccessExpression, - isPropertyDeclaration, - isPropertySignature, - isReturnStatement, - isSetAccessor, - isStatement, - isStatic, - isTypeAliasDeclaration, - isTypeAssertionExpression, - isTypeParameterDeclaration, - isTypeQueryNode, - isVariableDeclaration, - JSDocCallbackTag, - JSDocEnumTag, - JSDocTypedefTag, - MethodDeclaration, - MethodSignature, - ModifierFlags, - NamedDeclaration, - Node, - ParameterDeclaration, - PropertyAccessExpression, - PropertyAssignment, - PropertyDeclaration, - PropertySignature, - QualifiedName, - SetAccessorDeclaration, - ShorthandPropertyAssignment, - SpreadAssignment, - SpreadElement, - SymbolAccessibility, - SymbolAccessibilityResult, - SyntaxKind, - TypeAliasDeclaration, - TypeParameterDeclaration, - VariableDeclaration, +import { + addRelatedInfo, + ArrayLiteralExpression, + ArrowFunction, + assertType, + BinaryExpression, + BindingElement, + CallSignatureDeclaration, + ClassExpression, + ComputedPropertyName, + ConstructorDeclaration, + ConstructSignatureDeclaration, + createDiagnosticForNode, + Debug, + Declaration, + DeclarationName, + DiagnosticMessage, + Diagnostics, + DiagnosticWithLocation, + ElementAccessExpression, + EmitResolver, + EntityNameOrEntityNameExpression, + ExportAssignment, + Expression, + ExpressionWithTypeArguments, + findAncestor, + FunctionDeclaration, + FunctionExpression, + FunctionLikeDeclaration, + GetAccessorDeclaration, + getAllAccessorDeclarations, + getNameOfDeclaration, + getTextOfNode, + hasSyntacticModifier, + ImportEqualsDeclaration, + IndexSignatureDeclaration, + isAsExpression, + isBinaryExpression, + isBindingElement, + isCallSignatureDeclaration, + isClassDeclaration, + isConstructorDeclaration, + isConstructSignatureDeclaration, + isElementAccessExpression, + isEntityName, + isEntityNameExpression, + isExportAssignment, + isExpressionWithTypeArguments, + isFunctionDeclaration, + isFunctionLikeDeclaration, + isGetAccessor, + isHeritageClause, + isImportEqualsDeclaration, + isIndexSignatureDeclaration, + isJSDocTypeAlias, + isMethodDeclaration, + isMethodSignature, + isParameter, + isParameterPropertyDeclaration, + isParenthesizedExpression, + isPartOfTypeNode, + isPropertyAccessExpression, + isPropertyDeclaration, + isPropertySignature, + isReturnStatement, + isSetAccessor, + isStatement, + isStatic, + isTypeAliasDeclaration, + isTypeAssertionExpression, + isTypeParameterDeclaration, + isTypeQueryNode, + isVariableDeclaration, + JSDocCallbackTag, + JSDocEnumTag, + JSDocTypedefTag, + MethodDeclaration, + MethodSignature, + ModifierFlags, + NamedDeclaration, + Node, + ParameterDeclaration, + PropertyAccessExpression, + PropertyAssignment, + PropertyDeclaration, + PropertySignature, + QualifiedName, + SetAccessorDeclaration, + ShorthandPropertyAssignment, + SpreadAssignment, + SpreadElement, + SymbolAccessibility, + SymbolAccessibilityResult, + SyntaxKind, + TypeAliasDeclaration, + TypeParameterDeclaration, + VariableDeclaration, } from "../../_namespaces/ts.js"; /** @internal */ @@ -662,47 +661,47 @@ export function createGetIsolatedDeclarationErrors(resolver: EmitResolver): (nod | PropertyAssignment | ClassExpression; - function getDiagnostic(node: Node) { - const heritageClause = findAncestor(node, isHeritageClause); - if (heritageClause) { - return createDiagnosticForNode(node, Diagnostics.Extends_clause_can_t_contain_an_expression_with_isolatedDeclarations); - } - if ((isPartOfTypeNode(node) || isTypeQueryNode(node.parent)) && (isEntityName(node) || isEntityNameExpression(node))) { - return createEntityInTypeNodeError(node); - } - Debug.type(node); - switch (node.kind) { - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - return createAccessorTypeError(node); - case SyntaxKind.ComputedPropertyName: - case SyntaxKind.ShorthandPropertyAssignment: - case SyntaxKind.SpreadAssignment: - return createObjectLiteralError(node); - case SyntaxKind.ArrayLiteralExpression: - case SyntaxKind.SpreadElement: - return createArrayLiteralError(node); - case SyntaxKind.MethodDeclaration: - case SyntaxKind.ConstructSignature: - case SyntaxKind.FunctionExpression: - case SyntaxKind.ArrowFunction: - case SyntaxKind.FunctionDeclaration: - return createReturnTypeError(node); - case SyntaxKind.BindingElement: - return createBindingElementError(node); - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.VariableDeclaration: - return createVariableOrPropertyError(node); - case SyntaxKind.Parameter: - return createParameterError(node); - case SyntaxKind.PropertyAssignment: - return createExpressionError(node.initializer); - case SyntaxKind.ClassExpression: - return createClassExpressionError(node); - default: - assertType(node); - return createExpressionError(node as Expression); - } + function getDiagnostic(node: Node) { + const heritageClause = findAncestor(node, isHeritageClause); + if (heritageClause) { + return createDiagnosticForNode(node, Diagnostics.Extends_clause_can_t_contain_an_expression_with_isolatedDeclarations); + } + if ((isPartOfTypeNode(node) || isTypeQueryNode(node.parent)) && (isEntityName(node) || isEntityNameExpression(node))) { + return createEntityInTypeNodeError(node); + } + Debug.type(node); + switch (node.kind) { + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return createAccessorTypeError(node); + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.SpreadAssignment: + return createObjectLiteralError(node); + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.SpreadElement: + return createArrayLiteralError(node); + case SyntaxKind.MethodDeclaration: + case SyntaxKind.ConstructSignature: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionDeclaration: + return createReturnTypeError(node); + case SyntaxKind.BindingElement: + return createBindingElementError(node); + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.VariableDeclaration: + return createVariableOrPropertyError(node); + case SyntaxKind.Parameter: + return createParameterError(node); + case SyntaxKind.PropertyAssignment: + return createExpressionError(node.initializer); + case SyntaxKind.ClassExpression: + return createClassExpressionError(node); + default: + assertType(node); + return createExpressionError(node as Expression); + } } function findNearestDeclaration(node: Node) { From b3bebe391de6dd675f1d58525d9eee5b554adec5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 25 Jul 2025 18:23:15 +0000 Subject: [PATCH 5/5] Fix isolated declarations to not flag function expressions in call arguments Function expressions and arrow functions used as arguments to function calls were incorrectly being flagged for needing explicit return type annotations with --isolatedDeclarations. This change modifies the logic in expressionToTypeNode.ts to skip inference fallback reporting for function expressions that are direct arguments to call expressions. The fix addresses the underlying issue by checking if the function expression's parent is a CallExpression and passing reportFallback=false in those cases, preventing the inference fallback error from being generated in the first place. Fixes #62085 Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com> --- src/compiler/expressionToTypeNode.ts | 7 ++++++- src/compiler/transformers/declarations.ts | 8 -------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/compiler/expressionToTypeNode.ts b/src/compiler/expressionToTypeNode.ts index 0df3a399b8f14..10cdb4bbc2c3c 100644 --- a/src/compiler/expressionToTypeNode.ts +++ b/src/compiler/expressionToTypeNode.ts @@ -731,6 +731,9 @@ export function createSyntacticTypeNodeBuilder( case SyntaxKind.ConstructorType: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: + // Don't report inference fallback for function expressions that are arguments to call expressions + const shouldReportFallback = !(node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction) || !isCallExpression(node.parent); + return createReturnFromSignature(node, symbol, context, shouldReportFallback); case SyntaxKind.JSDocFunctionType: case SyntaxKind.JSDocSignature: return createReturnFromSignature(node, symbol, context); @@ -968,7 +971,9 @@ export function createSyntacticTypeNodeBuilder( return failed; } function typeFromFunctionLikeExpression(fnNode: FunctionExpression | ArrowFunction, context: SyntacticTypeNodeBuilderContext) { - const returnType = createReturnFromSignature(fnNode, /*symbol*/ undefined, context); + // Don't report inference fallback for function expressions that are arguments to call expressions + const shouldReportFallback = !isCallExpression(fnNode.parent); + const returnType = createReturnFromSignature(fnNode, /*symbol*/ undefined, context, shouldReportFallback); const typeParameters = reuseTypeParameters(fnNode.typeParameters, context); const parameters = fnNode.parameters.map(p => ensureParameter(p, context)); return syntacticResult( diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 08a88dc776e6e..4b6941dc61f95 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -94,7 +94,6 @@ import { isBinaryExpression, isBindingElement, isBindingPattern, - isCallExpression, isClassDeclaration, isClassElement, isComputedPropertyName, @@ -332,13 +331,6 @@ export function transformDeclarations(context: TransformationContext): Transform reportExpandoFunctionErrors(node); } else { - // Don't report errors for function expressions that are arguments to call expressions - if ( - (node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction) && - isCallExpression(node.parent) - ) { - return; - } context.addDiagnostic(getIsolatedDeclarationError(node)); } }