@@ -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}
0 commit comments