diff --git a/apps/api-extractor/src/analyzer/ExportAnalyzer.ts b/apps/api-extractor/src/analyzer/ExportAnalyzer.ts index ee5866578af..36c3bc2dfbf 100644 --- a/apps/api-extractor/src/analyzer/ExportAnalyzer.ts +++ b/apps/api-extractor/src/analyzer/ExportAnalyzer.ts @@ -376,14 +376,19 @@ export class ExportAnalyzer { symbol: ts.Symbol, referringModuleIsExternal: boolean ): AstEntity | undefined { - // eslint-disable-next-line no-bitwise - if ((symbol.flags & ts.SymbolFlags.FunctionScopedVariable) !== 0) { + if ( + // eslint-disable-next-line no-bitwise + (symbol.flags & ts.SymbolFlags.FunctionScopedVariable) !== 0 && + symbol.valueDeclaration?.kind !== ts.SyntaxKind.VariableDeclaration + ) { // If a symbol refers back to part of its own definition, don't follow that rabbit hole // Example: // // function f(x: number): typeof x { // return 123; // } + // + // TypeScript also uses this flag for "var" declarations, which are followed normally. return undefined; } diff --git a/build-tests/api-extractor-scenarios/etc/exportVar/api-extractor-scenarios.api.json b/build-tests/api-extractor-scenarios/etc/exportVar/api-extractor-scenarios.api.json new file mode 100644 index 00000000000..9c4146ad6a3 --- /dev/null +++ b/build-tests/api-extractor-scenarios/etc/exportVar/api-extractor-scenarios.api.json @@ -0,0 +1,240 @@ +{ + "metadata": { + "toolPackage": "@microsoft/api-extractor", + "toolVersion": "[test mode]", + "schemaVersion": 1011, + "oldestForwardsCompatibleVersion": 1001, + "tsdocConfig": { + "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", + "noStandardTags": true, + "tagDefinitions": [ + { + "tagName": "@alpha", + "syntaxKind": "modifier" + }, + { + "tagName": "@beta", + "syntaxKind": "modifier" + }, + { + "tagName": "@defaultValue", + "syntaxKind": "block" + }, + { + "tagName": "@decorator", + "syntaxKind": "block", + "allowMultiple": true + }, + { + "tagName": "@deprecated", + "syntaxKind": "block" + }, + { + "tagName": "@eventProperty", + "syntaxKind": "modifier" + }, + { + "tagName": "@example", + "syntaxKind": "block", + "allowMultiple": true + }, + { + "tagName": "@experimental", + "syntaxKind": "modifier" + }, + { + "tagName": "@inheritDoc", + "syntaxKind": "inline" + }, + { + "tagName": "@internal", + "syntaxKind": "modifier" + }, + { + "tagName": "@label", + "syntaxKind": "inline" + }, + { + "tagName": "@link", + "syntaxKind": "inline", + "allowMultiple": true + }, + { + "tagName": "@override", + "syntaxKind": "modifier" + }, + { + "tagName": "@packageDocumentation", + "syntaxKind": "modifier" + }, + { + "tagName": "@param", + "syntaxKind": "block", + "allowMultiple": true + }, + { + "tagName": "@privateRemarks", + "syntaxKind": "block" + }, + { + "tagName": "@public", + "syntaxKind": "modifier" + }, + { + "tagName": "@readonly", + "syntaxKind": "modifier" + }, + { + "tagName": "@remarks", + "syntaxKind": "block" + }, + { + "tagName": "@returns", + "syntaxKind": "block" + }, + { + "tagName": "@sealed", + "syntaxKind": "modifier" + }, + { + "tagName": "@see", + "syntaxKind": "block" + }, + { + "tagName": "@throws", + "syntaxKind": "block", + "allowMultiple": true + }, + { + "tagName": "@typeParam", + "syntaxKind": "block", + "allowMultiple": true + }, + { + "tagName": "@virtual", + "syntaxKind": "modifier" + }, + { + "tagName": "@jsx", + "syntaxKind": "block" + }, + { + "tagName": "@jsxRuntime", + "syntaxKind": "block" + }, + { + "tagName": "@jsxFrag", + "syntaxKind": "block" + }, + { + "tagName": "@jsxImportSource", + "syntaxKind": "block" + }, + { + "tagName": "@betaDocumentation", + "syntaxKind": "modifier" + }, + { + "tagName": "@internalRemarks", + "syntaxKind": "block" + }, + { + "tagName": "@preapproved", + "syntaxKind": "modifier" + } + ], + "supportForTags": { + "@alpha": true, + "@beta": true, + "@defaultValue": true, + "@decorator": true, + "@deprecated": true, + "@eventProperty": true, + "@example": true, + "@experimental": true, + "@inheritDoc": true, + "@internal": true, + "@label": true, + "@link": true, + "@override": true, + "@packageDocumentation": true, + "@param": true, + "@privateRemarks": true, + "@public": true, + "@readonly": true, + "@remarks": true, + "@returns": true, + "@sealed": true, + "@see": true, + "@throws": true, + "@typeParam": true, + "@virtual": true, + "@betaDocumentation": true, + "@internalRemarks": true, + "@preapproved": true + }, + "reportUnsupportedHtmlElements": false + } + }, + "kind": "Package", + "canonicalReference": "api-extractor-scenarios!", + "docComment": "", + "name": "api-extractor-scenarios", + "preserveMemberOrder": false, + "members": [ + { + "kind": "EntryPoint", + "canonicalReference": "api-extractor-scenarios!", + "name": "", + "preserveMemberOrder": false, + "members": [ + { + "kind": "Variable", + "canonicalReference": "api-extractor-scenarios!Var:var", + "docComment": "/**\n * @public\n */\n", + "excerptTokens": [ + { + "kind": "Content", + "text": "_default: " + }, + { + "kind": "Content", + "text": "{\n a: string;\n}" + } + ], + "fileUrlPath": "src/exportVar/var.ts", + "isReadonly": false, + "releaseTag": "Public", + "name": "Var", + "variableTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + } + }, + { + "kind": "Variable", + "canonicalReference": "api-extractor-scenarios!zero:var", + "docComment": "/**\n * @public\n */\n", + "excerptTokens": [ + { + "kind": "Content", + "text": "zero: " + }, + { + "kind": "Content", + "text": "number" + } + ], + "fileUrlPath": "src/exportVar/index.ts", + "isReadonly": false, + "releaseTag": "Public", + "name": "zero", + "variableTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + } + } + ] + } + ] +} diff --git a/build-tests/api-extractor-scenarios/etc/exportVar/api-extractor-scenarios.api.md b/build-tests/api-extractor-scenarios/etc/exportVar/api-extractor-scenarios.api.md new file mode 100644 index 00000000000..547e35b87d4 --- /dev/null +++ b/build-tests/api-extractor-scenarios/etc/exportVar/api-extractor-scenarios.api.md @@ -0,0 +1,17 @@ +## API Report File for "api-extractor-scenarios" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +// @public (undocumented) +export var Var: { + a: string; +}; + +// @public (undocumented) +export var zero: number; + +// (No @packageDocumentation comment for this package) + +``` diff --git a/build-tests/api-extractor-scenarios/etc/exportVar/rollup.d.ts b/build-tests/api-extractor-scenarios/etc/exportVar/rollup.d.ts new file mode 100644 index 00000000000..15ab8e696aa --- /dev/null +++ b/build-tests/api-extractor-scenarios/etc/exportVar/rollup.d.ts @@ -0,0 +1,9 @@ +/** @public */ +export declare var Var: { + a: string; +}; + +/** @public */ +export declare var zero: number; + +export { } diff --git a/build-tests/api-extractor-scenarios/src/exportVar/index.ts b/build-tests/api-extractor-scenarios/src/exportVar/index.ts new file mode 100644 index 00000000000..305b93e5f76 --- /dev/null +++ b/build-tests/api-extractor-scenarios/src/exportVar/index.ts @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +import Var from './var'; + +export { Var }; + +/** @public */ +export declare var zero: number; diff --git a/build-tests/api-extractor-scenarios/src/exportVar/var.ts b/build-tests/api-extractor-scenarios/src/exportVar/var.ts new file mode 100644 index 00000000000..09987bec901 --- /dev/null +++ b/build-tests/api-extractor-scenarios/src/exportVar/var.ts @@ -0,0 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +/** @public */ +declare var _default: { a: string }; +export default _default; diff --git a/common/changes/@microsoft/api-extractor/api-extractor-var-exports_2026-10-19-10-30-50.json b/common/changes/@microsoft/api-extractor/api-extractor-var-exports_2026-10-19-10-30-50.json new file mode 100644 index 00000000000..9a03f80a4ef --- /dev/null +++ b/common/changes/@microsoft/api-extractor/api-extractor-var-exports_2026-10-19-10-30-50.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "Fix an issue where an exported `var` declaration lost its name in the .d.ts rollup or caused an \"Unable to analyze the export\" error", + "type": "patch", + "packageName": "@microsoft/api-extractor" + } + ], + "packageName": "@microsoft/api-extractor", + "email": "yashvt9404@gmail.com" +} \ No newline at end of file