Skip to content

Commit b52b568

Browse files
committed
PR Feedback
1 parent 76df416 commit b52b568

10 files changed

Lines changed: 95 additions & 17 deletions

File tree

.vscode/settings.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,5 @@
1717
"temp": true,
1818
"**/test/**/temp": false,
1919
"coverage": true
20-
},
21-
"files.associations": {
22-
"rush.json": "jsonc",
2320
}
2421
}

apps/api-extractor/src/analyzer/AstSymbolTable.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,8 @@ export class AstSymbolTable {
433433
// but the declaration name is "X".
434434
localName = followedSymbol.name;
435435
if (TypeScriptHelpers.isWellKnownSymbolName(localName)) {
436+
// TypeScript binds well-known ECMAScript symbols like "Symbol.iterator" as "__@iterator".
437+
// This converts a string like "__@iterator" into the property name "[Symbol.iterator]".
436438
localName = `[Symbol.${localName.slice(3)}]`;
437439
} else {
438440
const isUniqueSymbol: boolean = TypeScriptHelpers.isUniqueSymbolName(localName);

apps/api-extractor/src/analyzer/TypeScriptHelpers.ts

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ export class TypeScriptHelpers {
210210
return highest;
211211
}
212212

213+
// Matches TypeScript's encoded names for well-known ECMAScript symbols like
214+
// "__@iterator" or "__@toStringTag".
213215
private static readonly _wellKnownSymbolNameRegExp: RegExp = /^__@\w+$/;
214216

215217
/**
@@ -219,6 +221,8 @@ export class TypeScriptHelpers {
219221
return TypeScriptHelpers._wellKnownSymbolNameRegExp.test(name);
220222
}
221223

224+
// Matches TypeScript's encoded names for late-bound symbols derived from `unique symbol` declarations
225+
// which have the form of "__@<variableName>@<symbolId>", i.e. "__@someSymbol@12345".
222226
private static readonly _uniqueSymbolNameRegExp: RegExp = /^__@.*@\d+$/;
223227

224228
/**
@@ -228,18 +232,25 @@ export class TypeScriptHelpers {
228232
return TypeScriptHelpers._uniqueSymbolNameRegExp.test(name);
229233
}
230234

235+
/**
236+
* Derives the string representation of a TypeScript late-bound symbol.
237+
*/
231238
public static tryGetLateBoundName(declarationName: ts.ComputedPropertyName): string | undefined {
232-
// Only a ComputedPropertyName whose expression is an EntityNameExpression can be
233-
// used as a late-bound name.
234-
let expressionName: string = '';
235-
let expression: ts.EntityNameExpression = declarationName.expression as ts.EntityNameExpression;
236-
while (expression.kind === ts.SyntaxKind.PropertyAccessExpression) {
237-
expressionName = `.${expression.name.getText().trim()}${expressionName}`;
238-
expression = expression.expression;
239-
}
240-
if (expression.kind !== ts.SyntaxKind.Identifier) {
241-
return undefined;
242-
}
243-
return `[${expression.getText().trim()}${expressionName}]`;
239+
// Create a node printer that ignores comments and indentation that we can use to convert
240+
// declarationName to a string.
241+
const printer: ts.Printer = ts.createPrinter({ removeComments: true }, {
242+
onEmitNode(hint: ts.EmitHint, node: ts.Node | undefined,
243+
emit: (hint: ts.EmitHint, node: ts.Node | undefined) => void): void {
244+
if (node) {
245+
ts.setEmitFlags(declarationName, ts.EmitFlags.NoIndentation | ts.EmitFlags.SingleLine);
246+
}
247+
emit(hint, node);
248+
}
249+
});
250+
const sourceFile: ts.SourceFile = declarationName.getSourceFile();
251+
const text: string = printer.printNode(ts.EmitHint.Unspecified, declarationName, sourceFile);
252+
// clean up any emit flags we've set on any nodes in the tree.
253+
ts.disposeEmitNodes(sourceFile);
254+
return text;
244255
}
245256
}

apps/api-extractor/src/analyzer/TypeScriptInternals.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,17 @@ export class TypeScriptInternals {
2424
public static tryGetSymbolForDeclaration(declaration: ts.Declaration, checker: ts.TypeChecker): ts.Symbol
2525
| undefined {
2626
let symbol: ts.Symbol | undefined = (declaration as any).symbol;
27-
if (symbol && symbol.escapedName === '__computed') {
27+
if (symbol && symbol.escapedName === ts.InternalSymbolName.Computed) {
2828
const name: ts.DeclarationName | undefined = ts.getNameOfDeclaration(declaration);
2929
symbol = name && checker.getSymbolAtLocation(name) || symbol;
3030
}
3131
return symbol;
3232
}
3333

34+
/**
35+
* Returns whether the provided Symbol is a TypeScript "late-bound" Symbol (i.e. was created by the Checker
36+
* for a computed property based on its type, rather than by the Binder).
37+
*/
3438
public static isLateBoundSymbol(symbol: ts.Symbol): boolean {
3539
// tslint:disable-next-line:no-bitwise
3640
if (symbol.flags & ts.SymbolFlags.Transient &&

build-tests/api-extractor-test-01/dist/api-extractor-test-01-beta.d.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111

1212
/// <reference types="jest" />
13+
/// <reference lib="es2015.symbol.wellknown" />
1314
/// <reference lib="es2018.intl" />
1415
import Long from 'long';
1516
import { MAX_UNSIGNED_VALUE } from 'long';
@@ -67,6 +68,13 @@ export declare class AmbientConsumer {
6768
localTypings(): IAmbientInterfaceExample;
6869
}
6970

71+
/** @public */
72+
declare namespace ANamespace {
73+
const locallyExportedCustomSymbol: unique symbol;
74+
/** @public */
75+
const fullyExportedCustomSymbol: unique symbol;
76+
}
77+
7078
/**
7179
* Referenced by DefaultExportEdgeCaseReferencer.
7280
* @public
@@ -110,6 +118,9 @@ export declare class ClassWithSymbols {
110118
readonly [unexportedCustomSymbol]: number;
111119
readonly [locallyExportedCustomSymbol]: string;
112120
[fullyExportedCustomSymbol](): void;
121+
readonly [ANamespace.locallyExportedCustomSymbol]: string;
122+
[ANamespace.fullyExportedCustomSymbol](): void;
123+
readonly [Symbol.toStringTag]: string;
113124
}
114125

115126
/**

build-tests/api-extractor-test-01/dist/api-extractor-test-01-public.d.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111

1212
/// <reference types="jest" />
13+
/// <reference lib="es2015.symbol.wellknown" />
1314
/// <reference lib="es2018.intl" />
1415
import Long from 'long';
1516
import { MAX_UNSIGNED_VALUE } from 'long';
@@ -67,6 +68,13 @@ export declare class AmbientConsumer {
6768
localTypings(): IAmbientInterfaceExample;
6869
}
6970

71+
/** @public */
72+
declare namespace ANamespace {
73+
const locallyExportedCustomSymbol: unique symbol;
74+
/** @public */
75+
const fullyExportedCustomSymbol: unique symbol;
76+
}
77+
7078
/**
7179
* Referenced by DefaultExportEdgeCaseReferencer.
7280
* @public
@@ -110,6 +118,9 @@ export declare class ClassWithSymbols {
110118
readonly [unexportedCustomSymbol]: number;
111119
readonly [locallyExportedCustomSymbol]: string;
112120
[fullyExportedCustomSymbol](): void;
121+
readonly [ANamespace.locallyExportedCustomSymbol]: string;
122+
[ANamespace.fullyExportedCustomSymbol](): void;
123+
readonly [Symbol.toStringTag]: string;
113124
}
114125

115126
/**

build-tests/api-extractor-test-01/dist/api-extractor-test-01.d.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111

1212
/// <reference types="jest" />
13+
/// <reference lib="es2015.symbol.wellknown" />
1314
/// <reference lib="es2018.intl" />
1415
import Long from 'long';
1516
import { MAX_UNSIGNED_VALUE } from 'long';
@@ -67,6 +68,13 @@ export declare class AmbientConsumer {
6768
localTypings(): IAmbientInterfaceExample;
6869
}
6970

71+
/** @public */
72+
declare namespace ANamespace {
73+
const locallyExportedCustomSymbol: unique symbol;
74+
/** @public */
75+
const fullyExportedCustomSymbol: unique symbol;
76+
}
77+
7078
/**
7179
* Referenced by DefaultExportEdgeCaseReferencer.
7280
* @public
@@ -110,6 +118,9 @@ export declare class ClassWithSymbols {
110118
readonly [unexportedCustomSymbol]: number;
111119
readonly [locallyExportedCustomSymbol]: string;
112120
[fullyExportedCustomSymbol](): void;
121+
readonly [ANamespace.locallyExportedCustomSymbol]: string;
122+
[ANamespace.fullyExportedCustomSymbol](): void;
123+
readonly [Symbol.toStringTag]: string;
113124
}
114125

115126
/**

build-tests/api-extractor-test-01/etc/api-extractor-test-01.api.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,19 @@ export class ClassWithAccessModifiers {
4848

4949
// @public (undocumented)
5050
export class ClassWithSymbols {
51+
// (undocumented)
52+
[ANamespace.fullyExportedCustomSymbol](): void;
53+
// Warning: (ae-forgotten-export) The symbol "ANamespace" needs to be exported by the entry point index.d.ts
54+
//
55+
// (undocumented)
56+
readonly [ANamespace.locallyExportedCustomSymbol]: string;
5157
// (undocumented)
5258
[fullyExportedCustomSymbol](): void;
5359
// (undocumented)
5460
readonly [locallyExportedCustomSymbol]: string;
5561
// (undocumented)
62+
readonly [Symbol.toStringTag]: string;
63+
// (undocumented)
5664
readonly [unexportedCustomSymbol]: number;
5765
}
5866

build-tests/api-extractor-test-01/src/EcmaScriptSymbols.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
22
// See LICENSE in the project root for license information.
33

4+
/// <reference lib="es2015.symbol.wellknown" />
5+
46
const unexportedCustomSymbol: unique symbol = Symbol('unexportedCustomSymbol');
57
export const locallyExportedCustomSymbol: unique symbol = Symbol('locallyExportedCustomSymbol');
68

79
/** @public */
810
export const fullyExportedCustomSymbol: unique symbol = Symbol('fullyExportedCustomSymbol');
911

12+
// NOTE: named 'ANamespace' so that it appears earlier in the rollup .d.ts file, due to
13+
// https://github.com/microsoft/TypeScript/issues/31746
14+
/** @public */
15+
export namespace ANamespace {
16+
export const locallyExportedCustomSymbol: unique symbol = Symbol('locallyExportedCustomSymbol');
17+
18+
/** @public */
19+
export const fullyExportedCustomSymbol: unique symbol = Symbol('fullyExportedCustomSymbol');
20+
}
21+
1022
/**
1123
* @public
1224
*/
@@ -19,4 +31,15 @@ export class ClassWithSymbols {
1931

2032
public [fullyExportedCustomSymbol](): void {
2133
}
34+
35+
public get [ANamespace.locallyExportedCustomSymbol](): string {
36+
return 'hello';
37+
}
38+
39+
public [ANamespace.fullyExportedCustomSymbol](): void {
40+
}
41+
42+
public get [Symbol.toStringTag](): string {
43+
return "ClassWithSymbols";
44+
}
2245
}

common/changes/@microsoft/api-extractor/supportSymbolMembers_2019-05-29-22-28.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"changes": [
33
{
44
"packageName": "@microsoft/api-extractor",
5-
"comment": "Improved handling of symbolic property and method names.",
5+
"comment": "Improve handling of symbolic property and method names.",
66
"type": "patch"
77
}
88
],

0 commit comments

Comments
 (0)