From d5cf5aa6f95f291ae041978e8a9d900231e7f39a Mon Sep 17 00:00:00 2001 From: Pete Gonzalez <4673363+octogonz@users.noreply.github.com> Date: Mon, 28 Sep 2020 18:52:51 -0700 Subject: [PATCH 1/3] Add test case for typeOf bug --- .../config/build-config.json | 1 + .../src/typeOf3/index.ts | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 build-tests/api-extractor-scenarios/src/typeOf3/index.ts diff --git a/build-tests/api-extractor-scenarios/config/build-config.json b/build-tests/api-extractor-scenarios/config/build-config.json index ee4bc6e2718..80ec5180ec8 100644 --- a/build-tests/api-extractor-scenarios/config/build-config.json +++ b/build-tests/api-extractor-scenarios/config/build-config.json @@ -31,6 +31,7 @@ "preapproved", "typeOf", "typeOf2", + "typeOf3", "typeParameters" ] } diff --git a/build-tests/api-extractor-scenarios/src/typeOf3/index.ts b/build-tests/api-extractor-scenarios/src/typeOf3/index.ts new file mode 100644 index 00000000000..7a1063e7349 --- /dev/null +++ b/build-tests/api-extractor-scenarios/src/typeOf3/index.ts @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +/** + * A function that references its own parameter type. + */ +export function f1(x: number): typeof x { + return x; +} + +/** + * A function that indirectly references its own parameter type. + */ +export function f2(x: number): keyof typeof x { + return 'valueOf'; +} + +/** + * A function that references its own type. + */ +export function f3(): typeof f3 | undefined { + return undefined; +} From 6ca0cba723ad8428e6e099f12715ce799f29a73f Mon Sep 17 00:00:00 2001 From: Pete Gonzalez <4673363+octogonz@users.noreply.github.com> Date: Mon, 28 Sep 2020 18:53:00 -0700 Subject: [PATCH 2/3] Fix typeOf bug --- .../src/analyzer/ExportAnalyzer.ts | 11 ++ .../typeOf3/api-extractor-scenarios.api.json | 153 ++++++++++++++++++ .../typeOf3/api-extractor-scenarios.api.md | 19 +++ .../etc/test-outputs/typeOf3/rollup.d.ts | 17 ++ .../src/typeOf3/index.ts | 3 + 5 files changed, 203 insertions(+) create mode 100644 build-tests/api-extractor-scenarios/etc/test-outputs/typeOf3/api-extractor-scenarios.api.json create mode 100644 build-tests/api-extractor-scenarios/etc/test-outputs/typeOf3/api-extractor-scenarios.api.md create mode 100644 build-tests/api-extractor-scenarios/etc/test-outputs/typeOf3/rollup.d.ts diff --git a/apps/api-extractor/src/analyzer/ExportAnalyzer.ts b/apps/api-extractor/src/analyzer/ExportAnalyzer.ts index 7ac791ea39a..6400c1bc470 100644 --- a/apps/api-extractor/src/analyzer/ExportAnalyzer.ts +++ b/apps/api-extractor/src/analyzer/ExportAnalyzer.ts @@ -348,6 +348,17 @@ export class ExportAnalyzer { symbol: ts.Symbol, referringModuleIsExternal: boolean ): AstEntity | undefined { + // eslint-disable-next-line no-bitwise + if ((symbol.flags & ts.SymbolFlags.FunctionScopedVariable) !== 0) { + // 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; + // } + return undefined; + } + let current: ts.Symbol = symbol; if (referringModuleIsExternal) { diff --git a/build-tests/api-extractor-scenarios/etc/test-outputs/typeOf3/api-extractor-scenarios.api.json b/build-tests/api-extractor-scenarios/etc/test-outputs/typeOf3/api-extractor-scenarios.api.json new file mode 100644 index 00000000000..19f566fe69e --- /dev/null +++ b/build-tests/api-extractor-scenarios/etc/test-outputs/typeOf3/api-extractor-scenarios.api.json @@ -0,0 +1,153 @@ +{ + "metadata": { + "toolPackage": "@microsoft/api-extractor", + "toolVersion": "[test mode]", + "schemaVersion": 1003, + "oldestForwardsCompatibleVersion": 1001 + }, + "kind": "Package", + "canonicalReference": "api-extractor-scenarios!", + "docComment": "", + "name": "api-extractor-scenarios", + "members": [ + { + "kind": "EntryPoint", + "canonicalReference": "api-extractor-scenarios!", + "name": "", + "members": [ + { + "kind": "Function", + "canonicalReference": "api-extractor-scenarios!f1:function(1)", + "docComment": "/**\n * A function that references its own parameter type.\n */\n", + "excerptTokens": [ + { + "kind": "Content", + "text": "export declare function f1(x: " + }, + { + "kind": "Content", + "text": "number" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Content", + "text": "typeof " + }, + { + "kind": "Reference", + "text": "x", + "canonicalReference": "api-extractor-scenarios!~x:var" + }, + { + "kind": "Content", + "text": ";" + } + ], + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 5 + }, + "releaseTag": "Public", + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "x", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + } + } + ], + "name": "f1" + }, + { + "kind": "Function", + "canonicalReference": "api-extractor-scenarios!f2:function(1)", + "docComment": "/**\n * A function that indirectly references its own parameter type.\n */\n", + "excerptTokens": [ + { + "kind": "Content", + "text": "export declare function f2(x: " + }, + { + "kind": "Content", + "text": "number" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Content", + "text": "keyof typeof " + }, + { + "kind": "Reference", + "text": "x", + "canonicalReference": "api-extractor-scenarios!~x:var" + }, + { + "kind": "Content", + "text": ";" + } + ], + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 5 + }, + "releaseTag": "Public", + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "x", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + } + } + ], + "name": "f2" + }, + { + "kind": "Function", + "canonicalReference": "api-extractor-scenarios!f3:function(1)", + "docComment": "/**\n * A function that references its own type.\n */\n", + "excerptTokens": [ + { + "kind": "Content", + "text": "export declare function f3(): " + }, + { + "kind": "Content", + "text": "typeof " + }, + { + "kind": "Reference", + "text": "f3", + "canonicalReference": "api-extractor-scenarios!f3:function" + }, + { + "kind": "Content", + "text": " | undefined" + }, + { + "kind": "Content", + "text": ";" + } + ], + "returnTypeTokenRange": { + "startIndex": 1, + "endIndex": 4 + }, + "releaseTag": "Public", + "overloadIndex": 1, + "parameters": [], + "name": "f3" + } + ] + } + ] +} diff --git a/build-tests/api-extractor-scenarios/etc/test-outputs/typeOf3/api-extractor-scenarios.api.md b/build-tests/api-extractor-scenarios/etc/test-outputs/typeOf3/api-extractor-scenarios.api.md new file mode 100644 index 00000000000..eb5a7b06549 --- /dev/null +++ b/build-tests/api-extractor-scenarios/etc/test-outputs/typeOf3/api-extractor-scenarios.api.md @@ -0,0 +1,19 @@ +## 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 +export function f1(x: number): typeof x; + +// @public +export function f2(x: number): keyof typeof x; + +// @public +export function f3(): typeof f3 | undefined; + + +// (No @packageDocumentation comment for this package) + +``` diff --git a/build-tests/api-extractor-scenarios/etc/test-outputs/typeOf3/rollup.d.ts b/build-tests/api-extractor-scenarios/etc/test-outputs/typeOf3/rollup.d.ts new file mode 100644 index 00000000000..b6babbe2c89 --- /dev/null +++ b/build-tests/api-extractor-scenarios/etc/test-outputs/typeOf3/rollup.d.ts @@ -0,0 +1,17 @@ + +/** + * A function that references its own parameter type. + */ +export declare function f1(x: number): typeof x; + +/** + * A function that indirectly references its own parameter type. + */ +export declare function f2(x: number): keyof typeof x; + +/** + * A function that references its own type. + */ +export declare function f3(): typeof f3 | undefined; + +export { } diff --git a/build-tests/api-extractor-scenarios/src/typeOf3/index.ts b/build-tests/api-extractor-scenarios/src/typeOf3/index.ts index 7a1063e7349..5819fffecae 100644 --- a/build-tests/api-extractor-scenarios/src/typeOf3/index.ts +++ b/build-tests/api-extractor-scenarios/src/typeOf3/index.ts @@ -3,6 +3,7 @@ /** * A function that references its own parameter type. + * @public */ export function f1(x: number): typeof x { return x; @@ -10,6 +11,7 @@ export function f1(x: number): typeof x { /** * A function that indirectly references its own parameter type. + * @public */ export function f2(x: number): keyof typeof x { return 'valueOf'; @@ -17,6 +19,7 @@ export function f2(x: number): keyof typeof x { /** * A function that references its own type. + * @public */ export function f3(): typeof f3 | undefined { return undefined; From ef37bccaa1d9f4f7957b0fed4ab776f7cbecc10d Mon Sep 17 00:00:00 2001 From: Pete Gonzalez <4673363+octogonz@users.noreply.github.com> Date: Mon, 28 Sep 2020 18:59:06 -0700 Subject: [PATCH 3/3] rush change --- .../octgonz-ae-typeof-fix_2020-09-29-01-58.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@microsoft/api-extractor/octgonz-ae-typeof-fix_2020-09-29-01-58.json diff --git a/common/changes/@microsoft/api-extractor/octgonz-ae-typeof-fix_2020-09-29-01-58.json b/common/changes/@microsoft/api-extractor/octgonz-ae-typeof-fix_2020-09-29-01-58.json new file mode 100644 index 00000000000..76b1ccb8b87 --- /dev/null +++ b/common/changes/@microsoft/api-extractor/octgonz-ae-typeof-fix_2020-09-29-01-58.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "@microsoft/api-extractor", + "comment": "Fix an InternalError reported when a declaration referred to itself using \"tyepof\"", + "type": "patch" + } + ], + "packageName": "@microsoft/api-extractor", + "email": "4673363+octogonz@users.noreply.github.com" +} \ No newline at end of file