From c05fac72fba8d700e8e0f7b32ebeb3e3905199e7 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sat, 16 Apr 2016 12:58:12 -0700 Subject: [PATCH] Use an element access when displaying literal members. --- src/compiler/checker.ts | 40 +++++++++++++++++++++++++++++++++------ src/compiler/utilities.ts | 4 ++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5e001347e06..761c6b2414d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1808,12 +1808,38 @@ namespace ts { /** * Writes only the name of the symbol out to the writer. Uses the original source text - * for the name of the symbol if it is available to match how the user inputted the name. + * for the name of the symbol if it is available to match how the user wrote the name. */ function appendSymbolNameOnly(symbol: Symbol, writer: SymbolWriter): void { writer.writeSymbol(getNameOfSymbol(symbol), symbol); } + /** + * Writes a property access or element access with the name of the symbol out to the writer. + * Uses the original source text for the name of the symbol if it is available to match how the user wrote the name, + * ensuring that any names written with literals use element accesses. + */ + function appendPropertyOrElementAccessForSymbol(symbol: Symbol, writer: SymbolWriter): void { + const symbolName = getNameOfSymbol(symbol); + const firstChar = symbolName.charCodeAt(0); + const needsElementAccess = !isIdentifierStart(firstChar, languageVersion); + + if (needsElementAccess) { + writePunctuation(writer, SyntaxKind.OpenBracketToken); + if (isSingleOrDoubleQuote(firstChar)) { + writer.writeStringLiteral(symbolName); + } + else { + writer.writeSymbol(symbolName, symbol); + } + writePunctuation(writer, SyntaxKind.CloseBracketToken); + } + else { + writePunctuation(writer, SyntaxKind.DotToken); + writer.writeSymbol(symbolName, symbol); + } + } + /** * Enclosing declaration is optional when we don't want to get qualified name in the enclosing declaration scope * Meaning needs to be specified if the enclosing declaration is given @@ -1832,10 +1858,12 @@ namespace ts { buildTypeParameterDisplayFromSymbol(parentSymbol, writer, enclosingDeclaration); } } - writePunctuation(writer, SyntaxKind.DotToken); + appendPropertyOrElementAccessForSymbol(symbol, writer); + } + else { + appendSymbolNameOnly(symbol, writer); } parentSymbol = symbol; - appendSymbolNameOnly(symbol, writer); } // const the writer know we just wrote out a symbol. The declaration emitter writer uses @@ -2030,10 +2058,10 @@ namespace ts { if (symbol) { // Always use 'typeof T' for type of class, enum, and module objects if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) { - writeTypeofSymbol(type, flags); + writeTypeOSymbol(type, flags); } else if (shouldWriteTypeOfFunctionSymbol()) { - writeTypeofSymbol(type, flags); + writeTypeOSymbol(type, flags); } else if (contains(symbolStack, symbol)) { // If type is an anonymous type literal in a type alias declaration, use type alias name @@ -2078,7 +2106,7 @@ namespace ts { } } - function writeTypeofSymbol(type: ObjectType, typeFormatFlags?: TypeFormatFlags) { + function writeTypeOSymbol(type: ObjectType, typeFormatFlags?: TypeFormatFlags) { writeKeyword(writer, SyntaxKind.TypeOfKeyword); writeSpace(writer); buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Value, SymbolFormatFlags.None, typeFormatFlags); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 660f12b99e0..e9f63918bbd 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1196,6 +1196,10 @@ namespace ts { return isRequire && (!checkArgumentIsStringLiteral || (expression).arguments[0].kind === SyntaxKind.StringLiteral); } + export function isSingleOrDoubleQuote(charCode: number) { + return charCode === CharacterCodes.singleQuote || charCode === CharacterCodes.doubleQuote; + } + /// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property /// assignments we treat as special in the binder export function getSpecialPropertyAssignmentKind(expression: Node): SpecialPropertyAssignmentKind {