From 042a78d2dccf6461850e1b000263fa8aa7069586 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 30 Jun 2017 15:46:07 -0700 Subject: [PATCH 01/25] Created a branded type for escaped strings Then flowed it throughout the compiler, finding and fixing a handful of bugs relating to underscore-prefixed identifiers in the process. Includes a test for two cases noticed - diagnostics from conflicting symbols from export *'s, and enum with underscore prefixed member emit. --- src/compiler/binder.ts | 103 ++-- src/compiler/checker.ts | 491 +++++++++--------- src/compiler/commandLineParser.ts | 2 +- src/compiler/core.ts | 41 +- src/compiler/declarationEmitter.ts | 6 +- src/compiler/emitter.ts | 10 +- src/compiler/factory.ts | 8 +- src/compiler/parser.ts | 33 +- src/compiler/program.ts | 4 +- src/compiler/transformers/destructuring.ts | 2 +- src/compiler/transformers/es2015.ts | 10 +- src/compiler/transformers/es2017.ts | 2 +- src/compiler/transformers/es5.ts | 2 +- src/compiler/transformers/esnext.ts | 2 +- src/compiler/transformers/generators.ts | 16 +- src/compiler/transformers/jsx.ts | 6 +- src/compiler/transformers/module/module.ts | 2 +- src/compiler/transformers/module/system.ts | 12 +- src/compiler/transformers/ts.ts | 4 +- src/compiler/transformers/utilities.ts | 18 +- src/compiler/types.ts | 29 +- src/compiler/utilities.ts | 42 +- src/services/classifier.ts | 4 +- src/services/codefixes/helpers.ts | 2 +- src/services/codefixes/importFixes.ts | 2 +- src/services/completions.ts | 26 +- src/services/documentHighlights.ts | 2 +- src/services/findAllReferences.ts | 25 +- src/services/goToDefinition.ts | 4 +- src/services/importTracker.ts | 6 +- src/services/jsDoc.ts | 6 +- src/services/navigateTo.ts | 12 +- src/services/navigationBar.ts | 10 +- src/services/pathCompletions.ts | 2 +- .../refactors/convertFunctionToEs6Class.ts | 2 +- src/services/services.ts | 32 +- src/services/signatureHelp.ts | 6 +- src/services/types.ts | 2 +- src/services/utilities.ts | 4 +- .../doubleUnderscoreSymbolsAndEmit.errors.txt | 60 +++ .../doubleUnderscoreSymbolsAndEmit.js | 112 ++++ .../doubleUnderscoreSymbolsAndEmit.ts | 58 +++ 42 files changed, 749 insertions(+), 473 deletions(-) create mode 100644 tests/baselines/reference/doubleUnderscoreSymbolsAndEmit.errors.txt create mode 100644 tests/baselines/reference/doubleUnderscoreSymbolsAndEmit.js create mode 100644 tests/cases/compiler/doubleUnderscoreSymbolsAndEmit.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 6975d431a112e..d8b34bbbaa707 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -132,8 +132,8 @@ namespace ts { let inStrictMode: boolean; let symbolCount = 0; - let Symbol: { new (flags: SymbolFlags, name: string): Symbol }; - let classifiableNames: Map; + let Symbol: { new (flags: SymbolFlags, name: EscapedIdentifier): Symbol }; + let classifiableNames: EscapedIdentifierMap; const unreachableFlow: FlowNode = { flags: FlowFlags.Unreachable }; const reportedUnreachableFlow: FlowNode = { flags: FlowFlags.Unreachable }; @@ -147,7 +147,7 @@ namespace ts { options = opts; languageVersion = getEmitScriptTarget(options); inStrictMode = bindInStrictMode(file, opts); - classifiableNames = createMap(); + classifiableNames = createMap() as EscapedIdentifierMap; symbolCount = 0; skipTransformFlagAggregation = file.isDeclarationFile; @@ -191,7 +191,7 @@ namespace ts { } } - function createSymbol(flags: SymbolFlags, name: string): Symbol { + function createSymbol(flags: SymbolFlags, name: EscapedIdentifier): Symbol { symbolCount++; return new Symbol(flags, name); } @@ -207,11 +207,11 @@ namespace ts { symbol.declarations.push(node); if (symbolFlags & SymbolFlags.HasExports && !symbol.exports) { - symbol.exports = createMap(); + symbol.exports = createSymbolTable(); } if (symbolFlags & SymbolFlags.HasMembers && !symbol.members) { - symbol.members = createMap(); + symbol.members = createSymbolTable(); } if (symbolFlags & SymbolFlags.Value) { @@ -226,62 +226,63 @@ namespace ts { // Should not be called on a declaration with a computed property name, // unless it is a well known Symbol. - function getDeclarationName(node: Declaration): string { + function getDeclarationName(node: Declaration): EscapedIdentifier { const name = getNameOfDeclaration(node); if (name) { if (isAmbientModule(node)) { - return isGlobalScopeAugmentation(node) ? "__global" : `"${(name).text}"`; + const moduleName = name.kind === SyntaxKind.Identifier ? unescapeIdentifier((name).text) : (name).text; + return (isGlobalScopeAugmentation(node) ? "__global" : `"${moduleName}"`) as EscapedIdentifier; } if (name.kind === SyntaxKind.ComputedPropertyName) { const nameExpression = (name).expression; // treat computed property names where expression is string/numeric literal as just string/numeric literal if (isStringOrNumericLiteral(nameExpression)) { - return nameExpression.text; + return nameExpression.text && escapeIdentifier(nameExpression.text); } Debug.assert(isWellKnownSymbolSyntactically(nameExpression)); - return getPropertyNameForKnownSymbolName((nameExpression).name.text); + return getPropertyNameForKnownSymbolName(unescapeIdentifier((nameExpression).name.text)); } - return (name).text; + return name.kind === SyntaxKind.Identifier ? (name).text : ((name).text && escapeIdentifier((name).text)); // A literal expression used as a symbol name _must_ be escaped } switch (node.kind) { case SyntaxKind.Constructor: - return "__constructor"; + return "__constructor" as EscapedIdentifier; case SyntaxKind.FunctionType: case SyntaxKind.CallSignature: - return "__call"; + return "__call" as EscapedIdentifier; case SyntaxKind.ConstructorType: case SyntaxKind.ConstructSignature: - return "__new"; + return "__new" as EscapedIdentifier; case SyntaxKind.IndexSignature: - return "__index"; + return "__index" as EscapedIdentifier; case SyntaxKind.ExportDeclaration: - return "__export"; + return "__export" as EscapedIdentifier; case SyntaxKind.ExportAssignment: - return (node).isExportEquals ? "export=" : "default"; + return ((node).isExportEquals ? "export=" : "default") as EscapedIdentifier; case SyntaxKind.BinaryExpression: if (getSpecialPropertyAssignmentKind(node as BinaryExpression) === SpecialPropertyAssignmentKind.ModuleExports) { // module.exports = ... - return "export="; + return "export=" as EscapedIdentifier; } Debug.fail("Unknown binary declaration kind"); break; case SyntaxKind.FunctionDeclaration: case SyntaxKind.ClassDeclaration: - return hasModifier(node, ModifierFlags.Default) ? "default" : undefined; + return (hasModifier(node, ModifierFlags.Default) ? "default" : undefined) as EscapedIdentifier; case SyntaxKind.JSDocFunctionType: - return isJSDocConstructSignature(node) ? "__new" : "__call"; + return (isJSDocConstructSignature(node) ? "__new" : "__call") as EscapedIdentifier; case SyntaxKind.Parameter: // Parameters with names are handled at the top of this function. Parameters // without names can only come from JSDocFunctionTypes. Debug.assert(node.parent.kind === SyntaxKind.JSDocFunctionType); const functionType = node.parent; const index = indexOf(functionType.parameters, node); - return "arg" + index; + return "arg" + index as EscapedIdentifier; case SyntaxKind.JSDocTypedefTag: const parentNode = node.parent && node.parent.parent; - let nameFromParentNode: string; + let nameFromParentNode: EscapedIdentifier; if (parentNode && parentNode.kind === SyntaxKind.VariableStatement) { if ((parentNode).declarationList.declarations.length > 0) { const nameIdentifier = (parentNode).declarationList.declarations[0].name; @@ -295,7 +296,7 @@ namespace ts { } function getDisplayName(node: Declaration): string { - return (node as NamedDeclaration).name ? declarationNameToString((node as NamedDeclaration).name) : getDeclarationName(node); + return (node as NamedDeclaration).name ? declarationNameToString((node as NamedDeclaration).name) : unescapeIdentifier(getDeclarationName(node)); } /** @@ -312,11 +313,11 @@ namespace ts { const isDefaultExport = hasModifier(node, ModifierFlags.Default); // The exported symbol for an export default function/class node is always named "default" - const name = isDefaultExport && parent ? "default" : getDeclarationName(node); + const name = isDefaultExport && parent ? ("default" as EscapedIdentifier) : getDeclarationName(node); let symbol: Symbol; if (name === undefined) { - symbol = createSymbol(SymbolFlags.None, "__missing"); + symbol = createSymbol(SymbolFlags.None, "__missing" as EscapedIdentifier); } else { // Check and see if the symbol table already has a symbol with this name. If not, @@ -481,7 +482,7 @@ namespace ts { if (containerFlags & ContainerFlags.IsContainer) { container = blockScopeContainer = node; if (containerFlags & ContainerFlags.HasLocals) { - container.locals = createMap(); + container.locals = createSymbolTable(); } addToContainerChain(container); } @@ -1028,7 +1029,7 @@ namespace ts { function bindBreakOrContinueStatement(node: BreakOrContinueStatement): void { bind(node.label); if (node.label) { - const activeLabel = findActiveLabel(node.label.text); + const activeLabel = findActiveLabel(unescapeIdentifier(node.label.text)); if (activeLabel) { activeLabel.referenced = true; bindBreakOrContinueFlow(node, activeLabel.breakTarget, activeLabel.continueTarget); @@ -1189,7 +1190,7 @@ namespace ts { const postStatementLabel = createBranchLabel(); bind(node.label); addAntecedent(preStatementLabel, currentFlow); - const activeLabel = pushActiveLabel(node.label.text, postStatementLabel, preStatementLabel); + const activeLabel = pushActiveLabel(unescapeIdentifier(node.label.text), postStatementLabel, preStatementLabel); bind(node.statement); popActiveLabel(); if (!activeLabel.referenced && !options.allowUnusedLabels) { @@ -1645,9 +1646,9 @@ namespace ts { const symbol = createSymbol(SymbolFlags.Signature, getDeclarationName(node)); addDeclarationToSymbol(symbol, node, SymbolFlags.Signature); - const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type"); + const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type" as EscapedIdentifier); addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral); - typeLiteralSymbol.members = createMap(); + typeLiteralSymbol.members = createSymbolTable(); typeLiteralSymbol.members.set(symbol.name, symbol); } @@ -1658,7 +1659,7 @@ namespace ts { } if (inStrictMode) { - const seen = createMap(); + const seen = createMap() as EscapedIdentifierMap; for (const prop of node.properties) { if (prop.kind === SyntaxKind.SpreadAssignment || prop.name.kind !== SyntaxKind.Identifier) { @@ -1693,18 +1694,18 @@ namespace ts { } } - return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__object"); + return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__object" as EscapedIdentifier); } function bindJsxAttributes(node: JsxAttributes) { - return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__jsxAttributes"); + return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__jsxAttributes" as EscapedIdentifier); } function bindJsxAttribute(node: JsxAttribute, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { return declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } - function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: string) { + function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: EscapedIdentifier) { const symbol = createSymbol(symbolFlags, name); addDeclarationToSymbol(symbol, node, symbolFlags); } @@ -1722,7 +1723,7 @@ namespace ts { // falls through default: if (!blockScopeContainer.locals) { - blockScopeContainer.locals = createMap(); + blockScopeContainer.locals = createSymbolTable(); addToContainerChain(blockScopeContainer); } declareSymbol(blockScopeContainer.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); @@ -1803,7 +1804,7 @@ namespace ts { // otherwise report generic error message. const span = getErrorSpanForNode(file, name); file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, - getStrictModeEvalOrArgumentsMessage(contextNode), identifier.text)); + getStrictModeEvalOrArgumentsMessage(contextNode), unescapeIdentifier(identifier.text))); } } } @@ -1895,8 +1896,8 @@ namespace ts { file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); } - function getDestructuringParameterName(node: Declaration) { - return "__" + indexOf((node.parent).parameters, node); + function getDestructuringParameterName(node: Declaration): EscapedIdentifier { + return "__" + indexOf((node.parent).parameters, node) as EscapedIdentifier; } function bind(node: Node): void { @@ -2190,7 +2191,7 @@ namespace ts { } function bindAnonymousTypeWorker(node: TypeLiteralNode | MappedTypeNode | JSDocTypeLiteral | JSDocRecordType) { - return bindAnonymousDeclaration(node, SymbolFlags.TypeLiteral, "__type"); + return bindAnonymousDeclaration(node, SymbolFlags.TypeLiteral, "__type" as EscapedIdentifier); } function checkTypePredicate(node: TypePredicateNode) { @@ -2212,7 +2213,7 @@ namespace ts { } function bindSourceFileAsExternalModule() { - bindAnonymousDeclaration(file, SymbolFlags.ValueModule, `"${removeFileExtension(file.fileName)}"`); + bindAnonymousDeclaration(file, SymbolFlags.ValueModule, `"${removeFileExtension(file.fileName)}"` as EscapedIdentifier); } function bindExportAssignment(node: ExportAssignment | BinaryExpression) { @@ -2256,7 +2257,7 @@ namespace ts { } } - file.symbol.globalExports = file.symbol.globalExports || createMap(); + file.symbol.globalExports = file.symbol.globalExports || createSymbolTable(); declareSymbol(file.symbol.globalExports, file.symbol, node, SymbolFlags.Alias, SymbolFlags.AliasExcludes); } @@ -2341,7 +2342,7 @@ namespace ts { case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: // Declare a 'member' if the container is an ES5 class or ES6 constructor - container.symbol.members = container.symbol.members || createMap(); + container.symbol.members = container.symbol.members || createSymbolTable(); // It's acceptable for multiple 'this' assignments of the same identifier to occur declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property); break; @@ -2403,11 +2404,11 @@ namespace ts { } } - function lookupSymbolForName(name: string) { + function lookupSymbolForName(name: EscapedIdentifier) { return (container.symbol && container.symbol.exports && container.symbol.exports.get(name)) || (container.locals && container.locals.get(name)); } - function bindPropertyAssignment(functionName: string, propertyAccessExpression: PropertyAccessExpression, isPrototypeProperty: boolean) { + function bindPropertyAssignment(functionName: EscapedIdentifier, propertyAccessExpression: PropertyAccessExpression, isPrototypeProperty: boolean) { let targetSymbol = lookupSymbolForName(functionName); if (targetSymbol && isDeclarationOfFunctionOrClassExpression(targetSymbol)) { @@ -2420,8 +2421,8 @@ namespace ts { // Set up the members collection if it doesn't exist already const symbolTable = isPrototypeProperty ? - (targetSymbol.members || (targetSymbol.members = createMap())) : - (targetSymbol.exports || (targetSymbol.exports = createMap())); + (targetSymbol.members || (targetSymbol.members = createSymbolTable())) : + (targetSymbol.exports || (targetSymbol.exports = createSymbolTable())); // Declare the method/property declareSymbol(symbolTable, targetSymbol, propertyAccessExpression, SymbolFlags.Property, SymbolFlags.PropertyExcludes); @@ -2440,7 +2441,7 @@ namespace ts { bindBlockScopedDeclaration(node, SymbolFlags.Class, SymbolFlags.ClassExcludes); } else { - const bindingName = node.name ? node.name.text : "__class"; + const bindingName = node.name ? node.name.text : "__class" as EscapedIdentifier; bindAnonymousDeclaration(node, SymbolFlags.Class, bindingName); // Add name of class expression into the map for semantic classifier if (node.name) { @@ -2459,13 +2460,13 @@ namespace ts { // Note: we check for this here because this class may be merging into a module. The // module might have an exported variable called 'prototype'. We can't allow that as // that would clash with the built-in 'prototype' for the class. - const prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype"); + const prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype" as EscapedIdentifier); const symbolExport = symbol.exports.get(prototypeSymbol.name); if (symbolExport) { if (node.name) { node.name.parent = node; } - file.bindDiagnostics.push(createDiagnosticForNode(symbolExport.declarations[0], Diagnostics.Duplicate_identifier_0, prototypeSymbol.name)); + file.bindDiagnostics.push(createDiagnosticForNode(symbolExport.declarations[0], Diagnostics.Duplicate_identifier_0, unescapeIdentifier(prototypeSymbol.name))); } symbol.exports.set(prototypeSymbol.name, prototypeSymbol); prototypeSymbol.parent = symbol; @@ -2553,7 +2554,7 @@ namespace ts { node.flowNode = currentFlow; } checkStrictModeFunctionName(node); - const bindingName = node.name ? node.name.text : "__function"; + const bindingName = node.name ? node.name.text : "__function" as EscapedIdentifier; return bindAnonymousDeclaration(node, SymbolFlags.Function, bindingName); } @@ -2567,7 +2568,7 @@ namespace ts { } return hasDynamicName(node) - ? bindAnonymousDeclaration(node, symbolFlags, "__computed") + ? bindAnonymousDeclaration(node, symbolFlags, "__computed" as EscapedIdentifier) : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bc2f859f8ecb9..94bb6ffc83fae 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -57,7 +57,7 @@ namespace ts { let symbolInstantiationDepth = 0; const emptyArray: any[] = []; - const emptySymbols = createMap(); + const emptySymbols = createSymbolTable(); const compilerOptions = host.getCompilerOptions(); const languageVersion = getEmitScriptTarget(compilerOptions); @@ -71,9 +71,9 @@ namespace ts { const emitResolver = createResolver(); const nodeBuilder = createNodeBuilder(); - const undefinedSymbol = createSymbol(SymbolFlags.Property, "undefined"); + const undefinedSymbol = createSymbol(SymbolFlags.Property, "undefined" as EscapedIdentifier); undefinedSymbol.declarations = []; - const argumentsSymbol = createSymbol(SymbolFlags.Property, "arguments"); + const argumentsSymbol = createSymbol(SymbolFlags.Property, "arguments" as EscapedIdentifier); /** This will be set during calls to `getResolvedSignature` where services determines an apparent number of arguments greater than what is actually provided. */ let apparentArgumentCount: number | undefined; @@ -101,11 +101,11 @@ namespace ts { getSymbolsOfParameterPropertyDeclaration: (parameter, parameterName) => { parameter = getParseTreeNode(parameter, isParameter); Debug.assert(parameter !== undefined, "Cannot get symbols of a synthetic parameter that cannot be resolved to a parse-tree node."); - return getSymbolsOfParameterPropertyDeclaration(parameter, parameterName); + return getSymbolsOfParameterPropertyDeclaration(parameter, escapeIdentifier(parameterName)); }, getDeclaredTypeOfSymbol, getPropertiesOfType, - getPropertyOfType, + getPropertyOfType: (type, name) => getPropertyOfType(type, escapeIdentifier(name)), getIndexInfoOfType, getSignaturesOfType, getIndexTypeOfType, @@ -176,7 +176,7 @@ namespace ts { }, isValidPropertyAccess: (node, propertyName) => { node = getParseTreeNode(node, isPropertyAccessOrQualifiedName); - return node ? isValidPropertyAccess(node, propertyName) : false; + return node ? isValidPropertyAccess(node, escapeIdentifier(propertyName)) : false; }, getSignatureFromDeclaration: declaration => { declaration = getParseTreeNode(declaration, isFunctionLike); @@ -211,7 +211,7 @@ namespace ts { node = getParseTreeNode(node, isParameter); return node ? isOptionalParameter(node) : false; }, - tryGetMemberInModuleExports, + tryGetMemberInModuleExports: (name, symbol) => tryGetMemberInModuleExports(escapeIdentifier(name), symbol), tryFindAmbientModuleWithoutAugmentations: moduleName => { // we deliberately exclude augmentations // since we are only interested in declarations of the module itself @@ -219,13 +219,13 @@ namespace ts { }, getApparentType, getAllPossiblePropertiesOfType, - getSuggestionForNonexistentProperty, - getSuggestionForNonexistentSymbol, + getSuggestionForNonexistentProperty: (node, type) => unescapeIdentifier(getSuggestionForNonexistentProperty(node, type)), + getSuggestionForNonexistentSymbol: (location, name, meaning) => unescapeIdentifier(getSuggestionForNonexistentSymbol(location, escapeIdentifier(name), meaning)), getBaseConstraintOfType, - getJsxNamespace, + getJsxNamespace: () => unescapeIdentifier(getJsxNamespace()), resolveNameAtLocation(location: Node, name: string, meaning: SymbolFlags): Symbol | undefined { location = getParseTreeNode(location); - return resolveName(location, name, meaning, /*nameNotFoundMessage*/ undefined, name); + return resolveName(location, escapeIdentifier(name), meaning, /*nameNotFoundMessage*/ undefined, escapeIdentifier(name)); }, }; @@ -236,8 +236,8 @@ namespace ts { const indexedAccessTypes = createMap(); const evolvingArrayTypes: EvolvingArrayType[] = []; - const unknownSymbol = createSymbol(SymbolFlags.Property, "unknown"); - const resolvingSymbol = createSymbol(0, "__resolving__"); + const unknownSymbol = createSymbol(SymbolFlags.Property, "unknown" as EscapedIdentifier); + const resolvingSymbol = createSymbol(0, "__resolving__" as EscapedIdentifier); const anyType = createIntrinsicType(TypeFlags.Any, "any"); const autoType = createIntrinsicType(TypeFlags.Any, "any"); @@ -259,8 +259,8 @@ namespace ts { const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - const emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type"); - emptyTypeLiteralSymbol.members = createMap(); + const emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type" as EscapedIdentifier); + emptyTypeLiteralSymbol.members = createSymbolTable(); const emptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, emptyArray, emptyArray, undefined, undefined); const emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); @@ -282,7 +282,7 @@ namespace ts { const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true); const jsObjectLiteralIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false); - const globals = createMap(); + const globals = createSymbolTable(); /** * List of every ambient module with a "*" wildcard. * Unlike other ambient modules, these can't be stored in `globals` because symbol tables only deal with exact matches. @@ -444,25 +444,25 @@ namespace ts { }); const typeofType = createTypeofType(); - let _jsxNamespace: string; + let _jsxNamespace: EscapedIdentifier; let _jsxFactoryEntity: EntityName; - let _jsxElementPropertiesName: string; + let _jsxElementPropertiesName: EscapedIdentifier; let _hasComputedJsxElementPropertiesName = false; - let _jsxElementChildrenPropertyName: string; + let _jsxElementChildrenPropertyName: EscapedIdentifier; let _hasComputedJsxElementChildrenPropertyName = false; /** Things we lazy load from the JSX namespace */ - const jsxTypes = createMap(); + const jsxTypes = createMap() as EscapedIdentifierMap; const JsxNames = { - JSX: "JSX", - IntrinsicElements: "IntrinsicElements", - ElementClass: "ElementClass", - ElementAttributesPropertyNameContainer: "ElementAttributesProperty", - ElementChildrenAttributeNameContainer: "ElementChildrenAttribute", - Element: "Element", - IntrinsicAttributes: "IntrinsicAttributes", - IntrinsicClassAttributes: "IntrinsicClassAttributes" + JSX: "JSX" as EscapedIdentifier, + IntrinsicElements: "IntrinsicElements" as EscapedIdentifier, + ElementClass: "ElementClass" as EscapedIdentifier, + ElementAttributesPropertyNameContainer: "ElementAttributesProperty" as EscapedIdentifier, + ElementChildrenAttributeNameContainer: "ElementChildrenAttribute" as EscapedIdentifier, + Element: "Element" as EscapedIdentifier, + IntrinsicAttributes: "IntrinsicAttributes" as EscapedIdentifier, + IntrinsicClassAttributes: "IntrinsicClassAttributes" as EscapedIdentifier }; const subtypeRelation = createMap(); @@ -489,16 +489,16 @@ namespace ts { Inferential = 2, // Inferential typing } - const builtinGlobals = createMap(); + const builtinGlobals = createSymbolTable(); builtinGlobals.set(undefinedSymbol.name, undefinedSymbol); initializeTypeChecker(); return checker; - function getJsxNamespace(): string { + function getJsxNamespace(): EscapedIdentifier { if (!_jsxNamespace) { - _jsxNamespace = "React"; + _jsxNamespace = "React" as EscapedIdentifier; if (compilerOptions.jsxFactory) { _jsxFactoryEntity = parseIsolatedEntityName(compilerOptions.jsxFactory, languageVersion); if (_jsxFactoryEntity) { @@ -506,7 +506,7 @@ namespace ts { } } else if (compilerOptions.reactNamespace) { - _jsxNamespace = compilerOptions.reactNamespace; + _jsxNamespace = escapeIdentifier(compilerOptions.reactNamespace); } } return _jsxNamespace; @@ -526,7 +526,7 @@ namespace ts { diagnostics.add(diagnostic); } - function createSymbol(flags: SymbolFlags, name: string) { + function createSymbol(flags: SymbolFlags, name: EscapedIdentifier) { symbolCount++; const symbol = (new Symbol(flags | SymbolFlags.Transient, name)); symbol.checkFlags = 0; @@ -593,11 +593,11 @@ namespace ts { } addRange(target.declarations, source.declarations); if (source.members) { - if (!target.members) target.members = createMap(); + if (!target.members) target.members = createSymbolTable(); mergeSymbolTable(target.members, source.members); } if (source.exports) { - if (!target.exports) target.exports = createMap(); + if (!target.exports) target.exports = createSymbolTable(); mergeSymbolTable(target.exports, source.exports); } recordMergedSymbol(target, source); @@ -675,7 +675,7 @@ namespace ts { const targetSymbol = target.get(id); if (targetSymbol) { // Error on redeclarations - forEach(targetSymbol.declarations, addDeclarationDiagnostic(id, message)); + forEach(targetSymbol.declarations, addDeclarationDiagnostic(unescapeIdentifier(id), message)); } else { target.set(id, sourceSymbol); @@ -706,7 +706,7 @@ namespace ts { return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(node); } - function getSymbol(symbols: SymbolTable, name: string, meaning: SymbolFlags): Symbol { + function getSymbol(symbols: SymbolTable, name: EscapedIdentifier, meaning: SymbolFlags): Symbol { if (meaning) { const symbol = symbols.get(name); if (symbol) { @@ -732,7 +732,7 @@ namespace ts { * @param parameterName a name of the parameter to get the symbols for. * @return a tuple of two symbols */ - function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): [Symbol, Symbol] { + function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: EscapedIdentifier): [Symbol, Symbol] { const constructorDeclaration = parameter.parent; const classDeclaration = parameter.parent.parent; @@ -855,21 +855,21 @@ namespace ts { // the given name can be found. function resolveName( location: Node | undefined, - name: string, + name: EscapedIdentifier, meaning: SymbolFlags, nameNotFoundMessage: DiagnosticMessage | undefined, - nameArg: string | Identifier, + nameArg: EscapedIdentifier | Identifier, suggestedNameNotFoundMessage?: DiagnosticMessage): Symbol { return resolveNameHelper(location, name, meaning, nameNotFoundMessage, nameArg, getSymbol, suggestedNameNotFoundMessage); } function resolveNameHelper( location: Node | undefined, - name: string, + name: EscapedIdentifier, meaning: SymbolFlags, nameNotFoundMessage: DiagnosticMessage, - nameArg: string | Identifier, - lookup: (symbols: SymbolTable, name: string, meaning: SymbolFlags) => Symbol, + nameArg: EscapedIdentifier | Identifier, + lookup: typeof getSymbol, suggestedNameNotFoundMessage?: DiagnosticMessage): Symbol { const originalLocation = location; // needed for did-you-mean error reporting, which gathers candidates starting from the original location let result: Symbol; @@ -933,7 +933,7 @@ namespace ts { // It's an external module. First see if the module has an export default and if the local // name of that export default matches. - if (result = moduleExports.get("default")) { + if (result = moduleExports.get("default" as EscapedIdentifier)) { const localSymbol = getLocalSymbolForExportDefault(result); if (localSymbol && (result.flags & meaning) && localSymbol.name === name) { break loop; @@ -1101,15 +1101,15 @@ namespace ts { !checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) && !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) && !checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation, name, meaning)) { - let suggestion: string | undefined; + let suggestion: EscapedIdentifier | undefined; if (suggestedNameNotFoundMessage && suggestionCount < maximumSuggestionCount) { suggestion = getSuggestionForNonexistentSymbol(originalLocation, name, meaning); if (suggestion) { - error(errorLocation, suggestedNameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg), suggestion); + error(errorLocation, suggestedNameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg as Identifier), unescapeIdentifier(suggestion)); } } if (!suggestion) { - error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); + error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg as Identifier)); } suggestionCount++; } @@ -1124,7 +1124,7 @@ namespace ts { // to a local variable in the constructor where the code will be emitted. const propertyName = (propertyWithInvalidInitializer).name; error(errorLocation, Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, - declarationNameToString(propertyName), typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); + declarationNameToString(propertyName), typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg as Identifier)); return undefined; } @@ -1152,7 +1152,7 @@ namespace ts { if (result && isInExternalModule && (meaning & SymbolFlags.Value) === SymbolFlags.Value) { const decls = result.declarations; if (decls && decls.length === 1 && decls[0].kind === SyntaxKind.NamespaceExportDeclaration) { - error(errorLocation, Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, name); + error(errorLocation, Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, unescapeIdentifier(name)); } } } @@ -1169,7 +1169,7 @@ namespace ts { return false; } - function checkAndReportErrorForMissingPrefix(errorLocation: Node, name: string, nameArg: string | Identifier): boolean { + function checkAndReportErrorForMissingPrefix(errorLocation: Node, name: EscapedIdentifier, nameArg: EscapedIdentifier | Identifier): boolean { if ((errorLocation.kind === SyntaxKind.Identifier && (isTypeReferenceIdentifier(errorLocation)) || isInTypeQuery(errorLocation))) { return false; } @@ -1186,7 +1186,7 @@ namespace ts { // Check to see if a static member exists. const constructorType = getTypeOfSymbol(classSymbol); if (getPropertyOfType(constructorType, name)) { - error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg), symbolToString(classSymbol)); + error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg as Identifier), symbolToString(classSymbol)); return true; } @@ -1195,7 +1195,7 @@ namespace ts { if (location === container && !(getModifierFlags(location) & ModifierFlags.Static)) { const instanceType = (getDeclaredTypeOfSymbol(classSymbol)).thisType; if (getPropertyOfType(instanceType, name)) { - error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); + error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg as Identifier)); return true; } } @@ -1232,11 +1232,11 @@ namespace ts { } } - function checkAndReportErrorForUsingTypeAsNamespace(errorLocation: Node, name: string, meaning: SymbolFlags): boolean { + function checkAndReportErrorForUsingTypeAsNamespace(errorLocation: Node, name: EscapedIdentifier, meaning: SymbolFlags): boolean { if (meaning === SymbolFlags.Namespace) { const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined)); if (symbol) { - error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_namespace_here, name); + error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_namespace_here, unescapeIdentifier(name)); return true; } } @@ -1244,33 +1244,33 @@ namespace ts { return false; } - function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: string, meaning: SymbolFlags): boolean { + function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: EscapedIdentifier, meaning: SymbolFlags): boolean { if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule)) { if (name === "any" || name === "string" || name === "number" || name === "boolean" || name === "never") { - error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, name); + error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeIdentifier(name)); return true; } const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined)); if (symbol && !(symbol.flags & SymbolFlags.NamespaceModule)) { - error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, name); + error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeIdentifier(name)); return true; } } return false; } - function checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation: Node, name: string, meaning: SymbolFlags): boolean { + function checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation: Node, name: EscapedIdentifier, meaning: SymbolFlags): boolean { if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule & ~SymbolFlags.Type)) { const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.NamespaceModule & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined)); if (symbol) { - error(errorLocation, Diagnostics.Cannot_use_namespace_0_as_a_value, name); + error(errorLocation, Diagnostics.Cannot_use_namespace_0_as_a_value, unescapeIdentifier(name)); return true; } } else if (meaning & (SymbolFlags.Type & ~SymbolFlags.NamespaceModule & ~SymbolFlags.Value)) { const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.NamespaceModule & ~SymbolFlags.Type, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined)); if (symbol) { - error(errorLocation, Diagnostics.Cannot_use_namespace_0_as_a_type, name); + error(errorLocation, Diagnostics.Cannot_use_namespace_0_as_a_type, unescapeIdentifier(name)); return true; } } @@ -1335,10 +1335,10 @@ namespace ts { exportDefaultSymbol = moduleSymbol; } else { - const exportValue = moduleSymbol.exports.get("export="); + const exportValue = moduleSymbol.exports.get("export=" as EscapedIdentifier); exportDefaultSymbol = exportValue - ? getPropertyOfType(getTypeOfSymbol(exportValue), "default") - : resolveSymbol(moduleSymbol.exports.get("default"), dontResolveAlias); + ? getPropertyOfType(getTypeOfSymbol(exportValue), "default" as EscapedIdentifier) + : resolveSymbol(moduleSymbol.exports.get("default" as EscapedIdentifier), dontResolveAlias); } if (!exportDefaultSymbol && !allowSyntheticDefaultImports) { @@ -1390,13 +1390,13 @@ namespace ts { return result; } - function getExportOfModule(symbol: Symbol, name: string, dontResolveAlias: boolean): Symbol { + function getExportOfModule(symbol: Symbol, name: EscapedIdentifier, dontResolveAlias: boolean): Symbol { if (symbol.flags & SymbolFlags.Module) { return resolveSymbol(getExportsOfSymbol(symbol).get(name), dontResolveAlias); } } - function getPropertyOfVariable(symbol: Symbol, name: string): Symbol { + function getPropertyOfVariable(symbol: Symbol, name: EscapedIdentifier): Symbol { if (symbol.flags & SymbolFlags.Variable) { const typeAnnotation = (symbol.valueDeclaration).type; if (typeAnnotation) { @@ -1417,7 +1417,7 @@ namespace ts { let symbolFromVariable: Symbol; // First check if module was specified with "export=". If so, get the member from the resolved type - if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get("export=")) { + if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get("export=" as EscapedIdentifier)) { symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name.text); } else { @@ -1655,11 +1655,7 @@ namespace ts { } function resolveExternalModule(location: Node, moduleReference: string, moduleNotFoundError: DiagnosticMessage, errorNode: Node, isForAugmentation = false): Symbol { - // Module names are escaped in our symbol table. However, string literal values aren't. - // Escape the name in the "require(...)" clause to ensure we find the right symbol. - const moduleName = escapeIdentifier(moduleReference); - - if (moduleName === undefined) { + if (moduleReference === undefined) { return; } @@ -1669,11 +1665,11 @@ namespace ts { error(errorNode, diag, withoutAtTypePrefix, moduleReference); } - const ambientModule = tryFindAmbientModule(moduleName, /*withAugmentations*/ true); + const ambientModule = tryFindAmbientModule(moduleReference, /*withAugmentations*/ true); if (ambientModule) { return ambientModule; } - const isRelative = isExternalModuleNameRelative(moduleName); + const isRelative = isExternalModuleNameRelative(moduleReference); const resolvedModule = getResolvedModule(getSourceFileOfNode(location), moduleReference); const resolutionDiagnostic = resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule); const sourceFile = resolvedModule && !resolutionDiagnostic && host.getSourceFile(resolvedModule.resolvedFileName); @@ -1690,7 +1686,7 @@ namespace ts { } if (patternAmbientModules) { - const pattern = findBestPatternMatch(patternAmbientModules, _ => _.pattern, moduleName); + const pattern = findBestPatternMatch(patternAmbientModules, _ => _.pattern, moduleReference); if (pattern) { return getMergedSymbol(pattern.symbol); } @@ -1719,16 +1715,16 @@ namespace ts { if (moduleNotFoundError) { // report errors only if it was requested if (resolutionDiagnostic) { - error(errorNode, resolutionDiagnostic, moduleName, resolvedModule.resolvedFileName); + error(errorNode, resolutionDiagnostic, moduleReference, resolvedModule.resolvedFileName); } else { - const tsExtension = tryExtractTypeScriptExtension(moduleName); + const tsExtension = tryExtractTypeScriptExtension(moduleReference); if (tsExtension) { const diag = Diagnostics.An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead; - error(errorNode, diag, tsExtension, removeExtension(moduleName, tsExtension)); + error(errorNode, diag, tsExtension, removeExtension(moduleReference, tsExtension)); } else { - error(errorNode, moduleNotFoundError, moduleName); + error(errorNode, moduleNotFoundError, moduleReference); } } } @@ -1738,7 +1734,7 @@ namespace ts { // An external module with an 'export =' declaration resolves to the target of the 'export =' declaration, // and an external module with no 'export =' declaration resolves to the module itself. function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol { - return moduleSymbol && getMergedSymbol(resolveSymbol(moduleSymbol.exports.get("export="), dontResolveAlias)) || moduleSymbol; + return moduleSymbol && getMergedSymbol(resolveSymbol(moduleSymbol.exports.get("export=" as EscapedIdentifier), dontResolveAlias)) || moduleSymbol; } // An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export =' @@ -1753,7 +1749,7 @@ namespace ts { } function hasExportAssignmentSymbol(moduleSymbol: Symbol): boolean { - return moduleSymbol.exports.get("export=") !== undefined; + return moduleSymbol.exports.get("export=" as EscapedIdentifier) !== undefined; } function getExportsOfModuleAsArray(moduleSymbol: Symbol): Symbol[] { @@ -1769,7 +1765,7 @@ namespace ts { return exports; } - function tryGetMemberInModuleExports(memberName: string, moduleSymbol: Symbol): Symbol | undefined { + function tryGetMemberInModuleExports(memberName: EscapedIdentifier, moduleSymbol: Symbol): Symbol | undefined { const symbolTable = getExportsOfModule(moduleSymbol); if (symbolTable) { return symbolTable.get(memberName); @@ -1790,11 +1786,13 @@ namespace ts { exportsWithDuplicate: ExportDeclaration[]; } + type ExportCollisionTrackerTable = EscapedIdentifierMap; + /** * Extends one symbol table with another while collecting information on name collisions for error message generation into the `lookupTable` argument * Not passing `lookupTable` and `exportNode` disables this collection, and just extends the tables */ - function extendExportSymbols(target: SymbolTable, source: SymbolTable, lookupTable?: Map, exportNode?: ExportDeclaration) { + function extendExportSymbols(target: SymbolTable, source: SymbolTable, lookupTable?: ExportCollisionTrackerTable, exportNode?: ExportDeclaration) { source && source.forEach((sourceSymbol, id) => { if (id === "default") return; @@ -1836,10 +1834,10 @@ namespace ts { visitedSymbols.push(symbol); const symbols = cloneMap(symbol.exports); // All export * declarations are collected in an __export symbol by the binder - const exportStars = symbol.exports.get("__export"); + const exportStars = symbol.exports.get("__export" as EscapedIdentifier); if (exportStars) { - const nestedSymbols = createMap(); - const lookupTable = createMap(); + const nestedSymbols = createSymbolTable(); + const lookupTable = createMap() as ExportCollisionTrackerTable; for (const node of exportStars.declarations) { const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier); const exportedSymbols = visit(resolvedModule); @@ -1860,7 +1858,7 @@ namespace ts { node, Diagnostics.Module_0_has_already_exported_a_member_named_1_Consider_explicitly_re_exporting_to_resolve_the_ambiguity, lookupTable.get(id).specifierText, - id + unescapeIdentifier(id) )); } }); @@ -1937,11 +1935,11 @@ namespace ts { // or the @ symbol. A third underscore indicates an escaped form of an identifer that started // with at least two underscores. The @ character indicates that the name is denoted by a well known ES // Symbol instance. - function isReservedMemberName(name: string) { - return name.charCodeAt(0) === CharacterCodes._ && - name.charCodeAt(1) === CharacterCodes._ && - name.charCodeAt(2) !== CharacterCodes._ && - name.charCodeAt(2) !== CharacterCodes.at; + function isReservedMemberName(name: EscapedIdentifier) { + return (name as string).charCodeAt(0) === CharacterCodes._ && + (name as string).charCodeAt(1) === CharacterCodes._ && + (name as string).charCodeAt(2) !== CharacterCodes._ && + (name as string).charCodeAt(2) !== CharacterCodes.at; } function getNamedMembers(members: SymbolTable): Symbol[] { @@ -2854,7 +2852,7 @@ namespace ts { parameterDeclaration.name.kind === SyntaxKind.Identifier ? setEmitFlags(getSynthesizedClone(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) : cloneBindingName(parameterDeclaration.name) : - parameterSymbol.name; + unescapeIdentifier(parameterSymbol.name); const questionToken = isOptionalParameter(parameterDeclaration) ? createToken(SyntaxKind.QuestionToken) : undefined; let parameterType = getTypeOfSymbol(parameterSymbol); @@ -2990,7 +2988,7 @@ namespace ts { return "(Anonymous function)"; } } - return symbol.name; + return unescapeIdentifier(symbol.name); } } @@ -3077,7 +3075,7 @@ namespace ts { return "(Anonymous function)"; } } - return symbol.name; + return unescapeIdentifier(symbol.name); } function getSymbolDisplayBuilder(): SymbolDisplayBuilder { @@ -3534,7 +3532,7 @@ namespace ts { continue; } if (getDeclarationModifierFlagsFromSymbol(p) & (ModifierFlags.Private | ModifierFlags.Protected)) { - writer.reportPrivateInBaseOfClassExpression(p.name); + writer.reportPrivateInBaseOfClassExpression(unescapeIdentifier(p.name)); } } const t = getTypeOfSymbol(p); @@ -4046,7 +4044,7 @@ namespace ts { } // Return the type of the given property in the given type, or undefined if no such property exists - function getTypeOfPropertyOfType(type: Type, name: string): Type { + function getTypeOfPropertyOfType(type: Type, name: EscapedIdentifier): Type { const prop = getPropertyOfType(type, name); return prop ? getTypeOfSymbol(prop) : undefined; } @@ -4076,8 +4074,8 @@ namespace ts { return mapType(source, t => getRestType(t, properties, symbol)); } - const members = createMap(); - const names = createMap(); + const members = createSymbolTable(); + const names = createMap() as EscapedIdentifierMap; for (const name of properties) { names.set(getTextOfPropertyName(name), true); } @@ -4164,7 +4162,7 @@ namespace ts { // Use specific property type when parent is a tuple or numeric index type when parent is an array const propName = "" + indexOf(pattern.elements, declaration); type = isTupleLikeType(parentType) - ? getTypeOfPropertyOfType(parentType, propName) + ? getTypeOfPropertyOfType(parentType, propName as EscapedIdentifier) : elementType; if (!type) { if (isTupleType(parentType)) { @@ -4372,7 +4370,7 @@ namespace ts { // Return the type implied by an object binding pattern function getTypeFromObjectBindingPattern(pattern: ObjectBindingPattern, includePatternInType: boolean, reportErrors: boolean): Type { - const members = createMap(); + const members = createSymbolTable(); let stringIndexInfo: IndexInfo; let hasComputedProperties = false; forEach(pattern.elements, e => { @@ -5309,18 +5307,10 @@ namespace ts { return false; } - function createSymbolTable(symbols: Symbol[]): SymbolTable { - const result = createMap(); - for (const symbol of symbols) { - result.set(symbol.name, symbol); - } - return result; - } - // The mappingThisOnly flag indicates that the only type parameter being mapped is "this". When the flag is true, // we check symbols to see if we can quickly conclude they are free of "this" references, thus needing no instantiation. function createInstantiatedSymbolTable(symbols: Symbol[], mapper: TypeMapper, mappingThisOnly: boolean): SymbolTable { - const result = createMap(); + const result = createSymbolTable(); for (const symbol of symbols) { result.set(symbol.name, mappingThisOnly && isIndependentMember(symbol) ? symbol : instantiateSymbol(symbol, mapper)); } @@ -5339,8 +5329,8 @@ namespace ts { if (!(type).declaredProperties) { const symbol = type.symbol; (type).declaredProperties = getNamedMembers(symbol.members); - (type).declaredCallSignatures = getSignaturesOfSymbol(symbol.members.get("__call")); - (type).declaredConstructSignatures = getSignaturesOfSymbol(symbol.members.get("__new")); + (type).declaredCallSignatures = getSignaturesOfSymbol(symbol.members.get("__call" as EscapedIdentifier)); + (type).declaredConstructSignatures = getSignaturesOfSymbol(symbol.members.get("__new" as EscapedIdentifier)); (type).declaredStringIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.String); (type).declaredNumberIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.Number); } @@ -5631,8 +5621,8 @@ namespace ts { } else if (symbol.flags & SymbolFlags.TypeLiteral) { const members = symbol.members; - const callSignatures = getSignaturesOfSymbol(members.get("__call")); - const constructSignatures = getSignaturesOfSymbol(members.get("__new")); + const callSignatures = getSignaturesOfSymbol(members.get("__call" as EscapedIdentifier)); + const constructSignatures = getSignaturesOfSymbol(members.get("__new" as EscapedIdentifier)); const stringIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.String); const numberIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.Number); setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); @@ -5647,7 +5637,7 @@ namespace ts { } if (symbol.flags & SymbolFlags.Class) { const classType = getDeclaredTypeOfClassOrInterface(symbol); - constructSignatures = getSignaturesOfSymbol(symbol.members.get("__constructor")); + constructSignatures = getSignaturesOfSymbol(symbol.members.get("__constructor" as EscapedIdentifier)); if (!constructSignatures.length) { constructSignatures = getDefaultConstructSignatures(classType); } @@ -5674,7 +5664,7 @@ namespace ts { /** Resolve the members of a mapped type { [P in K]: T } */ function resolveMappedTypeMembers(type: MappedType) { - const members: SymbolTable = createMap(); + const members: SymbolTable = createSymbolTable(); let stringIndexInfo: IndexInfo; // Resolve upfront such that recursive references see an empty object type. setStructuredTypeMembers(type, emptySymbols, emptyArray, emptyArray, undefined, undefined); @@ -5715,7 +5705,7 @@ namespace ts { // If the current iteration type constituent is a string literal type, create a property. // Otherwise, for type string create a string index signature. if (t.flags & TypeFlags.StringLiteral) { - const propName = (t).value; + const propName = escapeIdentifier((t).value); const modifiersProp = getPropertyOfType(modifiersType, propName); const isOptional = templateOptional || !!(modifiersProp && modifiersProp.flags & SymbolFlags.Optional); const prop = createSymbol(SymbolFlags.Property | (isOptional ? SymbolFlags.Optional : 0), propName); @@ -5817,7 +5807,7 @@ namespace ts { /** If the given type is an object type and that type has a property by the given name, * return the symbol for that property. Otherwise return undefined. */ - function getPropertyOfObjectType(type: Type, name: string): Symbol { + function getPropertyOfObjectType(type: Type, name: EscapedIdentifier): Symbol { if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); const symbol = resolved.members.get(name); @@ -5829,7 +5819,7 @@ namespace ts { function getPropertiesOfUnionOrIntersectionType(type: UnionOrIntersectionType): Symbol[] { if (!type.resolvedProperties) { - const members = createMap(); + const members = createSymbolTable(); for (const current of type.types) { for (const prop of getPropertiesOfType(current)) { if (!members.has(prop.name)) { @@ -5859,7 +5849,7 @@ namespace ts { function getAllPossiblePropertiesOfType(type: Type): Symbol[] { if (type.flags & TypeFlags.Union) { - const props = createMap(); + const props = createSymbolTable(); for (const memberType of (type as UnionType).types) { if (memberType.flags & TypeFlags.Primitive) { continue; @@ -6012,7 +6002,7 @@ namespace ts { t; } - function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: string): Symbol { + function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: EscapedIdentifier): Symbol { let props: Symbol[]; const types = containingType.types; const isUnion = containingType.flags & TypeFlags.Union; @@ -6083,8 +6073,8 @@ namespace ts { // constituents, in which case the isPartial flag is set when the containing type is union type. We need // these partial properties when identifying discriminant properties, but otherwise they are filtered out // and do not appear to be present in the union type. - function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: string): Symbol { - const properties = type.propertyCache || (type.propertyCache = createMap()); + function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: EscapedIdentifier): Symbol { + const properties = type.propertyCache || (type.propertyCache = createSymbolTable()); let property = properties.get(name); if (!property) { property = createUnionOrIntersectionProperty(type, name); @@ -6095,7 +6085,7 @@ namespace ts { return property; } - function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: string): Symbol { + function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: EscapedIdentifier): Symbol { const property = getUnionOrIntersectionProperty(type, name); // We need to filter out partial properties in union types return property && !(getCheckFlags(property) & CheckFlags.Partial) ? property : undefined; @@ -6109,7 +6099,7 @@ namespace ts { * @param type a type to look up property from * @param name a name of property to look up in a given type */ - function getPropertyOfType(type: Type, name: string): Symbol | undefined { + function getPropertyOfType(type: Type, name: EscapedIdentifier): Symbol | undefined { type = getApparentType(type); if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); @@ -6236,7 +6226,7 @@ namespace ts { if (isExternalModuleNameRelative(moduleName)) { return undefined; } - const symbol = getSymbol(globals, `"${moduleName}"`, SymbolFlags.ValueModule); + const symbol = getSymbol(globals, `"${moduleName}"` as EscapedIdentifier, SymbolFlags.ValueModule); // merged symbol is module declaration symbol combined with all augmentations return symbol && withAugmentations ? getMergedSymbol(symbol) : symbol; } @@ -6400,7 +6390,7 @@ namespace ts { let hasRestLikeParameter = hasRestParameter(declaration); if (!hasRestLikeParameter && isInJavaScriptFile(declaration) && !hasJSDocParameterTags(declaration) && containsArgumentsReference(declaration)) { hasRestLikeParameter = true; - const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args"); + const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args" as EscapedIdentifier); syntheticArgsSymbol.type = anyArrayType; syntheticArgsSymbol.isRestParameter = true; parameters.push(syntheticArgsSymbol); @@ -6605,7 +6595,7 @@ namespace ts { } function getIndexSymbol(symbol: Symbol): Symbol { - return symbol.members.get("__index"); + return symbol.members.get("__index" as EscapedIdentifier); } function getIndexDeclarationOfSymbol(symbol: Symbol, kind: IndexKind): SignatureDeclaration { @@ -6975,88 +6965,88 @@ namespace ts { } const type = getDeclaredTypeOfSymbol(symbol); if (!(type.flags & TypeFlags.Object)) { - error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_be_a_class_or_interface_type, symbol.name); + error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_be_a_class_or_interface_type, unescapeIdentifier(symbol.name)); return arity ? emptyGenericType : emptyObjectType; } if (length((type).typeParameters) !== arity) { - error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_have_1_type_parameter_s, symbol.name, arity); + error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_have_1_type_parameter_s, unescapeIdentifier(symbol.name), arity); return arity ? emptyGenericType : emptyObjectType; } return type; } - function getGlobalValueSymbol(name: string, reportErrors: boolean): Symbol { + function getGlobalValueSymbol(name: EscapedIdentifier, reportErrors: boolean): Symbol { return getGlobalSymbol(name, SymbolFlags.Value, reportErrors ? Diagnostics.Cannot_find_global_value_0 : undefined); } - function getGlobalTypeSymbol(name: string, reportErrors: boolean): Symbol { + function getGlobalTypeSymbol(name: EscapedIdentifier, reportErrors: boolean): Symbol { return getGlobalSymbol(name, SymbolFlags.Type, reportErrors ? Diagnostics.Cannot_find_global_type_0 : undefined); } - function getGlobalSymbol(name: string, meaning: SymbolFlags, diagnostic: DiagnosticMessage): Symbol { + function getGlobalSymbol(name: EscapedIdentifier, meaning: SymbolFlags, diagnostic: DiagnosticMessage): Symbol { return resolveName(undefined, name, meaning, diagnostic, name); } - function getGlobalType(name: string, arity: 0, reportErrors: boolean): ObjectType; - function getGlobalType(name: string, arity: number, reportErrors: boolean): GenericType; - function getGlobalType(name: string, arity: number, reportErrors: boolean): ObjectType { + function getGlobalType(name: EscapedIdentifier, arity: 0, reportErrors: boolean): ObjectType; + function getGlobalType(name: EscapedIdentifier, arity: number, reportErrors: boolean): GenericType; + function getGlobalType(name: EscapedIdentifier, arity: number, reportErrors: boolean): ObjectType { const symbol = getGlobalTypeSymbol(name, reportErrors); return symbol || reportErrors ? getTypeOfGlobalSymbol(symbol, arity) : undefined; } function getGlobalTypedPropertyDescriptorType() { - return deferredGlobalTypedPropertyDescriptorType || (deferredGlobalTypedPropertyDescriptorType = getGlobalType("TypedPropertyDescriptor", /*arity*/ 1, /*reportErrors*/ true)) || emptyGenericType; + return deferredGlobalTypedPropertyDescriptorType || (deferredGlobalTypedPropertyDescriptorType = getGlobalType("TypedPropertyDescriptor" as EscapedIdentifier, /*arity*/ 1, /*reportErrors*/ true)) || emptyGenericType; } function getGlobalTemplateStringsArrayType() { - return deferredGlobalTemplateStringsArrayType || (deferredGlobalTemplateStringsArrayType = getGlobalType("TemplateStringsArray", /*arity*/ 0, /*reportErrors*/ true)) || emptyObjectType; + return deferredGlobalTemplateStringsArrayType || (deferredGlobalTemplateStringsArrayType = getGlobalType("TemplateStringsArray" as EscapedIdentifier, /*arity*/ 0, /*reportErrors*/ true)) || emptyObjectType; } function getGlobalESSymbolConstructorSymbol(reportErrors: boolean) { - return deferredGlobalESSymbolConstructorSymbol || (deferredGlobalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol", reportErrors)); + return deferredGlobalESSymbolConstructorSymbol || (deferredGlobalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol" as EscapedIdentifier, reportErrors)); } function getGlobalESSymbolType(reportErrors: boolean) { - return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol", /*arity*/ 0, reportErrors)) || emptyObjectType; + return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol" as EscapedIdentifier, /*arity*/ 0, reportErrors)) || emptyObjectType; } function getGlobalPromiseType(reportErrors: boolean) { - return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise", /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise" as EscapedIdentifier, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalPromiseConstructorSymbol(reportErrors: boolean): Symbol | undefined { - return deferredGlobalPromiseConstructorSymbol || (deferredGlobalPromiseConstructorSymbol = getGlobalValueSymbol("Promise", reportErrors)); + return deferredGlobalPromiseConstructorSymbol || (deferredGlobalPromiseConstructorSymbol = getGlobalValueSymbol("Promise" as EscapedIdentifier, reportErrors)); } function getGlobalPromiseConstructorLikeType(reportErrors: boolean) { - return deferredGlobalPromiseConstructorLikeType || (deferredGlobalPromiseConstructorLikeType = getGlobalType("PromiseConstructorLike", /*arity*/ 0, reportErrors)) || emptyObjectType; + return deferredGlobalPromiseConstructorLikeType || (deferredGlobalPromiseConstructorLikeType = getGlobalType("PromiseConstructorLike" as EscapedIdentifier, /*arity*/ 0, reportErrors)) || emptyObjectType; } function getGlobalAsyncIterableType(reportErrors: boolean) { - return deferredGlobalAsyncIterableType || (deferredGlobalAsyncIterableType = getGlobalType("AsyncIterable", /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIterableType || (deferredGlobalAsyncIterableType = getGlobalType("AsyncIterable" as EscapedIdentifier, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalAsyncIteratorType(reportErrors: boolean) { - return deferredGlobalAsyncIteratorType || (deferredGlobalAsyncIteratorType = getGlobalType("AsyncIterator", /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIteratorType || (deferredGlobalAsyncIteratorType = getGlobalType("AsyncIterator" as EscapedIdentifier, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalAsyncIterableIteratorType(reportErrors: boolean) { - return deferredGlobalAsyncIterableIteratorType || (deferredGlobalAsyncIterableIteratorType = getGlobalType("AsyncIterableIterator", /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIterableIteratorType || (deferredGlobalAsyncIterableIteratorType = getGlobalType("AsyncIterableIterator" as EscapedIdentifier, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIterableType(reportErrors: boolean) { - return deferredGlobalIterableType || (deferredGlobalIterableType = getGlobalType("Iterable", /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalIterableType || (deferredGlobalIterableType = getGlobalType("Iterable" as EscapedIdentifier, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIteratorType(reportErrors: boolean) { - return deferredGlobalIteratorType || (deferredGlobalIteratorType = getGlobalType("Iterator", /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalIteratorType || (deferredGlobalIteratorType = getGlobalType("Iterator" as EscapedIdentifier, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIterableIteratorType(reportErrors: boolean) { - return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType("IterableIterator", /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType("IterableIterator" as EscapedIdentifier, /*arity*/ 1, reportErrors)) || emptyGenericType; } - function getGlobalTypeOrUndefined(name: string, arity = 0): ObjectType { + function getGlobalTypeOrUndefined(name: EscapedIdentifier, arity = 0): ObjectType { const symbol = getGlobalSymbol(name, SymbolFlags.Type, /*diagnostic*/ undefined); return symbol && getTypeOfGlobalSymbol(symbol, arity); } @@ -7065,7 +7055,7 @@ namespace ts { * Returns a type that is inside a namespace at the global scope, e.g. * getExportedTypeFromNamespace('JSX', 'Element') returns the JSX.Element type */ - function getExportedTypeFromNamespace(namespace: string, name: string): Type { + function getExportedTypeFromNamespace(namespace: EscapedIdentifier, name: EscapedIdentifier): Type { const namespaceSymbol = getGlobalSymbol(namespace, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined); const typeSymbol = namespaceSymbol && getSymbol(namespaceSymbol.exports, name, SymbolFlags.Type); return typeSymbol && getDeclaredTypeOfSymbol(typeSymbol); @@ -7123,7 +7113,7 @@ namespace ts { for (let i = 0; i < arity; i++) { const typeParameter = createType(TypeFlags.TypeParameter); typeParameters.push(typeParameter); - const property = createSymbol(SymbolFlags.Property, "" + i); + const property = createSymbol(SymbolFlags.Property, "" + i as EscapedIdentifier); property.type = typeParameter; properties.push(property); } @@ -7463,7 +7453,7 @@ namespace ts { } function getLiteralTypeFromPropertyName(prop: Symbol) { - return getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier || startsWith(prop.name, "__@") ? + return getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier || startsWith(prop.name as string, "__@") ? neverType : getLiteralType(unescapeIdentifier(prop.name)); } @@ -7504,10 +7494,10 @@ namespace ts { const propName = indexType.flags & TypeFlags.StringOrNumberLiteral ? "" + (indexType).value : accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false) ? - getPropertyNameForKnownSymbolName(((accessExpression.argumentExpression).name).text) : + getPropertyNameForKnownSymbolName(unescapeIdentifier(((accessExpression.argumentExpression).name).text)) : undefined; if (propName !== undefined) { - const prop = getPropertyOfType(objectType, propName); + const prop = getPropertyOfType(objectType, propName as EscapedIdentifier); // Symbols, numbers, and strings are escaped already by this point if (prop) { if (accessExpression) { if (isAssignmentTarget(accessExpression) && (isReferenceToReadonlyEntity(accessExpression, prop) || isReferenceThroughNamespaceImport(accessExpression))) { @@ -7692,8 +7682,8 @@ namespace ts { return emptyObjectType; } - const members = createMap(); - const skippedPrivateMembers = createMap(); + const members = createSymbolTable(); + const skippedPrivateMembers = createMap() as EscapedIdentifierMap; let stringIndexInfo: IndexInfo; let numberIndexInfo: IndexInfo; if (left === emptyObjectType) { @@ -8502,8 +8492,8 @@ namespace ts { if (!related) { if (reportErrors) { errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, - sourceParams[i < sourceMax ? i : sourceMax].name, - targetParams[i < targetMax ? i : targetMax].name); + unescapeIdentifier(sourceParams[i < sourceMax ? i : sourceMax].name), + unescapeIdentifier(targetParams[i < targetMax ? i : targetMax].name)); } return Ternary.False; } @@ -8652,7 +8642,7 @@ namespace ts { const targetProperty = getPropertyOfType(targetEnumType, property.name); if (!targetProperty || !(targetProperty.flags & SymbolFlags.EnumMember)) { if (errorReporter) { - errorReporter(Diagnostics.Property_0_is_missing_in_type_1, property.name, + errorReporter(Diagnostics.Property_0_is_missing_in_type_1, unescapeIdentifier(property.name), typeToString(getDeclaredTypeOfSymbol(targetSymbol), /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); } enumRelation.set(id, false); @@ -9904,7 +9894,7 @@ namespace ts { } function isTupleLikeType(type: Type): boolean { - return !!getPropertyOfType(type, "0"); + return !!getPropertyOfType(type, "0" as EscapedIdentifier); } function isUnitType(type: Type): boolean { @@ -10017,7 +10007,7 @@ namespace ts { } function transformTypeOfMembers(type: Type, f: (propertyType: Type) => Type) { - const members = createMap(); + const members = createSymbolTable(); for (const property of getPropertiesOfObjectType(type)) { const original = getTypeOfSymbol(property); const updated = f(original); @@ -10061,7 +10051,7 @@ namespace ts { } function getWidenedTypeOfObjectLiteral(type: Type): Type { - const members = createMap(); + const members = createSymbolTable(); for (const prop of getPropertiesOfObjectType(type)) { // Since get accessors already widen their return value there is no need to // widen accessor based properties here. @@ -10128,7 +10118,7 @@ namespace ts { const t = getTypeOfSymbol(p); if (t.flags & TypeFlags.ContainsWideningType) { if (!reportWideningErrorsInType(t)) { - error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(getWidenedType(t))); + error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, unescapeIdentifier(p.name), typeToString(getWidenedType(t))); } errorReported = true; } @@ -10283,7 +10273,7 @@ namespace ts { const templateType = getTemplateTypeFromMappedType(target); const readonlyMask = target.declaration.readonlyToken ? false : true; const optionalMask = target.declaration.questionToken ? 0 : SymbolFlags.Optional; - const members = createMap(); + const members = createSymbolTable(); for (const prop of properties) { const inferredPropType = inferTargetType(getTypeOfSymbol(prop)); if (!inferredPropType) { @@ -10759,7 +10749,7 @@ namespace ts { return undefined; } - function isDiscriminantProperty(type: Type, name: string) { + function isDiscriminantProperty(type: Type, name: EscapedIdentifier) { if (type && type.flags & TypeFlags.Union) { const prop = getUnionOrIntersectionProperty(type, name); if (prop && getCheckFlags(prop) & CheckFlags.SyntheticProperty) { @@ -10840,7 +10830,7 @@ namespace ts { // check. This gives us a quicker out in the common case where an object type is not a function. const resolved = resolveStructuredTypeMembers(type); return !!(resolved.callSignatures.length || resolved.constructSignatures.length || - resolved.members.get("bind") && isTypeSubtypeOf(type, globalFunctionType)); + resolved.members.get("bind" as EscapedIdentifier) && isTypeSubtypeOf(type, globalFunctionType)); } function getTypeFacts(type: Type): TypeFacts { @@ -10918,7 +10908,7 @@ namespace ts { } function getTypeOfDestructuredArrayElement(type: Type, index: number) { - return isTupleLikeType(type) && getTypeOfPropertyOfType(type, "" + index) || + return isTupleLikeType(type) && getTypeOfPropertyOfType(type, "" + index as EscapedIdentifier) || checkIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || unknownType; } @@ -11751,7 +11741,7 @@ namespace ts { } let targetType: Type; - const prototypeProperty = getPropertyOfType(rightType, "prototype"); + const prototypeProperty = getPropertyOfType(rightType, "prototype" as EscapedIdentifier); if (prototypeProperty) { // Target type is type of the prototype property const prototypePropertyType = getTypeOfSymbol(prototypeProperty); @@ -12842,7 +12832,7 @@ namespace ts { return undefined; } - function getTypeOfPropertyOfContextualType(type: Type, name: string) { + function getTypeOfPropertyOfContextualType(type: Type, name: EscapedIdentifier) { return mapType(type, t => { const prop = t.flags & TypeFlags.StructuredType ? getPropertyOfType(t, name) : undefined; return prop ? getTypeOfSymbol(prop) : undefined; @@ -12902,7 +12892,7 @@ namespace ts { const type = getApparentTypeOfContextualType(arrayLiteral); if (type) { const index = indexOf(arrayLiteral.elements, node); - return getTypeOfPropertyOfContextualType(type, "" + index) + return getTypeOfPropertyOfContextualType(type, "" + index as EscapedIdentifier) || getIndexTypeOfContextualType(type, IndexKind.Number) || getIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false, /*checkAssignability*/ false); } @@ -13234,11 +13224,11 @@ namespace ts { return isTypeAny(type) || isTypeOfKind(type, kind); } - function isInfinityOrNaNString(name: string): boolean { + function isInfinityOrNaNString(name: string | EscapedIdentifier): boolean { return name === "Infinity" || name === "-Infinity" || name === "NaN"; } - function isNumericLiteralName(name: string) { + function isNumericLiteralName(name: string | EscapedIdentifier) { // The intent of numeric names is that // - they are names with text in a numeric form, and that // - setting properties/indexing with them is always equivalent to doing so with the numeric literal 'numLit', @@ -13297,7 +13287,7 @@ namespace ts { // Grammar checking checkGrammarObjectLiteralExpression(node, inDestructuringPattern); - let propertiesTable = createMap(); + let propertiesTable = createSymbolTable(); let propertiesArray: Symbol[] = []; let spread: Type = emptyObjectType; let propagatedFlags: TypeFlags = 0; @@ -13386,7 +13376,7 @@ namespace ts { if (propertiesArray.length > 0) { spread = getSpreadType(spread, createObjectLiteralType()); propertiesArray = []; - propertiesTable = createMap(); + propertiesTable = createSymbolTable(); hasComputedStringProperty = false; hasComputedNumberProperty = false; typeFlags = 0; @@ -13504,9 +13494,9 @@ namespace ts { /** * Returns true iff the JSX element name would be a valid JS identifier, ignoring restrictions about keywords not being identifiers */ - function isUnhyphenatedJsxName(name: string) { + function isUnhyphenatedJsxName(name: string | EscapedIdentifier) { // - is the only character supported in JSX attribute names that isn't valid in JavaScript identifiers - return name.indexOf("-") < 0; + return (name as string).indexOf("-") < 0; } /** @@ -13533,7 +13523,7 @@ namespace ts { */ function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, filter?: (symbol: Symbol) => boolean, checkMode?: CheckMode) { const attributes = openingLikeElement.attributes; - let attributesTable = createMap(); + let attributesTable = createSymbolTable(); let spread: Type = emptyObjectType; let attributesArray: Symbol[] = []; let hasSpreadAnyType = false; @@ -13567,7 +13557,7 @@ namespace ts { if (attributesArray.length > 0) { spread = getSpreadType(spread, createJsxAttributesType(attributes.symbol, attributesTable)); attributesArray = []; - attributesTable = createMap(); + attributesTable = createSymbolTable(); } const exprType = checkExpression(attributeDecl.expression); if (isTypeAny(exprType)) { @@ -13590,7 +13580,7 @@ namespace ts { attributesArray = getPropertiesOfType(spread); } - attributesTable = createMap(); + attributesTable = createSymbolTable(); for (const attr of attributesArray) { if (!filter || filter(attr)) { attributesTable.set(attr.name, attr); @@ -13621,7 +13611,7 @@ namespace ts { // This is because children element will overwrite the value from attributes. // Note: we will not warn "children" attribute overwritten if "children" attribute is specified in object spread. if (explicitlySpecifyChildrenAttribute) { - error(attributes, Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, jsxChildrenPropertyName); + error(attributes, Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, unescapeIdentifier(jsxChildrenPropertyName)); } // If there are children in the body of JSX element, create dummy attribute "children" with anyType so that it will pass the attribute checking process @@ -13646,7 +13636,7 @@ namespace ts { * @param symbol a symbol of JsxAttributes containing attributes corresponding to attributesTable * @param attributesTable a symbol table of attributes property */ - function createJsxAttributesType(symbol: Symbol, attributesTable: Map) { + function createJsxAttributesType(symbol: Symbol, attributesTable: EscapedIdentifierMap) { const result = createAnonymousType(symbol, attributesTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined); result.flags |= TypeFlags.JsxAttributes | TypeFlags.ContainsObjectLiteral; result.objectFlags |= ObjectFlags.ObjectLiteral; @@ -13663,7 +13653,7 @@ namespace ts { return createJsxAttributesTypeFromAttributesProperty(node.parent as JsxOpeningLikeElement, /*filter*/ undefined, checkMode); } - function getJsxType(name: string) { + function getJsxType(name: EscapedIdentifier) { let jsxType = jsxTypes.get(name); if (jsxType === undefined) { jsxTypes.set(name, jsxType = getExportedTypeFromNamespace(JsxNames.JSX, name) || unknownType); @@ -13697,12 +13687,12 @@ namespace ts { } // Wasn't found - error(node, Diagnostics.Property_0_does_not_exist_on_type_1, (node.tagName).text, "JSX." + JsxNames.IntrinsicElements); + error(node, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeIdentifier((node.tagName).text), "JSX." + JsxNames.IntrinsicElements); return links.resolvedSymbol = unknownSymbol; } else { if (noImplicitAny) { - error(node, Diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, JsxNames.IntrinsicElements); + error(node, Diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, unescapeIdentifier(JsxNames.IntrinsicElements)); } return links.resolvedSymbol = unknownSymbol; } @@ -13755,7 +13745,7 @@ namespace ts { * @param nameOfAttribPropContainer a string of value JsxNames.ElementAttributesPropertyNameContainer or JsxNames.ElementChildrenAttributeNameContainer * if other string is given or the container doesn't exist, return undefined. */ - function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: string): string { + function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: EscapedIdentifier): EscapedIdentifier { // JSX const jsxNamespace = getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined); // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [symbol] @@ -13767,7 +13757,7 @@ namespace ts { if (propertiesOfJsxElementAttribPropInterface) { // Element Attributes has zero properties, so the element attributes type will be the class instance type if (propertiesOfJsxElementAttribPropInterface.length === 0) { - return ""; + return "" as EscapedIdentifier; } // Element Attributes has one property, so the element attributes type will be the type of the corresponding // property of the class instance type @@ -13776,7 +13766,7 @@ namespace ts { } else if (propertiesOfJsxElementAttribPropInterface.length > 1) { // More than one property on ElementAttributesProperty is an error - error(jsxElementAttribPropInterfaceSym.declarations[0], Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, nameOfAttribPropContainer); + error(jsxElementAttribPropInterfaceSym.declarations[0], Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, unescapeIdentifier(nameOfAttribPropContainer)); } } return undefined; @@ -13796,7 +13786,7 @@ namespace ts { return _jsxElementPropertiesName; } - function getJsxElementChildrenPropertyname(): string { + function getJsxElementChildrenPropertyname(): EscapedIdentifier { if (!_hasComputedJsxElementChildrenPropertyName) { _hasComputedJsxElementChildrenPropertyName = true; _jsxElementChildrenPropertyName = getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer); @@ -13954,7 +13944,7 @@ namespace ts { // Hello World const intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements); if (intrinsicElementsType !== unknownType) { - const stringLiteralTypeName = (elementType).value; + const stringLiteralTypeName = escapeIdentifier((elementType).value); const intrinsicProp = getPropertyOfType(intrinsicElementsType, stringLiteralTypeName); if (intrinsicProp) { return getTypeOfSymbol(intrinsicProp); @@ -13963,7 +13953,7 @@ namespace ts { if (indexSignatureType) { return indexSignatureType; } - error(openingLikeElement, Diagnostics.Property_0_does_not_exist_on_type_1, stringLiteralTypeName, "JSX." + JsxNames.IntrinsicElements); + error(openingLikeElement, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeIdentifier(stringLiteralTypeName), "JSX." + JsxNames.IntrinsicElements); } // If we need to report an error, we already done so here. So just return any to prevent any more error downstream return anyType; @@ -14196,7 +14186,7 @@ namespace ts { * @param name a property name to search * @param isComparingJsxAttributes a boolean flag indicating whether we are searching in JsxAttributesType */ - function isKnownProperty(targetType: Type, name: string, isComparingJsxAttributes: boolean): boolean { + function isKnownProperty(targetType: Type, name: EscapedIdentifier, isComparingJsxAttributes: boolean): boolean { if (targetType.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(targetType); if (resolved.stringIndexInfo || @@ -14246,7 +14236,7 @@ namespace ts { // If the targetAttributesType is an emptyObjectType, indicating that there is no property named 'props' on this instance type. // but there exists a sourceAttributesType, we need to explicitly give an error as normal assignability check allow excess properties and will pass. if (targetAttributesType === emptyObjectType && (isTypeAny(sourceAttributesType) || (sourceAttributesType).properties.length > 0)) { - error(openingLikeElement, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, getJsxElementPropertiesName()); + error(openingLikeElement, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, unescapeIdentifier(getJsxElementPropertiesName())); } else { // Check if sourceAttributesType assignable to targetAttributesType though this check will allow excess properties @@ -14256,7 +14246,7 @@ namespace ts { if (isSourceAttributeTypeAssignableToTarget && !isTypeAny(sourceAttributesType) && !isTypeAny(targetAttributesType)) { for (const attribute of openingLikeElement.attributes.properties) { if (isJsxAttribute(attribute) && !isKnownProperty(targetAttributesType, attribute.name.text, /*isComparingJsxAttributes*/ true)) { - error(attribute, Diagnostics.Property_0_does_not_exist_on_type_1, attribute.name.text, typeToString(targetAttributesType)); + error(attribute, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeIdentifier(attribute.name.text), typeToString(targetAttributesType)); // We break here so that errors won't be cascading break; } @@ -14441,13 +14431,13 @@ namespace ts { if (prop.valueDeclaration) { if (isInPropertyInitializer(node) && !isBlockScopedNameDeclaredBeforeUse(prop.valueDeclaration, right)) { - error(right, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, right.text); + error(right, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, unescapeIdentifier(right.text)); } if (prop.valueDeclaration.kind === SyntaxKind.ClassDeclaration && node.parent && node.parent.kind !== SyntaxKind.TypeReference && !isInAmbientContext(prop.valueDeclaration) && !isBlockScopedNameDeclaredBeforeUse(prop.valueDeclaration, right)) { - error(right, Diagnostics.Class_0_used_before_its_declaration, right.text); + error(right, Diagnostics.Class_0_used_before_its_declaration, unescapeIdentifier(right.text)); } } @@ -14462,7 +14452,7 @@ namespace ts { if (assignmentKind) { if (isReferenceToReadonlyEntity(node, prop) || isReferenceThroughNamespaceImport(node)) { - error(right, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, right.text); + error(right, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, unescapeIdentifier(right.text)); return unknownType; } } @@ -14499,12 +14489,12 @@ namespace ts { diagnostics.add(createDiagnosticForNodeFromMessageChain(propNode, errorInfo)); } - function getSuggestionForNonexistentProperty(node: Identifier, containingType: Type): string | undefined { - const suggestion = getSpellingSuggestionForName(node.text, getPropertiesOfObjectType(containingType), SymbolFlags.Value); + function getSuggestionForNonexistentProperty(node: Identifier, containingType: Type): EscapedIdentifier | undefined { + const suggestion = getSpellingSuggestionForName(unescapeIdentifier(node.text), getPropertiesOfObjectType(containingType), SymbolFlags.Value); return suggestion && suggestion.name; } - function getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string { + function getSuggestionForNonexistentSymbol(location: Node, name: EscapedIdentifier, meaning: SymbolFlags): EscapedIdentifier { const result = resolveNameHelper(location, name, meaning, /*nameNotFoundMessage*/ undefined, name, (symbols, name, meaning) => { const symbol = getSymbol(symbols, name, meaning); if (symbol) { @@ -14513,7 +14503,7 @@ namespace ts { // However, resolveNameHelper will continue and call this callback again, so we'll eventually get a correct suggestion. return symbol; } - return getSpellingSuggestionForName(name, arrayFrom(symbols.values()), meaning); + return getSpellingSuggestionForName(unescapeIdentifier(name), arrayFrom(symbols.values()), meaning); }); if (result) { return result.name; @@ -14547,10 +14537,11 @@ namespace ts { } name = name.toLowerCase(); for (const candidate of symbols) { + let candidateName = unescapeIdentifier(candidate.name); if (candidate.flags & meaning && - candidate.name && - Math.abs(candidate.name.length - name.length) < maximumLengthDifference) { - const candidateName = candidate.name.toLowerCase(); + candidateName && + Math.abs(candidateName.length - name.length) < maximumLengthDifference) { + candidateName = candidateName.toLowerCase(); if (candidateName === name) { return candidate; } @@ -14608,7 +14599,7 @@ namespace ts { return false; } - function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean { + function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: EscapedIdentifier): boolean { const left = node.kind === SyntaxKind.PropertyAccessExpression ? (node).expression : (node).left; @@ -14619,7 +14610,7 @@ namespace ts { function isValidPropertyAccessWithType( node: PropertyAccessExpression | QualifiedName, left: LeftHandSideExpression | QualifiedName, - propertyName: string, + propertyName: EscapedIdentifier, type: Type): boolean { if (type !== unknownType && !isTypeAny(type)) { @@ -15361,9 +15352,10 @@ namespace ts { const element = node; switch (element.name.kind) { case SyntaxKind.Identifier: + return getLiteralType(unescapeIdentifier((element.name).text)); case SyntaxKind.NumericLiteral: case SyntaxKind.StringLiteral: - return getLiteralType((element.name).text); + return getLiteralType((element.name).text); case SyntaxKind.ComputedPropertyName: const nameType = checkComputedPropertyName(element.name); @@ -17072,7 +17064,7 @@ namespace ts { const element = elements[elementIndex]; if (element.kind !== SyntaxKind.OmittedExpression) { if (element.kind !== SyntaxKind.SpreadElement) { - const propName = "" + elementIndex; + const propName = "" + elementIndex as EscapedIdentifier; const type = isTypeAny(sourceType) ? sourceType : isTupleLikeType(sourceType) @@ -17089,7 +17081,7 @@ namespace ts { error(element, Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(sourceType), getTypeReferenceArity(sourceType), elements.length); } else { - error(element, Diagnostics.Type_0_has_no_property_1, typeToString(sourceType), propName); + error(element, Diagnostics.Type_0_has_no_property_1, typeToString(sourceType), propName as string); } } } @@ -18086,8 +18078,8 @@ namespace ts { Property = Getter | Setter } - const instanceNames = createMap(); - const staticNames = createMap(); + const instanceNames = createMap() as EscapedIdentifierMap; + const staticNames = createMap() as EscapedIdentifierMap; for (const member of node.members) { if (member.kind === SyntaxKind.Constructor) { for (const param of (member as ConstructorDeclaration).parameters) { @@ -18123,7 +18115,7 @@ namespace ts { } } - function addName(names: Map, location: Node, name: string, meaning: Declaration) { + function addName(names: EscapedIdentifierMap, location: Node, name: EscapedIdentifier, meaning: Declaration) { const prev = names.get(name); if (prev) { if (prev & Declaration.Method) { @@ -18184,8 +18176,10 @@ namespace ts { switch (member.name.kind) { case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: + memberName = member.name.text; + break; case SyntaxKind.Identifier: - memberName = (member.name as LiteralExpression | Identifier).text; + memberName = unescapeIdentifier(member.name.text); break; default: continue; @@ -18895,7 +18889,7 @@ namespace ts { return typeAsPromise.promisedTypeOfPromise = (promise).typeArguments[0]; } - const thenFunction = getTypeOfPropertyOfType(promise, "then"); + const thenFunction = getTypeOfPropertyOfType(promise, "then" as EscapedIdentifier); if (isTypeAny(thenFunction)) { return undefined; } @@ -19027,7 +19021,7 @@ namespace ts { // of a runtime problem. If the user wants to return this value from an async // function, they would need to wrap it in some other value. If they want it to // be treated as a promise, they can cast to . - const thenFunction = getTypeOfPropertyOfType(type, "then"); + const thenFunction = getTypeOfPropertyOfType(type, "then" as EscapedIdentifier); if (thenFunction && getSignaturesOfType(thenFunction, SignatureKind.Call).length > 0) { if (errorNode) { Debug.assert(!!diagnosticMessage); @@ -19136,7 +19130,7 @@ namespace ts { const collidingSymbol = getSymbol(node.locals, rootName.text, SymbolFlags.Value); if (collidingSymbol) { error(collidingSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions, - rootName.text, + unescapeIdentifier(rootName.text), entityNameToString(promiseConstructorName)); return unknownType; } @@ -19485,11 +19479,11 @@ namespace ts { !isParameterPropertyDeclaration(parameter) && !parameterIsThisKeyword(parameter) && !parameterNameStartsWithUnderscore(name)) { - error(name, Diagnostics._0_is_declared_but_never_used, local.name); + error(name, Diagnostics._0_is_declared_but_never_used, unescapeIdentifier(local.name)); } } else if (compilerOptions.noUnusedLocals) { - forEach(local.declarations, d => errorUnusedLocal(getNameOfDeclaration(d) || d, local.name)); + forEach(local.declarations, d => errorUnusedLocal(getNameOfDeclaration(d) || d, unescapeIdentifier(local.name))); } } }); @@ -19522,7 +19516,7 @@ namespace ts { } function isIdentifierThatStartsWithUnderScore(node: Node) { - return node.kind === SyntaxKind.Identifier && (node).text.charCodeAt(0) === CharacterCodes._; + return node.kind === SyntaxKind.Identifier && unescapeIdentifier((node).text).charCodeAt(0) === CharacterCodes._; } function checkUnusedClassMembers(node: ClassDeclaration | ClassExpression): void { @@ -19531,13 +19525,13 @@ namespace ts { for (const member of node.members) { if (member.kind === SyntaxKind.MethodDeclaration || member.kind === SyntaxKind.PropertyDeclaration) { if (!member.symbol.isReferenced && getModifierFlags(member) & ModifierFlags.Private) { - error(member.name, Diagnostics._0_is_declared_but_never_used, member.symbol.name); + error(member.name, Diagnostics._0_is_declared_but_never_used, unescapeIdentifier(member.symbol.name)); } } else if (member.kind === SyntaxKind.Constructor) { for (const parameter of (member).parameters) { if (!parameter.symbol.isReferenced && getModifierFlags(parameter) & ModifierFlags.Private) { - error(parameter.name, Diagnostics.Property_0_is_declared_but_never_used, parameter.symbol.name); + error(parameter.name, Diagnostics.Property_0_is_declared_but_never_used, unescapeIdentifier(parameter.symbol.name)); } } } @@ -19558,7 +19552,7 @@ namespace ts { } for (const typeParameter of node.typeParameters) { if (!getMergedSymbol(typeParameter.symbol).isReferenced) { - error(typeParameter.name, Diagnostics._0_is_declared_but_never_used, typeParameter.symbol.name); + error(typeParameter.name, Diagnostics._0_is_declared_but_never_used, unescapeIdentifier(typeParameter.symbol.name)); } } } @@ -19571,7 +19565,7 @@ namespace ts { if (!local.isReferenced && !local.exportSymbol) { for (const declaration of local.declarations) { if (!isAmbientModule(declaration)) { - errorUnusedLocal(getNameOfDeclaration(declaration), local.name); + errorUnusedLocal(getNameOfDeclaration(declaration), unescapeIdentifier(local.name)); } } } @@ -20464,7 +20458,7 @@ namespace ts { } // Both async and non-async iterators must have a `next` method. - const nextMethod = getTypeOfPropertyOfType(type, "next"); + const nextMethod = getTypeOfPropertyOfType(type, "next" as EscapedIdentifier); if (isTypeAny(nextMethod)) { return undefined; } @@ -20492,7 +20486,7 @@ namespace ts { } } - const nextValue = nextResult && getTypeOfPropertyOfType(nextResult, "value"); + const nextValue = nextResult && getTypeOfPropertyOfType(nextResult, "value" as EscapedIdentifier); if (!nextValue) { if (errorNode) { error(errorNode, isAsyncIterator @@ -20837,7 +20831,7 @@ namespace ts { case "symbol": case "void": case "object": - error(name, message, (name).text); + error(name, message, (name).text as string); } } @@ -21172,7 +21166,8 @@ namespace ts { return true; } - const seen = createMap<{ prop: Symbol; containingType: Type }>(); + type InheritanceInfoMap = { prop: Symbol; containingType: Type }; + const seen = createMap() as EscapedIdentifierMap; forEach(resolveDeclaredMembers(type).declaredProperties, p => { seen.set(p.name, { prop: p, containingType: type }); }); let ok = true; @@ -21371,7 +21366,7 @@ namespace ts { if (type.symbol && type.symbol.flags & SymbolFlags.Enum) { const name = expr.kind === SyntaxKind.PropertyAccessExpression ? (expr).name.text : - ((expr).argumentExpression).text; + ((expr).argumentExpression).text as EscapedIdentifier; return evaluateEnumMember(expr, type.symbol, name); } } @@ -21380,7 +21375,7 @@ namespace ts { return undefined; } - function evaluateEnumMember(expr: Expression, enumSymbol: Symbol, name: string) { + function evaluateEnumMember(expr: Expression, enumSymbol: Symbol, name: EscapedIdentifier) { const memberSymbol = enumSymbol.exports.get(name); if (memberSymbol) { const declaration = memberSymbol.valueDeclaration; @@ -21570,7 +21565,7 @@ namespace ts { if (isGlobalAugmentation) { error(node.name, Diagnostics.Augmentations_for_the_global_scope_can_only_be_directly_nested_in_external_modules_or_ambient_module_declarations); } - else if (isExternalModuleNameRelative(node.name.text)) { + else if (isExternalModuleNameRelative(node.name.kind === SyntaxKind.Identifier ? unescapeIdentifier(node.name.text) : node.name.text)) { error(node.name, Diagnostics.Ambient_module_declaration_cannot_specify_relative_module_name); } } @@ -21845,7 +21840,7 @@ namespace ts { const symbol = resolveName(exportedName, exportedName.text, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined); if (symbol && (symbol === undefinedSymbol || isGlobalSourceFile(getDeclarationContainer(symbol.declarations[0])))) { - error(exportedName, Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, exportedName.text); + error(exportedName, Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, unescapeIdentifier(exportedName.text)); } else { markExportAsReferenced(node); @@ -21903,7 +21898,7 @@ namespace ts { const moduleSymbol = getSymbolOfNode(node); const links = getSymbolLinks(moduleSymbol); if (!links.exportsChecked) { - const exportEqualsSymbol = moduleSymbol.exports.get("export="); + const exportEqualsSymbol = moduleSymbol.exports.get("export=" as EscapedIdentifier); if (exportEqualsSymbol && hasExportedMembers(moduleSymbol)) { const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration; if (!isTopLevelInExternalModuleAugmentation(declaration)) { @@ -21930,7 +21925,7 @@ namespace ts { if (exportedDeclarationsCount > 1) { for (const declaration of declarations) { if (isNotOverload(declaration)) { - diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, id)); + diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, unescapeIdentifier(id))); } } } @@ -22250,7 +22245,7 @@ namespace ts { return []; } - const symbols = createMap(); + const symbols = createSymbolTable(); let memberFlags: ModifierFlags = ModifierFlags.None; populateSymbols(); @@ -22616,7 +22611,7 @@ namespace ts { if (objectType === unknownType) return undefined; const apparentType = getApparentType(objectType); if (apparentType === unknownType) return undefined; - return getPropertyOfType(apparentType, (node).text); + return getPropertyOfType(apparentType, (node).text as EscapedIdentifier); } break; } @@ -23209,7 +23204,7 @@ namespace ts { } function hasGlobalName(name: string): boolean { - return globals.has(name); + return globals.has(escapeIdentifier(name)); } function getReferencedValueSymbol(reference: Identifier, startInDeclarationContainer?: boolean): Symbol { @@ -23453,23 +23448,23 @@ namespace ts { addToSymbolTable(globals, builtinGlobals, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0); getSymbolLinks(undefinedSymbol).type = undefinedWideningType; - getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments", /*arity*/ 0, /*reportErrors*/ true); + getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments" as EscapedIdentifier, /*arity*/ 0, /*reportErrors*/ true); getSymbolLinks(unknownSymbol).type = unknownType; // Initialize special types - globalArrayType = getGlobalType("Array", /*arity*/ 1, /*reportErrors*/ true); - globalObjectType = getGlobalType("Object", /*arity*/ 0, /*reportErrors*/ true); - globalFunctionType = getGlobalType("Function", /*arity*/ 0, /*reportErrors*/ true); - globalStringType = getGlobalType("String", /*arity*/ 0, /*reportErrors*/ true); - globalNumberType = getGlobalType("Number", /*arity*/ 0, /*reportErrors*/ true); - globalBooleanType = getGlobalType("Boolean", /*arity*/ 0, /*reportErrors*/ true); - globalRegExpType = getGlobalType("RegExp", /*arity*/ 0, /*reportErrors*/ true); + globalArrayType = getGlobalType("Array" as EscapedIdentifier, /*arity*/ 1, /*reportErrors*/ true); + globalObjectType = getGlobalType("Object" as EscapedIdentifier, /*arity*/ 0, /*reportErrors*/ true); + globalFunctionType = getGlobalType("Function" as EscapedIdentifier, /*arity*/ 0, /*reportErrors*/ true); + globalStringType = getGlobalType("String" as EscapedIdentifier, /*arity*/ 0, /*reportErrors*/ true); + globalNumberType = getGlobalType("Number" as EscapedIdentifier, /*arity*/ 0, /*reportErrors*/ true); + globalBooleanType = getGlobalType("Boolean" as EscapedIdentifier, /*arity*/ 0, /*reportErrors*/ true); + globalRegExpType = getGlobalType("RegExp" as EscapedIdentifier, /*arity*/ 0, /*reportErrors*/ true); anyArrayType = createArrayType(anyType); autoArrayType = createArrayType(autoType); - globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray", /*arity*/ 1); + globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray" as EscapedIdentifier, /*arity*/ 1); anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; - globalThisType = getGlobalTypeOrUndefined("ThisType", /*arity*/ 1); + globalThisType = getGlobalTypeOrUndefined("ThisType" as EscapedIdentifier, /*arity*/ 1); } function checkExternalEmitHelpers(location: Node, helpers: ExternalEmitHelpers) { @@ -24086,7 +24081,7 @@ namespace ts { } function checkGrammarObjectLiteralExpression(node: ObjectLiteralExpression, inDestructuring: boolean) { - const seen = createMap(); + const seen = createMap() as EscapedIdentifierMap; const Property = 1; const GetAccessor = 2; const SetAccessor = 4; @@ -24176,7 +24171,7 @@ namespace ts { } function checkGrammarJsxElement(node: JsxOpeningLikeElement) { - const seen = createMap(); + const seen = createMap() as EscapedIdentifierMap; for (const attr of node.attributes.properties) { if (attr.kind === SyntaxKind.JsxSpreadAttribute) { @@ -24733,7 +24728,7 @@ namespace ts { function getAmbientModules(): Symbol[] { const result: Symbol[] = []; globals.forEach((global, sym) => { - if (ambientModuleSymbolRegex.test(sym)) { + if (ambientModuleSymbolRegex.test(unescapeIdentifier(sym))) { result.push(global); } }); diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 5da7e83655fe5..6288f5ad18293 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1047,7 +1047,7 @@ namespace ts { errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.name, Diagnostics.String_literal_with_double_quotes_expected)); } - const keyText = getTextOfPropertyName(element.name); + const keyText = unescapeIdentifier(getTextOfPropertyName(element.name)); const option = knownOptions ? knownOptions.get(keyText) : undefined; if (extraKeyDiagnosticMessage && !option) { errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.name, extraKeyDiagnosticMessage, keyText)); diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 5c7536a825ed6..129c5be1ba0de 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -47,6 +47,17 @@ namespace ts { return new MapCtr(); } + /* @internal */ + export function createSymbolTable(symbols?: Symbol[]): SymbolTable { + const result = createMap() as SymbolTable; + if (symbols) { + for (const symbol of symbols) { + result.set(symbol.name, symbol); + } + } + return result; + } + export function createMapFromTemplate(template?: MapLike): Map { const map: Map = new MapCtr(); @@ -1000,11 +1011,13 @@ namespace ts { * Calls `callback` for each entry in the map, returning the first truthy result. * Use `map.forEach` instead for normal iteration. */ - export function forEachEntry(map: Map, callback: (value: T, key: string) => U | undefined): U | undefined { + export function forEachEntry(map: EscapedIdentifierMap, callback: (value: T, key: string) => U | undefined): U | undefined; + export function forEachEntry(map: Map, callback: (value: T, key: string) => U | undefined): U | undefined; + export function forEachEntry(map: EscapedIdentifierMap | Map, callback: (value: T, key: string) => U | undefined): U | undefined { const iterator = map.entries(); for (let { value: pair, done } = iterator.next(); !done; { value: pair, done } = iterator.next()) { const [key, value] = pair; - const result = callback(value, key); + const result = callback(value, key as string); if (result) { return result; } @@ -1013,10 +1026,12 @@ namespace ts { } /** `forEachEntry` for just keys. */ - export function forEachKey(map: Map<{}>, callback: (key: string) => T | undefined): T | undefined { + export function forEachKey(map: EscapedIdentifierMap<{}>, callback: (key: EscapedIdentifier) => T | undefined): T | undefined; + export function forEachKey(map: Map<{}>, callback: (key: string) => T | undefined): T | undefined; + export function forEachKey(map: EscapedIdentifierMap<{}> | Map<{}>, callback: (key: string & EscapedIdentifier) => T | undefined): T | undefined { const iterator = map.keys(); for (let { value: key, done } = iterator.next(); !done; { value: key, done } = iterator.next()) { - const result = callback(key); + const result = callback(key as string & EscapedIdentifier); if (result) { return result; } @@ -1025,9 +1040,11 @@ namespace ts { } /** Copy entries from `source` to `target`. */ - export function copyEntries(source: Map, target: Map): void { - source.forEach((value, key) => { - target.set(key, value); + export function copyEntries(source: EscapedIdentifierMap, target: EscapedIdentifierMap): void; + export function copyEntries(source: Map, target: Map): void; + export function copyEntries | Map>(source: U, target: U): void { + (source as Map).forEach((value, key) => { + (target as Map).set(key, value); }); } @@ -1099,9 +1116,11 @@ namespace ts { return arrayToMap(array, makeKey, () => true); } - export function cloneMap(map: Map) { + export function cloneMap(map: SymbolTable): SymbolTable; + export function cloneMap(map: Map): Map; + export function cloneMap(map: Map | SymbolTable): Map | SymbolTable { const clone = createMap(); - copyEntries(map, clone); + copyEntries(map as Map, clone); return clone; } @@ -2272,13 +2291,13 @@ namespace ts { getTokenConstructor(): new (kind: TKind, pos?: number, end?: number) => Token; getIdentifierConstructor(): new (kind: SyntaxKind.Identifier, pos?: number, end?: number) => Identifier; getSourceFileConstructor(): new (kind: SyntaxKind.SourceFile, pos?: number, end?: number) => SourceFile; - getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol; + getSymbolConstructor(): new (flags: SymbolFlags, name: EscapedIdentifier) => Symbol; getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type; getSignatureConstructor(): new (checker: TypeChecker) => Signature; getSourceMapSourceConstructor(): new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource; } - function Symbol(this: Symbol, flags: SymbolFlags, name: string) { + function Symbol(this: Symbol, flags: SymbolFlags, name: EscapedIdentifier) { this.flags = flags; this.name = name; this.declarations = undefined; diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 753080cc6a081..ee8e461360920 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -61,7 +61,7 @@ namespace ts { let resultHasExternalModuleIndicator: boolean; let currentText: string; let currentLineMap: number[]; - let currentIdentifiers: Map; + let currentIdentifiers: EscapedIdentifierMap; let isCurrentFileExternalModule: boolean; let reportedDeclarationError = false; let errorNameNode: DeclarationName; @@ -608,14 +608,14 @@ namespace ts { // Note that export default is only allowed at most once in a module, so we // do not need to keep track of created temp names. function getExportTempVariableName(baseName: string): string { - if (!currentIdentifiers.has(baseName)) { + if (!currentIdentifiers.has(escapeIdentifier(baseName))) { return baseName; } let count = 0; while (true) { count++; const name = baseName + "_" + count; - if (!currentIdentifiers.has(name)) { + if (!currentIdentifiers.has(escapeIdentifier(name))) { return name; } } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 65cbee9873a35..3d0e4b3e3fa86 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2818,13 +2818,13 @@ namespace ts { // Auto, Loop, and Unique names are cached based on their unique // autoGenerateId. const autoGenerateId = name.autoGenerateId; - return autoGeneratedIdToGeneratedName[autoGenerateId] || (autoGeneratedIdToGeneratedName[autoGenerateId] = unescapeIdentifier(makeName(name))); + return autoGeneratedIdToGeneratedName[autoGenerateId] || (autoGeneratedIdToGeneratedName[autoGenerateId] = makeName(name)); } } function generateNameCached(node: Node) { const nodeId = getNodeId(node); - return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = unescapeIdentifier(generateNameForNode(node))); + return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = generateNameForNode(node)); } /** @@ -2833,7 +2833,7 @@ namespace ts { */ function isUniqueName(name: string): boolean { return !(hasGlobalName && hasGlobalName(name)) - && !currentSourceFile.identifiers.has(name) + && !currentSourceFile.identifiers.has(escapeIdentifier(name)) && !generatedNames.has(name); } @@ -2843,7 +2843,7 @@ namespace ts { function isUniqueLocalName(name: string, container: Node): boolean { for (let node = container; isNodeDescendantOf(node, container); node = node.nextContainer) { if (node.locals) { - const local = node.locals.get(name); + const local = node.locals.get(escapeIdentifier(name)); // We conservatively include alias symbols to cover cases where they're emitted as locals if (local && local.flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) { return false; @@ -2918,7 +2918,7 @@ namespace ts { function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) { const expr = getExternalModuleName(node); const baseName = expr.kind === SyntaxKind.StringLiteral ? - escapeIdentifier(makeIdentifierFromModuleName((expr).text)) : "module"; + makeIdentifierFromModuleName((expr).text) : "module"; return makeUniqueName(baseName); } diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index ed3ed36e79a03..4c086b78a4e36 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -99,7 +99,7 @@ namespace ts { } function createLiteralFromNode(sourceNode: StringLiteral | NumericLiteral | Identifier): StringLiteral { - const node = createStringLiteral(sourceNode.text); + const node = createStringLiteral(sourceNode.kind === SyntaxKind.Identifier ? unescapeIdentifier(sourceNode.text) : sourceNode.text); node.textSourceNode = sourceNode; return node; } @@ -124,7 +124,7 @@ namespace ts { export function updateIdentifier(node: Identifier, typeArguments: NodeArray | undefined): Identifier { return node.typeArguments !== typeArguments - ? updateNode(createIdentifier(node.text, typeArguments), node) + ? updateNode(createIdentifier(unescapeIdentifier(node.text), typeArguments), node) : node; } @@ -2643,12 +2643,12 @@ namespace ts { function createJsxFactoryExpressionFromEntityName(jsxFactory: EntityName, parent: JsxOpeningLikeElement): Expression { if (isQualifiedName(jsxFactory)) { const left = createJsxFactoryExpressionFromEntityName(jsxFactory.left, parent); - const right = createIdentifier(jsxFactory.right.text); + const right = createIdentifier(unescapeIdentifier(jsxFactory.right.text)); right.text = jsxFactory.right.text; return createPropertyAccess(left, right); } else { - return createReactNamespace(jsxFactory.text, parent); + return createReactNamespace(unescapeIdentifier(jsxFactory.text), parent); } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a8234b850e210..a28ef611d3e13 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -536,7 +536,7 @@ namespace ts { let currentToken: SyntaxKind; let sourceText: string; let nodeCount: number; - let identifiers: Map; + let identifiers: EscapedIdentifierMap; let identifierCount: number; let parsingContext: ParsingContext; @@ -681,7 +681,7 @@ namespace ts { parseDiagnostics = []; parsingContext = 0; - identifiers = createMap(); + identifiers = createMap() as EscapedIdentifierMap; identifierCount = 0; nodeCount = 0; @@ -1178,12 +1178,12 @@ namespace ts { } const result = createNode(kind, scanner.getStartPos()); - (result).text = ""; + (result).text = "" as EscapedIdentifier; return finishNode(result); } - function internIdentifier(text: string): string { - text = escapeIdentifier(text); + function internIdentifier(input: string): EscapedIdentifier { + const text = escapeIdentifier(input); let identifier = identifiers.get(text); if (identifier === undefined) { identifiers.set(text, identifier = text); @@ -1227,7 +1227,9 @@ namespace ts { function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName { if (token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral) { - return parseLiteralNode(/*internName*/ true); + const node = parseLiteralNode(); // Interning makes the string literal be escaped - we do not want that + internIdentifier(node.text); // We do, however, want to intern the text for the purposes of the identifier list + return node; } if (allowComputedPropertyNames && token() === SyntaxKind.OpenBracketToken) { return parseComputedPropertyName(); @@ -2049,26 +2051,26 @@ namespace ts { return finishNode(span); } - function parseLiteralNode(internName?: boolean): LiteralExpression { - return parseLiteralLikeNode(token(), internName); + function parseLiteralNode(): LiteralExpression { + return parseLiteralLikeNode(token()); } function parseTemplateHead(): TemplateHead { - const fragment = parseLiteralLikeNode(token(), /*internName*/ false); + const fragment = parseLiteralLikeNode(token()); Debug.assert(fragment.kind === SyntaxKind.TemplateHead, "Template head has wrong token kind"); return fragment; } function parseTemplateMiddleOrTemplateTail(): TemplateMiddle | TemplateTail { - const fragment = parseLiteralLikeNode(token(), /*internName*/ false); + const fragment = parseLiteralLikeNode(token()); Debug.assert(fragment.kind === SyntaxKind.TemplateMiddle || fragment.kind === SyntaxKind.TemplateTail, "Template fragment has wrong token kind"); return fragment; } - function parseLiteralLikeNode(kind: SyntaxKind, internName: boolean): LiteralLikeNode { + function parseLiteralLikeNode(kind: SyntaxKind): LiteralLikeNode { const node = createNode(kind); const text = scanner.getTokenValue(); - node.text = internName ? internIdentifier(text) : text; + node.text = text; if (scanner.hasExtendedUnicodeEscape()) { node.hasExtendedUnicodeEscape = true; @@ -4098,7 +4100,7 @@ namespace ts { indexedAccess.argumentExpression = allowInAnd(parseExpression); if (indexedAccess.argumentExpression.kind === SyntaxKind.StringLiteral || indexedAccess.argumentExpression.kind === SyntaxKind.NumericLiteral) { const literal = indexedAccess.argumentExpression; - literal.text = internIdentifier(literal.text); + literal.text = internIdentifier(literal.text) as string; } } @@ -5624,7 +5626,8 @@ namespace ts { node.flags |= NodeFlags.GlobalAugmentation; } else { - node.name = parseLiteralNode(/*internName*/ true); + node.name = parseLiteralNode(); // Interning as an identifier causes it to be escaped - we do not want that + internIdentifier(node.name.text); // We do, however, want to intern the identifier for completions } if (token() === SyntaxKind.OpenBraceToken) { @@ -6990,7 +6993,7 @@ namespace ts { const pos = scanner.getTokenPos(); const end = scanner.getTextPos(); const result = createNode(SyntaxKind.Identifier, pos); - result.text = content.substring(pos, end); + result.text = escapeIdentifier(content.substring(pos, end)); finishNode(result, end); nextJSDocToken(); diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 7b62fde8570dc..6c1b721e4eb2f 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -405,7 +405,7 @@ namespace ts { let commonSourceDirectory: string; let diagnosticsProducingTypeChecker: TypeChecker; let noDiagnosticsTypeChecker: TypeChecker; - let classifiableNames: Map; + let classifiableNames: EscapedIdentifierMap; let modifiedFilePaths: Path[] | undefined; const cachedSemanticDiagnosticsForFile: DiagnosticCache = {}; @@ -580,7 +580,7 @@ namespace ts { if (!classifiableNames) { // Initialize a checker so that all our files are bound. getTypeChecker(); - classifiableNames = createMap(); + classifiableNames = createMap() as EscapedIdentifierMap; for (const sourceFile of files) { copyEntries(sourceFile.classifiableNames, classifiableNames); diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index cd3b8bdce6bfd..4bc1f936d83d9 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -411,7 +411,7 @@ namespace ts { } else if (isStringOrNumericLiteral(propertyName)) { const argumentExpression = getSynthesizedClone(propertyName); - argumentExpression.text = unescapeIdentifier(argumentExpression.text); + argumentExpression.text = argumentExpression.text; return createElementAccess(value, argumentExpression); } else { diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 4146574fe12b3..d25ffef1a4b6a 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -661,7 +661,7 @@ namespace ts { // - break/continue is non-labeled and located in non-converted loop/switch statement const jump = node.kind === SyntaxKind.BreakStatement ? Jump.Break : Jump.Continue; const canUseBreakOrContinue = - (node.label && convertedLoopState.labels && convertedLoopState.labels.get(node.label.text)) || + (node.label && convertedLoopState.labels && convertedLoopState.labels.get(unescapeIdentifier(node.label.text))) || (!node.label && (convertedLoopState.allowedNonLabeledJumps & jump)); if (!canUseBreakOrContinue) { @@ -680,11 +680,11 @@ namespace ts { else { if (node.kind === SyntaxKind.BreakStatement) { labelMarker = `break-${node.label.text}`; - setLabeledJump(convertedLoopState, /*isBreak*/ true, node.label.text, labelMarker); + setLabeledJump(convertedLoopState, /*isBreak*/ true, unescapeIdentifier(node.label.text), labelMarker); } else { labelMarker = `continue-${node.label.text}`; - setLabeledJump(convertedLoopState, /*isBreak*/ false, node.label.text, labelMarker); + setLabeledJump(convertedLoopState, /*isBreak*/ false, unescapeIdentifier(node.label.text), labelMarker); } } let returnExpression: Expression = createLiteral(labelMarker); @@ -2236,11 +2236,11 @@ namespace ts { } function recordLabel(node: LabeledStatement) { - convertedLoopState.labels.set(node.label.text, node.label.text); + convertedLoopState.labels.set(unescapeIdentifier(node.label.text), unescapeIdentifier(node.label.text)); } function resetLabel(node: LabeledStatement) { - convertedLoopState.labels.set(node.label.text, undefined); + convertedLoopState.labels.set(unescapeIdentifier(node.label.text), undefined); } function visitLabeledStatement(node: LabeledStatement): VisitResult { diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index 3565547d78aa8..d2fc430de830c 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -369,7 +369,7 @@ namespace ts { function substitutePropertyAccessExpression(node: PropertyAccessExpression) { if (node.expression.kind === SyntaxKind.SuperKeyword) { return createSuperAccessInAsyncMethod( - createLiteral(node.name.text), + createLiteral(unescapeIdentifier(node.name.text)), node ); } diff --git a/src/compiler/transformers/es5.ts b/src/compiler/transformers/es5.ts index bcecb86e75d87..4cc5840cbc8e9 100644 --- a/src/compiler/transformers/es5.ts +++ b/src/compiler/transformers/es5.ts @@ -111,7 +111,7 @@ namespace ts { * @param name An Identifier */ function trySubstituteReservedName(name: Identifier) { - const token = name.originalKeywordKind || (nodeIsSynthesized(name) ? stringToToken(name.text) : undefined); + const token = name.originalKeywordKind || (nodeIsSynthesized(name) ? stringToToken(unescapeIdentifier(name.text)) : undefined); if (token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord) { return setTextRange(createLiteral(name), name); } diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index a3aa0139aa41c..ea9e07a6e0422 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -776,7 +776,7 @@ namespace ts { function substitutePropertyAccessExpression(node: PropertyAccessExpression) { if (node.expression.kind === SyntaxKind.SuperKeyword) { return createSuperAccessInAsyncMethod( - createLiteral(node.name.text), + createLiteral(unescapeIdentifier(node.name.text)), node ); } diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index d0049e72f0bff..31e2cf7bab135 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -1635,14 +1635,14 @@ namespace ts { } function transformAndEmitContinueStatement(node: ContinueStatement): void { - const label = findContinueTarget(node.label ? node.label.text : undefined); + const label = findContinueTarget(node.label ? unescapeIdentifier(node.label.text) : undefined); Debug.assert(label > 0, "Expected continue statment to point to a valid Label."); emitBreak(label, /*location*/ node); } function visitContinueStatement(node: ContinueStatement): Statement { if (inStatementContainingYield) { - const label = findContinueTarget(node.label && node.label.text); + const label = findContinueTarget(node.label && unescapeIdentifier(node.label.text)); if (label > 0) { return createInlineBreak(label, /*location*/ node); } @@ -1652,14 +1652,14 @@ namespace ts { } function transformAndEmitBreakStatement(node: BreakStatement): void { - const label = findBreakTarget(node.label ? node.label.text : undefined); + const label = findBreakTarget(node.label ? unescapeIdentifier(node.label.text) : undefined); Debug.assert(label > 0, "Expected break statment to point to a valid Label."); emitBreak(label, /*location*/ node); } function visitBreakStatement(node: BreakStatement): Statement { if (inStatementContainingYield) { - const label = findBreakTarget(node.label && node.label.text); + const label = findBreakTarget(node.label && unescapeIdentifier(node.label.text)); if (label > 0) { return createInlineBreak(label, /*location*/ node); } @@ -1838,7 +1838,7 @@ namespace ts { // /*body*/ // .endlabeled // .mark endLabel - beginLabeledBlock(node.label.text); + beginLabeledBlock(unescapeIdentifier(node.label.text)); transformAndEmitEmbeddedStatement(node.statement); endLabeledBlock(); } @@ -1849,7 +1849,7 @@ namespace ts { function visitLabeledStatement(node: LabeledStatement) { if (inStatementContainingYield) { - beginScriptLabeledBlock(node.label.text); + beginScriptLabeledBlock(unescapeIdentifier(node.label.text)); } node = visitEachChild(node, visitor, context); @@ -1950,7 +1950,7 @@ namespace ts { } function substituteExpressionIdentifier(node: Identifier) { - if (!isGeneratedIdentifier(node) && renamedCatchVariables && renamedCatchVariables.has(node.text)) { + if (!isGeneratedIdentifier(node) && renamedCatchVariables && renamedCatchVariables.has(unescapeIdentifier(node.text))) { const original = getOriginalNode(node); if (isIdentifier(original) && original.parent) { const declaration = resolver.getReferencedValueDeclaration(original); @@ -2123,7 +2123,7 @@ namespace ts { hoistVariableDeclaration(variable.name); } else { - const text = (variable.name).text; + const text = unescapeIdentifier((variable.name).text); name = declareLocal(text); if (!renamedCatchVariables) { renamedCatchVariables = createMap(); diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index 09f361d1b131a..2d3a228e4c58f 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -253,7 +253,7 @@ namespace ts { else { const name = (node).tagName; if (isIdentifier(name) && isIntrinsicJsxName(name.text)) { - return createLiteral(name.text); + return createLiteral(unescapeIdentifier(name.text)); } else { return createExpressionFromEntityName(name); @@ -268,11 +268,11 @@ namespace ts { */ function getAttributeName(node: JsxAttribute): StringLiteral | Identifier { const name = node.name; - if (/^[A-Za-z_]\w*$/.test(name.text)) { + if (/^[A-Za-z_]\w*$/.test(unescapeIdentifier(name.text))) { return name; } else { - return createLiteral(name.text); + return createLiteral(unescapeIdentifier(name.text)); } } diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 6141f52f5f4cb..84fef26001ea3 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -1225,7 +1225,7 @@ namespace ts { */ function appendExportsOfDeclaration(statements: Statement[] | undefined, decl: Declaration): Statement[] | undefined { const name = getDeclarationName(decl); - const exportSpecifiers = currentModuleInfo.exportSpecifiers.get(name.text); + const exportSpecifiers = currentModuleInfo.exportSpecifiers.get(unescapeIdentifier(name.text)); if (exportSpecifiers) { for (const exportSpecifier of exportSpecifiers) { statements = appendExportStatement(statements, exportSpecifier.name, name, /*location*/ exportSpecifier.name); diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index fa126d1faa79f..0049c50f23af0 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -353,7 +353,7 @@ namespace ts { // write name of indirectly exported entry, i.e. 'export {x} from ...' exportedNames.push( createPropertyAssignment( - createLiteral((element.name || element.propertyName).text), + createLiteral(unescapeIdentifier((element.name || element.propertyName).text)), createTrue() ) ); @@ -504,10 +504,10 @@ namespace ts { for (const e of (entry).exportClause.elements) { properties.push( createPropertyAssignment( - createLiteral(e.name.text), + createLiteral(unescapeIdentifier(e.name.text)), createElementAccess( parameterName, - createLiteral((e.propertyName || e.name).text) + createLiteral(unescapeIdentifier((e.propertyName || e.name).text)) ) ) ); @@ -1028,7 +1028,7 @@ namespace ts { let excludeName: string; if (exportSelf) { statements = appendExportStatement(statements, decl.name, getLocalName(decl)); - excludeName = decl.name.text; + excludeName = unescapeIdentifier(decl.name.text); } statements = appendExportsOfDeclaration(statements, decl, excludeName); @@ -1055,7 +1055,7 @@ namespace ts { if (hasModifier(decl, ModifierFlags.Export)) { const exportName = hasModifier(decl, ModifierFlags.Default) ? createLiteral("default") : decl.name; statements = appendExportStatement(statements, exportName, getLocalName(decl)); - excludeName = exportName.text; + excludeName = exportName.kind === SyntaxKind.Identifier ? unescapeIdentifier(exportName.text) : exportName.text; } if (decl.name) { @@ -1080,7 +1080,7 @@ namespace ts { } const name = getDeclarationName(decl); - const exportSpecifiers = moduleInfo.exportSpecifiers.get(name.text); + const exportSpecifiers = moduleInfo.exportSpecifiers.get(unescapeIdentifier(name.text)); if (exportSpecifiers) { for (const exportSpecifier of exportSpecifiers) { if (exportSpecifier.name.text !== excludeName) { diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index acfd465ff998f..15e80af407306 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -65,7 +65,7 @@ namespace ts { let currentNamespace: ModuleDeclaration; let currentNamespaceContainerName: Identifier; let currentScope: SourceFile | Block | ModuleBlock | CaseBlock; - let currentScopeFirstDeclarationsOfName: Map; + let currentScopeFirstDeclarationsOfName: EscapedIdentifierMap; /** * Keeps track of whether expression substitution has been enabled for specific edge cases. @@ -2647,7 +2647,7 @@ namespace ts { const name = node.symbol && node.symbol.name; if (name) { if (!currentScopeFirstDeclarationsOfName) { - currentScopeFirstDeclarationsOfName = createMap(); + currentScopeFirstDeclarationsOfName = createMap() as EscapedIdentifierMap; } if (!currentScopeFirstDeclarationsOfName.has(name)) { diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index a39115a788e92..32b359525cee4 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -58,9 +58,9 @@ namespace ts { else { // export { x, y } for (const specifier of (node).exportClause.elements) { - if (!uniqueExports.get(specifier.name.text)) { + if (!uniqueExports.get(unescapeIdentifier(specifier.name.text))) { const name = specifier.propertyName || specifier.name; - exportSpecifiers.add(name.text, specifier); + exportSpecifiers.add(unescapeIdentifier(name.text), specifier); const decl = resolver.getReferencedImportDeclaration(name) || resolver.getReferencedValueDeclaration(name); @@ -69,7 +69,7 @@ namespace ts { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(decl), specifier.name); } - uniqueExports.set(specifier.name.text, true); + uniqueExports.set(unescapeIdentifier(specifier.name.text), true); exportedNames = append(exportedNames, specifier.name); } } @@ -103,9 +103,9 @@ namespace ts { else { // export function x() { } const name = (node).name; - if (!uniqueExports.get(name.text)) { + if (!uniqueExports.get(unescapeIdentifier(name.text))) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name); - uniqueExports.set(name.text, true); + uniqueExports.set(unescapeIdentifier(name.text), true); exportedNames = append(exportedNames, name); } } @@ -124,9 +124,9 @@ namespace ts { else { // export class x { } const name = (node).name; - if (!uniqueExports.get(name.text)) { + if (!uniqueExports.get(unescapeIdentifier(name.text))) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name); - uniqueExports.set(name.text, true); + uniqueExports.set(unescapeIdentifier(name.text), true); exportedNames = append(exportedNames, name); } } @@ -158,8 +158,8 @@ namespace ts { } } else if (!isGeneratedIdentifier(decl.name)) { - if (!uniqueExports.get(decl.name.text)) { - uniqueExports.set(decl.name.text, true); + if (!uniqueExports.get(unescapeIdentifier(decl.name.text))) { + uniqueExports.set(unescapeIdentifier(decl.name.text), true); exportedNames = append(exportedNames, decl.name); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index e2e14c9fd6b3b..9c1501508bd60 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -589,7 +589,7 @@ namespace ts { * Text of identifier (with escapes converted to characters). * If the identifier begins with two underscores, this will begin with three. */ - text: string; + text: EscapedIdentifier; originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later /*@internal*/ autoGenerateKind?: GeneratedIdentifierKind; // Specifies whether to auto-generate the text for an identifier. /*@internal*/ autoGenerateId?: number; // Ensures unique generated identifiers get unique names, but clones get the same name. @@ -2336,7 +2336,7 @@ namespace ts { // The first node that causes this file to be a CommonJS module /* @internal */ commonJsModuleIndicator: Node; - /* @internal */ identifiers: Map; + /* @internal */ identifiers: EscapedIdentifierMap; /* @internal */ nodeCount: number; /* @internal */ identifierCount: number; /* @internal */ symbolCount: number; @@ -2357,7 +2357,7 @@ namespace ts { // Stores a line map for the file. // This field should never be used directly to obtain line map, use getLineMap function instead. /* @internal */ lineMap: number[]; - /* @internal */ classifiableNames?: Map; + /* @internal */ classifiableNames?: EscapedIdentifierMap; // Stores a mapping 'external module reference text' -> 'resolved file name' | undefined // It is used to resolve module names in the checker. // Content of this field should never be used directly - use getResolvedModuleFileName/setResolvedModuleFileName functions instead @@ -2463,7 +2463,7 @@ namespace ts { /* @internal */ getDiagnosticsProducingTypeChecker(): TypeChecker; /* @internal */ dropDiagnosticsProducingTypeChecker(): void; - /* @internal */ getClassifiableNames(): Map; + /* @internal */ getClassifiableNames(): EscapedIdentifierMap; /* @internal */ getNodeCount(): number; /* @internal */ getIdentifierCount(): number; @@ -2937,7 +2937,7 @@ namespace ts { export interface Symbol { flags: SymbolFlags; // Symbol flags - name: string; // Name of symbol + name: EscapedIdentifier; // Name of symbol declarations?: Declaration[]; // Declarations associated with this symbol valueDeclaration?: Declaration; // First value declaration of the symbol members?: SymbolTable; // Class, interface or literal instance members @@ -3005,7 +3005,24 @@ namespace ts { isRestParameter?: boolean; } - export type SymbolTable = Map; + export type EscapedIdentifier = (string & { __escapedIdentifier: void }) | (void & { __escapedIdentifier: void }); + + /** EscapedStringMap based on ES6 Map interface. */ + export interface EscapedIdentifierMap { + get(key: EscapedIdentifier): T | undefined; + has(key: EscapedIdentifier): boolean; + set(key: EscapedIdentifier, value: T): this; + delete(key: EscapedIdentifier): boolean; + clear(): void; + forEach(action: (value: T, key: EscapedIdentifier) => void): void; + readonly size: number; + keys(): Iterator; + values(): Iterator; + entries(): Iterator<[EscapedIdentifier, T]>; + } + + /** SymbolTable based on ES6 Map interface. */ + export type SymbolTable = EscapedIdentifierMap; /** Represents a "prefix*suffix" pattern. */ /* @internal */ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 3d7e8c529b894..bdc094c266879 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -351,8 +351,8 @@ namespace ts { } // Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__' - export function escapeIdentifier(identifier: string): string { - return identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier; + export function escapeIdentifier(identifier: string): EscapedIdentifier { + return (identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier) as EscapedIdentifier; } // Make an identifier from an external module name by extracting the string after the last "/" and replacing @@ -467,16 +467,16 @@ namespace ts { return info.declaration ? declarationNameToString(info.declaration.parameters[0].name) : undefined; } - export function getTextOfPropertyName(name: PropertyName): string { + export function getTextOfPropertyName(name: PropertyName): EscapedIdentifier { switch (name.kind) { case SyntaxKind.Identifier: return (name).text; case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: - return (name).text; + return (name).text as EscapedIdentifier; case SyntaxKind.ComputedPropertyName: if (isStringOrNumericLiteral((name).expression)) { - return ((name).expression).text; + return ((name).expression).text as EscapedIdentifier; } } @@ -486,11 +486,11 @@ namespace ts { export function entityNameToString(name: EntityNameOrEntityNameExpression): string { switch (name.kind) { case SyntaxKind.Identifier: - return getFullWidth(name) === 0 ? unescapeIdentifier((name).text) : getTextOfNode(name); + return getFullWidth(name) === 0 ? unescapeIdentifier(name.text) : getTextOfNode(name); case SyntaxKind.QualifiedName: - return entityNameToString((name).left) + "." + entityNameToString((name).right); + return entityNameToString(name.left) + "." + entityNameToString(name.right); case SyntaxKind.PropertyAccessExpression: - return entityNameToString((name).expression) + "." + entityNameToString((name).name); + return entityNameToString(name.expression) + "." + entityNameToString(name.name); } } @@ -1959,26 +1959,26 @@ namespace ts { return isPropertyAccessExpression(node) && isESSymbolIdentifier(node.expression); } - export function getPropertyNameForPropertyNameNode(name: DeclarationName | ParameterDeclaration): string { - if (name.kind === SyntaxKind.Identifier || name.kind === SyntaxKind.StringLiteral || name.kind === SyntaxKind.NumericLiteral || name.kind === SyntaxKind.Parameter) { - return (name).text; + export function getPropertyNameForPropertyNameNode(name: DeclarationName): EscapedIdentifier { + if (name.kind === SyntaxKind.Identifier || name.kind === SyntaxKind.StringLiteral || name.kind === SyntaxKind.NumericLiteral) { + return name.text as EscapedIdentifier; } if (name.kind === SyntaxKind.ComputedPropertyName) { - const nameExpression = (name).expression; + const nameExpression = name.expression; if (isWellKnownSymbolSyntactically(nameExpression)) { const rightHandSideName = (nameExpression).name.text; - return getPropertyNameForKnownSymbolName(rightHandSideName); + return getPropertyNameForKnownSymbolName(unescapeIdentifier(rightHandSideName)); } else if (nameExpression.kind === SyntaxKind.StringLiteral || nameExpression.kind === SyntaxKind.NumericLiteral) { - return (nameExpression).text; + return (nameExpression).text as EscapedIdentifier; } } return undefined; } - export function getPropertyNameForKnownSymbolName(symbolName: string): string { - return "__@" + symbolName; + export function getPropertyNameForKnownSymbolName(symbolName: string): EscapedIdentifier { + return "__@" + symbolName as EscapedIdentifier; } /** @@ -2344,8 +2344,10 @@ namespace ts { return escapedCharsMap.get(c) || get16BitUnicodeEscapeSequence(c.charCodeAt(0)); } - export function isIntrinsicJsxName(name: string) { - const ch = name.substr(0, 1); + export function isIntrinsicJsxName(name: EscapedIdentifier | string) { + // An escaped identifier had a leading underscore prior to being escaped, which would return true + // The escape adds an extra underscore which does not change the result + const ch = (name as string).substr(0, 1); return ch.toLowerCase() === ch; } @@ -3974,8 +3976,8 @@ namespace ts { * @param identifier The escaped identifier text. * @returns The unescaped identifier text. */ - export function unescapeIdentifier(identifier: string): string { - return identifier.length >= 3 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ && identifier.charCodeAt(2) === CharacterCodes._ ? identifier.substr(1) : identifier; + export function unescapeIdentifier(identifier: EscapedIdentifier): string { + return (identifier as string).length >= 3 && (identifier as string).charCodeAt(0) === CharacterCodes._ && (identifier as string).charCodeAt(1) === CharacterCodes._ && (identifier as string).charCodeAt(2) === CharacterCodes._ ? (identifier as string).substr(1) : identifier as string; } export function getNameOfDeclaration(declaration: Declaration): DeclarationName | undefined { diff --git a/src/services/classifier.ts b/src/services/classifier.ts index ff33059630d82..ec30fb478bcfb 100644 --- a/src/services/classifier.ts +++ b/src/services/classifier.ts @@ -462,7 +462,7 @@ namespace ts { } /* @internal */ - export function getSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: Map, span: TextSpan): ClassifiedSpan[] { + export function getSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: EscapedIdentifierMap, span: TextSpan): ClassifiedSpan[] { return convertClassifications(getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span)); } @@ -487,7 +487,7 @@ namespace ts { } /* @internal */ - export function getEncodedSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: Map, span: TextSpan): Classifications { + export function getEncodedSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: EscapedIdentifierMap, span: TextSpan): Classifications { const result: number[] = []; processNode(sourceFile); diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 81aae4c0e5e3a..cbe288cbff6d2 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -35,7 +35,7 @@ namespace ts.codefix { */ export function createMissingMemberNodes(classDeclaration: ClassLikeDeclaration, possiblyMissingSymbols: Symbol[], checker: TypeChecker): Node[] { const classMembers = classDeclaration.symbol.members; - const missingMembers = possiblyMissingSymbols.filter(symbol => !classMembers.has(symbol.getName())); + const missingMembers = possiblyMissingSymbols.filter(symbol => !classMembers.has(symbol.name)); let newNodes: Node[] = []; for (const symbol of missingMembers) { diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index c2d26da4392d1..0bf99c130981e 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -148,7 +148,7 @@ namespace ts.codefix { else if (isJsxOpeningLikeElement(token.parent) && token.parent.tagName === token) { // The error wasn't for the symbolAtLocation, it was for the JSX tag itself, which needs access to e.g. `React`. symbol = checker.getAliasedSymbol(checker.resolveNameAtLocation(token, checker.getJsxNamespace(), SymbolFlags.Value)); - symbolName = symbol.name; + symbolName = symbol.getName(); } else { Debug.fail("Either the symbol or the JSX namespace should be a UMD global if we got here"); diff --git a/src/services/completions.ts b/src/services/completions.ts index 410ba636d7b77..f131c0329f864 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -88,10 +88,11 @@ namespace ts.Completions { if (pos === position) { return; } + const realName = unescapeIdentifier(name); - if (!uniqueNames.get(name)) { - uniqueNames.set(name, name); - const displayName = getCompletionEntryDisplayName(unescapeIdentifier(name), target, /*performCharacterChecks*/ true); + if (!uniqueNames.get(realName)) { + uniqueNames.set(realName, realName); + const displayName = getCompletionEntryDisplayName(realName, target, /*performCharacterChecks*/ true); if (displayName) { const entry = { name: displayName, @@ -139,7 +140,7 @@ namespace ts.Completions { for (const symbol of symbols) { const entry = createCompletionEntry(symbol, location, performCharacterChecks, typeChecker, target); if (entry) { - const id = escapeIdentifier(entry.name); + const id = entry.name; if (!uniqueNames.get(id)) { entries.push(entry); uniqueNames.set(id, id); @@ -613,7 +614,7 @@ namespace ts.Completions { if (symbol && symbol.flags & SymbolFlags.HasExports) { // Extract module or enum members const exportedSymbols = typeChecker.getExportsOfModule(symbol); - const isValidValueAccess = (symbol: Symbol) => typeChecker.isValidPropertyAccess((node.parent), symbol.name); + const isValidValueAccess = (symbol: Symbol) => typeChecker.isValidPropertyAccess((node.parent), symbol.getName()); const isValidTypeAccess = (symbol: Symbol) => symbolCanbeReferencedAtTypeLocation(symbol); const isValidAccess = isRhsOfImportDeclaration ? // Any kind is allowed when dotting off namespace in internal import equals declaration @@ -637,7 +638,7 @@ namespace ts.Completions { if (type) { // Filter private properties for (const symbol of type.getApparentProperties()) { - if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { + if (typeChecker.isValidPropertyAccess((node.parent), symbol.getName())) { symbols.push(symbol); } } @@ -1446,7 +1447,7 @@ namespace ts.Completions { * do not occur at the current position and have not otherwise been typed. */ function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ImportOrExportSpecifier[]): Symbol[] { - const existingImportsOrExports = createMap(); + const existingImportsOrExports = createMap() as EscapedIdentifierMap; for (const element of namedImportsOrExports) { // If this is the current item we are editing right now, do not filter it out @@ -1476,7 +1477,7 @@ namespace ts.Completions { return contextualMemberSymbols; } - const existingMemberNames = createMap(); + const existingMemberNames = createMap() as EscapedIdentifierMap; for (const m of existingMembers) { // Ignore omitted expressions for missing members if (m.kind !== SyntaxKind.PropertyAssignment && @@ -1493,7 +1494,7 @@ namespace ts.Completions { continue; } - let existingName: string; + let existingName: EscapedIdentifier; if (m.kind === SyntaxKind.BindingElement && (m).propertyName) { // include only identifiers in completion list @@ -1505,7 +1506,8 @@ namespace ts.Completions { // TODO(jfreeman): Account for computed property name // NOTE: if one only performs this step when m.name is an identifier, // things like '__proto__' are not filtered out. - existingName = (getNameOfDeclaration(m) as Identifier).text; + const name = getNameOfDeclaration(m); + existingName = name.kind === SyntaxKind.Identifier ? name.text : escapeIdentifier((name as LiteralExpression).text); // Literals used as identifiers must be escaped to be valid symbol names } existingMemberNames.set(existingName, true); @@ -1520,7 +1522,7 @@ namespace ts.Completions { * @returns Symbols to be suggested in an class element depending on existing memebers and symbol flags */ function filterClassMembersList(baseSymbols: Symbol[], implementingTypeSymbols: Symbol[], existingMembers: ClassElement[], currentClassElementModifierFlags: ModifierFlags): Symbol[] { - const existingMemberNames = createMap(); + const existingMemberNames = createMap() as EscapedIdentifierMap; for (const m of existingMembers) { // Ignore omitted expressions for missing members if (m.kind !== SyntaxKind.PropertyDeclaration && @@ -1573,7 +1575,7 @@ namespace ts.Completions { * do not occur at the current position and have not otherwise been typed. */ function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray): Symbol[] { - const seenNames = createMap(); + const seenNames = createMap() as EscapedIdentifierMap; for (const attr of attributes) { // If this is the current item we are editing right now, do not filter it out if (isCurrentlyEditingNode(attr)) { diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index fc84b60cc1f6e..3d016d5a8d12d 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -248,7 +248,7 @@ namespace ts.DocumentHighlights { case SyntaxKind.ForOfStatement: case SyntaxKind.WhileStatement: case SyntaxKind.DoStatement: - if (!statement.label || isLabeledBy(node, statement.label.text)) { + if (!statement.label || isLabeledBy(node, unescapeIdentifier(statement.label.text))) { return node; } break; diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 192895cde591c..ecfb4c77320ab 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -122,7 +122,7 @@ namespace ts.FindAllReferences { } case "label": { const { node } = def; - return { node, name: node.text, kind: ScriptElementKind.label, displayParts: [displayPart(node.text, SymbolDisplayPartKind.text)] }; + return { node, name: unescapeIdentifier(node.text), kind: ScriptElementKind.label, displayParts: [displayPart(unescapeIdentifier(node.text), SymbolDisplayPartKind.text)] }; } case "keyword": { const { node } = def; @@ -357,7 +357,7 @@ namespace ts.FindAllReferences.Core { // Labels if (isLabelName(node)) { if (isJumpStatementTarget(node)) { - const labelDefinition = getTargetLabel((node.parent), (node).text); + const labelDefinition = getTargetLabel((node.parent), unescapeIdentifier((node).text)); // if we have a label definition, look within its statement for references, if not, then // the label is undefined and we have no results.. return labelDefinition && getLabelReferencesInNode(labelDefinition.parent, labelDefinition); @@ -432,7 +432,7 @@ namespace ts.FindAllReferences.Core { readonly location: Node; readonly symbol: Symbol; readonly text: string; - readonly escapedText: string; + readonly escapedText: EscapedIdentifier; /** Only set if `options.implementations` is true. These are the symbols checked to get the implementations of a property access. */ readonly parents: Symbol[] | undefined; @@ -604,7 +604,7 @@ namespace ts.FindAllReferences.Core { if (isObjectBindingPatternElementWithoutPropertyName(symbol)) { const bindingElement = getDeclarationOfKind(symbol, SyntaxKind.BindingElement); const typeOfPattern = checker.getTypeAtLocation(bindingElement.parent); - return typeOfPattern && checker.getPropertyOfType(typeOfPattern, (bindingElement.name).text); + return typeOfPattern && checker.getPropertyOfType(typeOfPattern, unescapeIdentifier((bindingElement.name).text)); } return undefined; } @@ -716,7 +716,7 @@ namespace ts.FindAllReferences.Core { function getLabelReferencesInNode(container: Node, targetLabel: Identifier): SymbolAndEntries[] { const references: Entry[] = []; const sourceFile = container.getSourceFile(); - const labelName = targetLabel.text; + const labelName = unescapeIdentifier(targetLabel.text); const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container); for (const position of possiblePositions) { const node = getTouchingWord(sourceFile, position, /*includeJsDocComment*/ false); @@ -977,7 +977,7 @@ namespace ts.FindAllReferences.Core { * Reference the constructor and all calls to `new this()`. */ function findOwnConstructorReferences(classSymbol: Symbol, sourceFile: SourceFile, addNode: (node: Node) => void): void { - for (const decl of classSymbol.members.get("__constructor").declarations) { + for (const decl of classSymbol.members.get("__constructor" as EscapedIdentifier).declarations) { const ctrKeyword = ts.findChildOfKind(decl, ts.SyntaxKind.ConstructorKeyword, sourceFile)!; Debug.assert(decl.kind === SyntaxKind.Constructor && !!ctrKeyword); addNode(ctrKeyword); @@ -1001,7 +1001,7 @@ namespace ts.FindAllReferences.Core { /** Find references to `super` in the constructor of an extending class. */ function findSuperConstructorAccesses(cls: ClassLikeDeclaration, addNode: (node: Node) => void): void { const symbol = cls.symbol; - const ctr = symbol.members.get("__constructor"); + const ctr = symbol.members.get("__constructor" as EscapedIdentifier); if (!ctr) { return; } @@ -1414,7 +1414,7 @@ namespace ts.FindAllReferences.Core { // Property Declaration symbol is a member of the class, so the symbol is stored in its class Declaration.symbol.members if (symbol.valueDeclaration && symbol.valueDeclaration.kind === SyntaxKind.Parameter && isParameterPropertyDeclaration(symbol.valueDeclaration)) { - addRange(result, checker.getSymbolsOfParameterPropertyDeclaration(symbol.valueDeclaration, symbol.name)); + addRange(result, checker.getSymbolsOfParameterPropertyDeclaration(symbol.valueDeclaration, symbol.getName())); } // If this is symbol of binding element without propertyName declaration in Object binding pattern @@ -1433,7 +1433,7 @@ namespace ts.FindAllReferences.Core { // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions if (!implementations && rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { - getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ createMap(), checker); + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ createSymbolTable(), checker); } } @@ -1551,7 +1551,7 @@ namespace ts.FindAllReferences.Core { } const result: Symbol[] = []; - getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ createMap(), state.checker); + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ createSymbolTable(), state.checker); return find(result, search.includes); } @@ -1568,7 +1568,10 @@ namespace ts.FindAllReferences.Core { } return undefined; } - return (node.name).text; + if (node.name.kind === SyntaxKind.Identifier) { + return unescapeIdentifier(node.name.text); + } + return node.name.text; } /** Gets all symbols for one property. Does not get symbols for every property. */ diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index ac60ba7942c05..bc0e7d106c4bf 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -26,8 +26,8 @@ namespace ts.GoToDefinition { // Labels if (isJumpStatementTarget(node)) { - const labelName = (node).text; - const label = getTargetLabel((node.parent), (node).text); + const labelName = unescapeIdentifier((node).text); + const label = getTargetLabel((node.parent), labelName); return label ? [createDefinitionInfoFromName(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; } diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index 5e8e7b8b3a7f4..1405bcffe82de 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -597,15 +597,15 @@ namespace ts.FindAllReferences { function symbolName(symbol: Symbol): string | undefined { if (symbol.name !== "default") { - return symbol.name; + return symbol.getName(); } return forEach(symbol.declarations, decl => { if (isExportAssignment(decl)) { - return isIdentifier(decl.expression) ? decl.expression.text : undefined; + return isIdentifier(decl.expression) ? unescapeIdentifier(decl.expression.text) : undefined; } const name = getNameOfDeclaration(decl); - return name && name.kind === SyntaxKind.Identifier && name.text; + return name && name.kind === SyntaxKind.Identifier && unescapeIdentifier(name.text); }); } diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index 5d03ad03b0c8f..6acd3b106704a 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -82,7 +82,7 @@ namespace ts.JsDoc { if (tagsForDoc) { tags.push(...tagsForDoc.filter(tag => tag.kind === SyntaxKind.JSDocTag).map(jsDocTag => { return { - name: jsDocTag.tagName.text, + name: unescapeIdentifier(jsDocTag.tagName.text), text: jsDocTag.comment }; })); } @@ -133,7 +133,7 @@ namespace ts.JsDoc { } export function getJSDocParameterNameCompletions(tag: JSDocParameterTag): CompletionEntry[] { - const nameThusFar = tag.name.text; + const nameThusFar = unescapeIdentifier(tag.name.text); const jsdoc = tag.parent; const fn = jsdoc.parent; if (!ts.isFunctionLike(fn)) return []; @@ -141,7 +141,7 @@ namespace ts.JsDoc { return mapDefined(fn.parameters, param => { if (!isIdentifier(param.name)) return undefined; - const name = param.name.text; + const name = unescapeIdentifier(param.name.text); if (jsdoc.tags.some(t => t !== tag && isJSDocParameterTag(t) && t.name.text === name) || nameThusFar !== undefined && !startsWith(name, nameThusFar)) { return undefined; diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index 304f64f3cdbbb..b79fd36fbd372 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -85,11 +85,13 @@ namespace ts.NavigateTo { function getTextOfIdentifierOrLiteral(node: Node) { if (node) { - if (node.kind === SyntaxKind.Identifier || - node.kind === SyntaxKind.StringLiteral || + if (node.kind === SyntaxKind.Identifier) { + return unescapeIdentifier((node).text); + } + if (node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NumericLiteral) { - return (node).text; + return (node).text; } } @@ -132,7 +134,7 @@ namespace ts.NavigateTo { if (expression.kind === SyntaxKind.PropertyAccessExpression) { const propertyAccess = expression; if (includeLastPortion) { - containers.unshift(propertyAccess.name.text); + containers.unshift(unescapeIdentifier(propertyAccess.name.text)); } return tryAddComputedPropertyName(propertyAccess.expression, containers, /*includeLastPortion*/ true); @@ -204,7 +206,7 @@ namespace ts.NavigateTo { fileName: rawItem.fileName, textSpan: createTextSpanFromNode(declaration), // TODO(jfreeman): What should be the containerName when the container has a computed name? - containerName: containerName ? (containerName).text : "", + containerName: containerName ? unescapeIdentifier((containerName).text) : "", containerKind: containerName ? getNodeKind(container) : ScriptElementKind.unknown }; } diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 819202ff6f4ec..4a97faedbc0dc 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -380,7 +380,7 @@ namespace ts.NavigationBar { const declName = getNameOfDeclaration(node); if (declName) { - return getPropertyNameForPropertyNameNode(declName); + return unescapeIdentifier(getPropertyNameForPropertyNameNode(declName)); } switch (node.kind) { case SyntaxKind.FunctionExpression: @@ -442,7 +442,7 @@ namespace ts.NavigationBar { function getJSDocTypedefTagName(node: JSDocTypedefTag): string { if (node.name) { - return node.name.text; + return unescapeIdentifier(node.name.text); } else { const parentNode = node.parent && node.parent.parent; @@ -450,7 +450,7 @@ namespace ts.NavigationBar { if ((parentNode).declarationList.declarations.length > 0) { const nameIdentifier = (parentNode).declarationList.declarations[0].name; if (nameIdentifier.kind === SyntaxKind.Identifier) { - return (nameIdentifier).text; + return unescapeIdentifier((nameIdentifier).text); } } } @@ -580,12 +580,12 @@ namespace ts.NavigationBar { // Otherwise, we need to aggregate each identifier to build up the qualified name. const result: string[] = []; - result.push(moduleDeclaration.name.text); + result.push(moduleDeclaration.name.kind === SyntaxKind.Identifier ? unescapeIdentifier(moduleDeclaration.name.text) : moduleDeclaration.name.text); while (moduleDeclaration.body && moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) { moduleDeclaration = moduleDeclaration.body; - result.push(moduleDeclaration.name.text); + result.push(moduleDeclaration.name.kind === SyntaxKind.Identifier ? unescapeIdentifier(moduleDeclaration.name.text) : moduleDeclaration.name.text); } return result.join("."); diff --git a/src/services/pathCompletions.ts b/src/services/pathCompletions.ts index 3ded126ab6552..db3235864eaee 100644 --- a/src/services/pathCompletions.ts +++ b/src/services/pathCompletions.ts @@ -244,7 +244,7 @@ namespace ts.Completions.PathCompletions { const moduleNameFragment = isNestedModule ? fragment.substr(0, fragment.lastIndexOf(directorySeparator)) : undefined; // Get modules that the type checker picked up - const ambientModules = map(typeChecker.getAmbientModules(), sym => stripQuotes(sym.name)); + const ambientModules = map(typeChecker.getAmbientModules(), sym => stripQuotes(unescapeIdentifier(sym.name))); let nonRelativeModuleNames = filter(ambientModules, moduleName => startsWith(moduleName, fragment)); // Nested modules of the form "module-name/sub" need to be adjusted to only return the string diff --git a/src/services/refactors/convertFunctionToEs6Class.ts b/src/services/refactors/convertFunctionToEs6Class.ts index 745ba6d15bfd7..c15123092dc99 100644 --- a/src/services/refactors/convertFunctionToEs6Class.ts +++ b/src/services/refactors/convertFunctionToEs6Class.ts @@ -159,7 +159,7 @@ namespace ts.refactor { deleteNode(nodeToDelete); if (!assignmentBinaryExpression.right) { - return createProperty([], modifiers, symbol.name, /*questionToken*/ undefined, + return createProperty([], modifiers, symbol.getName(), /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined); } diff --git a/src/services/services.ts b/src/services/services.ts index 402baf12eecec..810c853a81f31 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -304,7 +304,7 @@ namespace ts { class SymbolObject implements Symbol { flags: SymbolFlags; - name: string; + name: EscapedIdentifier; declarations?: Declaration[]; // Undefined is used to indicate the value has not been computed. If, after computing, the @@ -315,7 +315,7 @@ namespace ts { // symbol has no JSDoc tags, then the empty array will be returned. tags?: JSDocTagInfo[]; - constructor(flags: SymbolFlags, name: string) { + constructor(flags: SymbolFlags, name: EscapedIdentifier) { this.flags = flags; this.name = name; } @@ -325,7 +325,7 @@ namespace ts { } getName(): string { - return this.name; + return unescapeIdentifier(this.name); } getDeclarations(): Declaration[] | undefined { @@ -360,7 +360,7 @@ namespace ts { class IdentifierObject extends TokenOrIdentifierObject implements Identifier { public kind: SyntaxKind.Identifier; - public text: string; + public text: EscapedIdentifier; _primaryExpressionBrand: any; _memberExpressionBrand: any; _leftHandSideExpressionBrand: any; @@ -508,8 +508,8 @@ namespace ts { public scriptKind: ScriptKind; public languageVersion: ScriptTarget; public languageVariant: LanguageVariant; - public identifiers: Map; - public nameTable: Map; + public identifiers: EscapedIdentifierMap; + public nameTable: EscapedIdentifierMap; public resolvedModules: Map; public resolvedTypeReferenceDirectiveNames: Map; public imports: StringLiteral[]; @@ -597,7 +597,7 @@ namespace ts { if (name.kind === SyntaxKind.ComputedPropertyName) { const expr = (name).expression; if (expr.kind === SyntaxKind.PropertyAccessExpression) { - return (expr).name.text; + return unescapeIdentifier((expr).name.text); } return getTextOfIdentifierOrLiteral(expr); @@ -609,11 +609,13 @@ namespace ts { function getTextOfIdentifierOrLiteral(node: Node) { if (node) { - if (node.kind === SyntaxKind.Identifier || - node.kind === SyntaxKind.StringLiteral || + if (node.kind === SyntaxKind.Identifier) { + return unescapeIdentifier((node).text); + } + if (node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NumericLiteral) { - return (node).text; + return (node).text; } } @@ -2082,7 +2084,7 @@ namespace ts { /* @internal */ /** Names in the name table are escaped, so an identifier `__foo` will have a name table entry `___foo`. */ - export function getNameTable(sourceFile: SourceFile): Map { + export function getNameTable(sourceFile: SourceFile): EscapedIdentifierMap { if (!sourceFile.nameTable) { initializeNameTable(sourceFile); } @@ -2091,7 +2093,7 @@ namespace ts { } function initializeNameTable(sourceFile: SourceFile): void { - const nameTable = createMap(); + const nameTable = createMap() as EscapedIdentifierMap; walk(sourceFile); sourceFile.nameTable = nameTable; @@ -2111,7 +2113,7 @@ namespace ts { node.parent.kind === SyntaxKind.ExternalModuleReference || isArgumentOfElementAccessExpression(node) || isLiteralComputedPropertyDeclarationName(node)) { - setNameTable((node).text, node); + setNameTable((node).text as EscapedIdentifier, node); // Literal expressions are escaped } break; default: @@ -2124,7 +2126,7 @@ namespace ts { } } - function setNameTable(text: string, node: ts.Node): void { + function setNameTable(text: EscapedIdentifier, node: ts.Node): void { nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1); } } @@ -2167,7 +2169,7 @@ namespace ts { export function getPropertySymbolsFromContextualType(typeChecker: TypeChecker, node: ObjectLiteralElement): Symbol[] { const objectLiteral = node.parent; const contextualType = typeChecker.getContextualType(objectLiteral); - const name = getTextOfPropertyName(node.name); + const name = unescapeIdentifier(getTextOfPropertyName(node.name)); if (name && contextualType) { const result: Symbol[] = []; const symbol = contextualType.getProperty(name); diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 785c5b0ab747a..3c46e056d2f41 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -74,7 +74,7 @@ namespace ts.SignatureHelp { const typeChecker = program.getTypeChecker(); for (const sourceFile of program.getSourceFiles()) { const nameToDeclarations = sourceFile.getNamedDeclarations(); - const declarations = nameToDeclarations.get(name.text); + const declarations = nameToDeclarations.get(unescapeIdentifier(name.text)); if (declarations) { for (const declaration of declarations) { @@ -416,7 +416,7 @@ namespace ts.SignatureHelp { typeChecker.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation)); return { - name: parameter.name, + name: parameter.getName(), documentation: parameter.getDocumentationComment(), displayParts, isOptional: typeChecker.isOptionalParameter(parameter.valueDeclaration) @@ -428,7 +428,7 @@ namespace ts.SignatureHelp { typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, invocation)); return { - name: typeParameter.symbol.name, + name: typeParameter.symbol.getName(), documentation: emptyArray, displayParts, isOptional: false diff --git a/src/services/types.ts b/src/services/types.ts index 447029a2f668f..edd22ca05759b 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -56,7 +56,7 @@ namespace ts { export interface SourceFile { /* @internal */ version: string; /* @internal */ scriptSnapshot: IScriptSnapshot; - /* @internal */ nameTable: Map; + /* @internal */ nameTable: EscapedIdentifierMap; /* @internal */ getNamedDeclarations(): Map; diff --git a/src/services/utilities.ts b/src/services/utilities.ts index a3e44f00d1afa..7e8f27c4c3827 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1092,7 +1092,7 @@ namespace ts { /** True if the symbol is for an external module, as opposed to a namespace. */ export function isExternalModuleSymbol(moduleSymbol: Symbol): boolean { Debug.assert(!!(moduleSymbol.flags & SymbolFlags.Module)); - return moduleSymbol.name.charCodeAt(0) === CharacterCodes.doubleQuote; + return moduleSymbol.getName().charCodeAt(0) === CharacterCodes.doubleQuote; } /** Returns `true` the first time it encounters a node and `false` afterwards. */ @@ -1272,7 +1272,7 @@ namespace ts { // If this is an export or import specifier it could have been renamed using the 'as' syntax. // If so we want to search for whatever is under the cursor. if (isImportOrExportSpecifierName(location) || isStringOrNumericLiteral(location) && location.parent.kind === SyntaxKind.ComputedPropertyName) { - return location.text; + return location.kind === SyntaxKind.Identifier ? unescapeIdentifier((location as Identifier).text) : (location as LiteralLikeNode).text; } // Try to get the local symbol if we're dealing with an 'export default' diff --git a/tests/baselines/reference/doubleUnderscoreSymbolsAndEmit.errors.txt b/tests/baselines/reference/doubleUnderscoreSymbolsAndEmit.errors.txt new file mode 100644 index 0000000000000..b35e68749b840 --- /dev/null +++ b/tests/baselines/reference/doubleUnderscoreSymbolsAndEmit.errors.txt @@ -0,0 +1,60 @@ +tests/cases/compiler/index.tsx(33,1): error TS2308: Module "./b" has already exported a member named '__foo'. Consider explicitly re-exporting to resolve the ambiguity. + + +==== tests/cases/compiler/index.tsx (1 errors) ==== + declare global { + namespace JSX { + interface IntrinsicElements { + __foot: any; + } + } + function __make (params: object): any; + } + + enum Foo { + "__a" = 1, + "(Anonymous function)" = 2, + "(Anonymous class)" = 4, + "__call" = 10 + } + namespace Foo { + export function ___call(): number { + return 5; + } + } + function Bar() { + return "no"; + } + namespace Bar { + export function __call(x: number): number { + return 5; + } + } + + const thing = <__foot>; + + export * from "./b"; + export * from "./c"; + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2308: Module "./b" has already exported a member named '__foo'. Consider explicitly re-exporting to resolve the ambiguity. + + function doThing() { + __call: while (true) { + aLabel: for (let i = 0; i < 10; i++) { + if (i === 3) { + break __call; + } + if (i === 5) { + break aLabel; + } + } + } + } + doThing(); + +==== tests/cases/compiler/b.ts (0 errors) ==== + export function __foo(): number | void {} + +==== tests/cases/compiler/c.ts (0 errors) ==== + export function __foo(): string | void {} + \ No newline at end of file diff --git a/tests/baselines/reference/doubleUnderscoreSymbolsAndEmit.js b/tests/baselines/reference/doubleUnderscoreSymbolsAndEmit.js new file mode 100644 index 0000000000000..bee117f7d3283 --- /dev/null +++ b/tests/baselines/reference/doubleUnderscoreSymbolsAndEmit.js @@ -0,0 +1,112 @@ +//// [tests/cases/compiler/doubleUnderscoreSymbolsAndEmit.ts] //// + +//// [index.tsx] +declare global { + namespace JSX { + interface IntrinsicElements { + __foot: any; + } + } + function __make (params: object): any; +} + +enum Foo { + "__a" = 1, + "(Anonymous function)" = 2, + "(Anonymous class)" = 4, + "__call" = 10 +} +namespace Foo { + export function ___call(): number { + return 5; + } +} +function Bar() { + return "no"; +} +namespace Bar { + export function __call(x: number): number { + return 5; + } +} + +const thing = <__foot>; + +export * from "./b"; +export * from "./c"; + +function doThing() { + __call: while (true) { + aLabel: for (let i = 0; i < 10; i++) { + if (i === 3) { + break __call; + } + if (i === 5) { + break aLabel; + } + } + } +} +doThing(); + +//// [b.ts] +export function __foo(): number | void {} + +//// [c.ts] +export function __foo(): string | void {} + + +//// [b.js] +"use strict"; +exports.__esModule = true; +function __foo() { } +exports.__foo = __foo; +//// [c.js] +"use strict"; +exports.__esModule = true; +function __foo() { } +exports.__foo = __foo; +//// [index.js] +"use strict"; +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +exports.__esModule = true; +var Foo; +(function (Foo) { + Foo[Foo["__a"] = 1] = "__a"; + Foo[Foo["(Anonymous function)"] = 2] = "(Anonymous function)"; + Foo[Foo["(Anonymous class)"] = 4] = "(Anonymous class)"; + Foo[Foo["__call"] = 10] = "__call"; +})(Foo || (Foo = {})); +(function (Foo) { + function ___call() { + return 5; + } + Foo.___call = ___call; +})(Foo || (Foo = {})); +function Bar() { + return "no"; +} +(function (Bar) { + function __call(x) { + return 5; + } + Bar.__call = __call; +})(Bar || (Bar = {})); +var thing = __make("__foot", null); +__export(require("./b")); +__export(require("./c")); +function doThing() { + __call: while (true) { + aLabel: for (var i = 0; i < 10; i++) { + if (i === 3) { + break __call; + } + if (i === 5) { + break aLabel; + } + } + } +} +doThing(); diff --git a/tests/cases/compiler/doubleUnderscoreSymbolsAndEmit.ts b/tests/cases/compiler/doubleUnderscoreSymbolsAndEmit.ts new file mode 100644 index 0000000000000..91bd8a38dc74e --- /dev/null +++ b/tests/cases/compiler/doubleUnderscoreSymbolsAndEmit.ts @@ -0,0 +1,58 @@ +// @jsx: react +// @jsxFactory: __make +// @module: commonjs +// @filename: index.tsx + +declare global { + namespace JSX { + interface IntrinsicElements { + __foot: any; + } + } + function __make (params: object): any; +} + +enum Foo { + "__a" = 1, + "(Anonymous function)" = 2, + "(Anonymous class)" = 4, + "__call" = 10 +} +namespace Foo { + export function ___call(): number { + return 5; + } +} +function Bar() { + return "no"; +} +namespace Bar { + export function __call(x: number): number { + return 5; + } +} + +const thing = <__foot>; + +export * from "./b"; +export * from "./c"; + +function doThing() { + __call: while (true) { + aLabel: for (let i = 0; i < 10; i++) { + if (i === 3) { + break __call; + } + if (i === 5) { + break aLabel; + } + } + } +} +doThing(); + +// @filename: b.ts +export function __foo(): number | void {} + +// @filename: c.ts +export function __foo(): string | void {} From ce4018ce07cd90fa76778acd998d66523299398f Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 3 Jul 2017 13:42:46 -0700 Subject: [PATCH 02/25] Correctly double underscores WRT mapped types --- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 4 +- src/compiler/parser.ts | 2 +- .../reference/doubleUnderscoreMappedTypes.js | 38 ++++++++++++ .../doubleUnderscoreMappedTypes.symbols | 52 ++++++++++++++++ .../doubleUnderscoreMappedTypes.types | 59 +++++++++++++++++++ ...pedReservedCompilerNamedIdentifier.symbols | 4 -- ...capedReservedCompilerNamedIdentifier.types | 8 +-- .../protoAsIndexInIndexExpression.types | 2 +- .../baselines/reference/protoInIndexer.types | 2 +- .../compiler/doubleUnderscoreMappedTypes.ts | 23 ++++++++ 11 files changed, 182 insertions(+), 14 deletions(-) create mode 100644 tests/baselines/reference/doubleUnderscoreMappedTypes.js create mode 100644 tests/baselines/reference/doubleUnderscoreMappedTypes.symbols create mode 100644 tests/baselines/reference/doubleUnderscoreMappedTypes.types create mode 100644 tests/cases/compiler/doubleUnderscoreMappedTypes.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index d8b34bbbaa707..b055a80920bb9 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1666,7 +1666,7 @@ namespace ts { continue; } - const identifier = prop.name; + const identifier = prop.name; // ECMA-262 11.1.5 Object Initializer // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 94bb6ffc83fae..7bec6b8f65cea 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7492,12 +7492,12 @@ namespace ts { function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode, cacheSymbol: boolean) { const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined; const propName = indexType.flags & TypeFlags.StringOrNumberLiteral ? - "" + (indexType).value : + escapeIdentifier("" + (indexType).value) : accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false) ? getPropertyNameForKnownSymbolName(unescapeIdentifier(((accessExpression.argumentExpression).name).text)) : undefined; if (propName !== undefined) { - const prop = getPropertyOfType(objectType, propName as EscapedIdentifier); // Symbols, numbers, and strings are escaped already by this point + const prop = getPropertyOfType(objectType, propName); if (prop) { if (accessExpression) { if (isAssignmentTarget(accessExpression) && (isReferenceToReadonlyEntity(accessExpression, prop) || isReferenceThroughNamespaceImport(accessExpression))) { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a28ef611d3e13..587ba4b81734a 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -4100,7 +4100,7 @@ namespace ts { indexedAccess.argumentExpression = allowInAnd(parseExpression); if (indexedAccess.argumentExpression.kind === SyntaxKind.StringLiteral || indexedAccess.argumentExpression.kind === SyntaxKind.NumericLiteral) { const literal = indexedAccess.argumentExpression; - literal.text = internIdentifier(literal.text) as string; + internIdentifier(literal.text); } } diff --git a/tests/baselines/reference/doubleUnderscoreMappedTypes.js b/tests/baselines/reference/doubleUnderscoreMappedTypes.js new file mode 100644 index 0000000000000..5f136eddc2fca --- /dev/null +++ b/tests/baselines/reference/doubleUnderscoreMappedTypes.js @@ -0,0 +1,38 @@ +//// [doubleUnderscoreMappedTypes.ts] +interface Properties { + property1: string; + __property2: string; +} + +// As expected, I can make an object satisfying this interface +const ok: Properties = { + property1: "", + __property2: "" +}; + +// As expected, "__property2" is indeed a key of the type +type Keys = keyof Properties; +const k: Keys = "__property2"; // ok + +// This should be valid +type Property2Type = Properties["__property2"]; + +// And should work with partial +const partial: Partial = { + property1: "", + __property2: "" +}; + + +//// [doubleUnderscoreMappedTypes.js] +// As expected, I can make an object satisfying this interface +var ok = { + property1: "", + __property2: "" +}; +var k = "__property2"; // ok +// And should work with partial +var partial = { + property1: "", + __property2: "" +}; diff --git a/tests/baselines/reference/doubleUnderscoreMappedTypes.symbols b/tests/baselines/reference/doubleUnderscoreMappedTypes.symbols new file mode 100644 index 0000000000000..2569a88cf0720 --- /dev/null +++ b/tests/baselines/reference/doubleUnderscoreMappedTypes.symbols @@ -0,0 +1,52 @@ +=== tests/cases/compiler/doubleUnderscoreMappedTypes.ts === +interface Properties { +>Properties : Symbol(Properties, Decl(doubleUnderscoreMappedTypes.ts, 0, 0)) + + property1: string; +>property1 : Symbol(Properties.property1, Decl(doubleUnderscoreMappedTypes.ts, 0, 22)) + + __property2: string; +>__property2 : Symbol(Properties.__property2, Decl(doubleUnderscoreMappedTypes.ts, 1, 22)) +} + +// As expected, I can make an object satisfying this interface +const ok: Properties = { +>ok : Symbol(ok, Decl(doubleUnderscoreMappedTypes.ts, 6, 5)) +>Properties : Symbol(Properties, Decl(doubleUnderscoreMappedTypes.ts, 0, 0)) + + property1: "", +>property1 : Symbol(property1, Decl(doubleUnderscoreMappedTypes.ts, 6, 24)) + + __property2: "" +>__property2 : Symbol(__property2, Decl(doubleUnderscoreMappedTypes.ts, 7, 18)) + +}; + +// As expected, "__property2" is indeed a key of the type +type Keys = keyof Properties; +>Keys : Symbol(Keys, Decl(doubleUnderscoreMappedTypes.ts, 9, 2)) +>Properties : Symbol(Properties, Decl(doubleUnderscoreMappedTypes.ts, 0, 0)) + +const k: Keys = "__property2"; // ok +>k : Symbol(k, Decl(doubleUnderscoreMappedTypes.ts, 13, 5)) +>Keys : Symbol(Keys, Decl(doubleUnderscoreMappedTypes.ts, 9, 2)) + +// This should be valid +type Property2Type = Properties["__property2"]; +>Property2Type : Symbol(Property2Type, Decl(doubleUnderscoreMappedTypes.ts, 13, 30)) +>Properties : Symbol(Properties, Decl(doubleUnderscoreMappedTypes.ts, 0, 0)) + +// And should work with partial +const partial: Partial = { +>partial : Symbol(partial, Decl(doubleUnderscoreMappedTypes.ts, 19, 5)) +>Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) +>Properties : Symbol(Properties, Decl(doubleUnderscoreMappedTypes.ts, 0, 0)) + + property1: "", +>property1 : Symbol(property1, Decl(doubleUnderscoreMappedTypes.ts, 19, 38)) + + __property2: "" +>__property2 : Symbol(__property2, Decl(doubleUnderscoreMappedTypes.ts, 20, 18)) + +}; + diff --git a/tests/baselines/reference/doubleUnderscoreMappedTypes.types b/tests/baselines/reference/doubleUnderscoreMappedTypes.types new file mode 100644 index 0000000000000..6cac09578eef3 --- /dev/null +++ b/tests/baselines/reference/doubleUnderscoreMappedTypes.types @@ -0,0 +1,59 @@ +=== tests/cases/compiler/doubleUnderscoreMappedTypes.ts === +interface Properties { +>Properties : Properties + + property1: string; +>property1 : string + + __property2: string; +>__property2 : string +} + +// As expected, I can make an object satisfying this interface +const ok: Properties = { +>ok : Properties +>Properties : Properties +>{ property1: "", __property2: ""} : { property1: string; __property2: string; } + + property1: "", +>property1 : string +>"" : "" + + __property2: "" +>__property2 : string +>"" : "" + +}; + +// As expected, "__property2" is indeed a key of the type +type Keys = keyof Properties; +>Keys : "property1" | "__property2" +>Properties : Properties + +const k: Keys = "__property2"; // ok +>k : "property1" | "__property2" +>Keys : "property1" | "__property2" +>"__property2" : "__property2" + +// This should be valid +type Property2Type = Properties["__property2"]; +>Property2Type : string +>Properties : Properties + +// And should work with partial +const partial: Partial = { +>partial : Partial +>Partial : Partial +>Properties : Properties +>{ property1: "", __property2: ""} : { property1: string; __property2: string; } + + property1: "", +>property1 : string +>"" : "" + + __property2: "" +>__property2 : string +>"" : "" + +}; + diff --git a/tests/baselines/reference/escapedReservedCompilerNamedIdentifier.symbols b/tests/baselines/reference/escapedReservedCompilerNamedIdentifier.symbols index b629c5bd8750c..9cdd59134cb23 100644 --- a/tests/baselines/reference/escapedReservedCompilerNamedIdentifier.symbols +++ b/tests/baselines/reference/escapedReservedCompilerNamedIdentifier.symbols @@ -11,7 +11,6 @@ var o = { var b = o["__proto__"]; >b : Symbol(b, Decl(escapedReservedCompilerNamedIdentifier.ts, 5, 3)) >o : Symbol(o, Decl(escapedReservedCompilerNamedIdentifier.ts, 2, 3)) ->"__proto__" : Symbol("__proto__", Decl(escapedReservedCompilerNamedIdentifier.ts, 2, 9)) var o1 = { >o1 : Symbol(o1, Decl(escapedReservedCompilerNamedIdentifier.ts, 6, 3)) @@ -23,7 +22,6 @@ var o1 = { var b1 = o1["__proto__"]; >b1 : Symbol(b1, Decl(escapedReservedCompilerNamedIdentifier.ts, 9, 3)) >o1 : Symbol(o1, Decl(escapedReservedCompilerNamedIdentifier.ts, 6, 3)) ->"__proto__" : Symbol(__proto__, Decl(escapedReservedCompilerNamedIdentifier.ts, 6, 10)) // Triple underscores var ___proto__ = 10; @@ -37,7 +35,6 @@ var o2 = { var b2 = o2["___proto__"]; >b2 : Symbol(b2, Decl(escapedReservedCompilerNamedIdentifier.ts, 15, 3)) >o2 : Symbol(o2, Decl(escapedReservedCompilerNamedIdentifier.ts, 12, 3)) ->"___proto__" : Symbol("___proto__", Decl(escapedReservedCompilerNamedIdentifier.ts, 12, 10)) var o3 = { >o3 : Symbol(o3, Decl(escapedReservedCompilerNamedIdentifier.ts, 16, 3)) @@ -49,7 +46,6 @@ var o3 = { var b3 = o3["___proto__"]; >b3 : Symbol(b3, Decl(escapedReservedCompilerNamedIdentifier.ts, 19, 3)) >o3 : Symbol(o3, Decl(escapedReservedCompilerNamedIdentifier.ts, 16, 3)) ->"___proto__" : Symbol(___proto__, Decl(escapedReservedCompilerNamedIdentifier.ts, 16, 10)) // One underscore var _proto__ = 10; diff --git a/tests/baselines/reference/escapedReservedCompilerNamedIdentifier.types b/tests/baselines/reference/escapedReservedCompilerNamedIdentifier.types index 1cecaaa74f0f4..8af183766191b 100644 --- a/tests/baselines/reference/escapedReservedCompilerNamedIdentifier.types +++ b/tests/baselines/reference/escapedReservedCompilerNamedIdentifier.types @@ -16,7 +16,7 @@ var b = o["__proto__"]; >b : number >o["__proto__"] : number >o : { "__proto__": number; } ->"__proto__" : "___proto__" +>"__proto__" : "__proto__" var o1 = { >o1 : { __proto__: number; } @@ -31,7 +31,7 @@ var b1 = o1["__proto__"]; >b1 : number >o1["__proto__"] : number >o1 : { __proto__: number; } ->"__proto__" : "___proto__" +>"__proto__" : "__proto__" // Triple underscores var ___proto__ = 10; @@ -50,7 +50,7 @@ var b2 = o2["___proto__"]; >b2 : number >o2["___proto__"] : number >o2 : { "___proto__": number; } ->"___proto__" : "____proto__" +>"___proto__" : "___proto__" var o3 = { >o3 : { ___proto__: number; } @@ -65,7 +65,7 @@ var b3 = o3["___proto__"]; >b3 : number >o3["___proto__"] : number >o3 : { ___proto__: number; } ->"___proto__" : "____proto__" +>"___proto__" : "___proto__" // One underscore var _proto__ = 10; diff --git a/tests/baselines/reference/protoAsIndexInIndexExpression.types b/tests/baselines/reference/protoAsIndexInIndexExpression.types index b761aa2c7a70a..e9adb6705ac96 100644 --- a/tests/baselines/reference/protoAsIndexInIndexExpression.types +++ b/tests/baselines/reference/protoAsIndexInIndexExpression.types @@ -17,7 +17,7 @@ WorkspacePrototype['__proto__'] = EntityPrototype; >WorkspacePrototype['__proto__'] = EntityPrototype : any >WorkspacePrototype['__proto__'] : any >WorkspacePrototype : { serialize: () => any; } ->'__proto__' : "___proto__" +>'__proto__' : "__proto__" >EntityPrototype : any var o = { diff --git a/tests/baselines/reference/protoInIndexer.types b/tests/baselines/reference/protoInIndexer.types index 27f1f721fd3b2..c15f98b75ffcf 100644 --- a/tests/baselines/reference/protoInIndexer.types +++ b/tests/baselines/reference/protoInIndexer.types @@ -7,7 +7,7 @@ class X { >this['__proto__'] = null : null >this['__proto__'] : any >this : this ->'__proto__' : "___proto__" +>'__proto__' : "__proto__" >null : null } } diff --git a/tests/cases/compiler/doubleUnderscoreMappedTypes.ts b/tests/cases/compiler/doubleUnderscoreMappedTypes.ts new file mode 100644 index 0000000000000..693848abba1ba --- /dev/null +++ b/tests/cases/compiler/doubleUnderscoreMappedTypes.ts @@ -0,0 +1,23 @@ +interface Properties { + property1: string; + __property2: string; +} + +// As expected, I can make an object satisfying this interface +const ok: Properties = { + property1: "", + __property2: "" +}; + +// As expected, "__property2" is indeed a key of the type +type Keys = keyof Properties; +const k: Keys = "__property2"; // ok + +// This should be valid +type Property2Type = Properties["__property2"]; + +// And should work with partial +const partial: Partial = { + property1: "", + __property2: "" +}; From 342ec75d0a8026930035b18a9a1e250af88aeb5f Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 3 Jul 2017 13:59:16 -0700 Subject: [PATCH 03/25] Add fourslash tests for other fixed issues --- tests/cases/fourslash/doubleUnderscoreCompletions.ts | 12 ++++++++++++ tests/cases/fourslash/doubleUnderscoreRenames.ts | 12 ++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 tests/cases/fourslash/doubleUnderscoreCompletions.ts create mode 100644 tests/cases/fourslash/doubleUnderscoreRenames.ts diff --git a/tests/cases/fourslash/doubleUnderscoreCompletions.ts b/tests/cases/fourslash/doubleUnderscoreCompletions.ts new file mode 100644 index 0000000000000..df36a9adc4802 --- /dev/null +++ b/tests/cases/fourslash/doubleUnderscoreCompletions.ts @@ -0,0 +1,12 @@ +/// + +// @allowJs: true +// @Filename: a.js +//// function MyObject(){ +//// this.__property = 1; +//// } +//// var instance = new MyObject(); +//// instance./*1*/ + +goTo.marker("1"); +verify.completionListContains("__property", "(property) MyObject.__property: number"); diff --git a/tests/cases/fourslash/doubleUnderscoreRenames.ts b/tests/cases/fourslash/doubleUnderscoreRenames.ts new file mode 100644 index 0000000000000..5709be97b6f6b --- /dev/null +++ b/tests/cases/fourslash/doubleUnderscoreRenames.ts @@ -0,0 +1,12 @@ +/// + +// @Filename: fileA.ts +//// export function [|__foo|]() { +//// } +//// +// @Filename: fileB.ts +//// import { [|__foo|] as bar } from "./fileA"; +//// +//// bar(); + +verify.rangesAreRenameLocations(); From 1f553664f2eab48deda3c989b97d25f7eae897a2 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 5 Jul 2017 10:27:38 -0700 Subject: [PATCH 04/25] use function call over cast --- src/compiler/binder.ts | 4 ++-- src/compiler/checker.ts | 16 ++++++++-------- src/compiler/core.ts | 5 +++++ src/compiler/parser.ts | 2 +- src/compiler/program.ts | 2 +- src/compiler/transformers/ts.ts | 2 +- src/services/completions.ts | 8 ++++---- src/services/services.ts | 2 +- 8 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index b055a80920bb9..0c691e4dc4667 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -147,7 +147,7 @@ namespace ts { options = opts; languageVersion = getEmitScriptTarget(options); inStrictMode = bindInStrictMode(file, opts); - classifiableNames = createMap() as EscapedIdentifierMap; + classifiableNames = createEscapedIdentifierMap(); symbolCount = 0; skipTransformFlagAggregation = file.isDeclarationFile; @@ -1659,7 +1659,7 @@ namespace ts { } if (inStrictMode) { - const seen = createMap() as EscapedIdentifierMap; + const seen = createEscapedIdentifierMap(); for (const prop of node.properties) { if (prop.kind === SyntaxKind.SpreadAssignment || prop.name.kind !== SyntaxKind.Identifier) { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8ec8faf1be652..3b0d413a2a1ef 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -452,7 +452,7 @@ namespace ts { let _hasComputedJsxElementChildrenPropertyName = false; /** Things we lazy load from the JSX namespace */ - const jsxTypes = createMap() as EscapedIdentifierMap; + const jsxTypes = createEscapedIdentifierMap(); const JsxNames = { JSX: "JSX" as EscapedIdentifier, @@ -4075,7 +4075,7 @@ namespace ts { } const members = createSymbolTable(); - const names = createMap() as EscapedIdentifierMap; + const names = createEscapedIdentifierMap(); for (const name of properties) { names.set(getTextOfPropertyName(name), true); } @@ -7683,7 +7683,7 @@ namespace ts { } const members = createSymbolTable(); - const skippedPrivateMembers = createMap() as EscapedIdentifierMap; + const skippedPrivateMembers = createEscapedIdentifierMap(); let stringIndexInfo: IndexInfo; let numberIndexInfo: IndexInfo; if (left === emptyObjectType) { @@ -18078,8 +18078,8 @@ namespace ts { Property = Getter | Setter } - const instanceNames = createMap() as EscapedIdentifierMap; - const staticNames = createMap() as EscapedIdentifierMap; + const instanceNames = createEscapedIdentifierMap(); + const staticNames = createEscapedIdentifierMap(); for (const member of node.members) { if (member.kind === SyntaxKind.Constructor) { for (const param of (member as ConstructorDeclaration).parameters) { @@ -21167,7 +21167,7 @@ namespace ts { } type InheritanceInfoMap = { prop: Symbol; containingType: Type }; - const seen = createMap() as EscapedIdentifierMap; + const seen = createEscapedIdentifierMap(); forEach(resolveDeclaredMembers(type).declaredProperties, p => { seen.set(p.name, { prop: p, containingType: type }); }); let ok = true; @@ -24081,7 +24081,7 @@ namespace ts { } function checkGrammarObjectLiteralExpression(node: ObjectLiteralExpression, inDestructuring: boolean) { - const seen = createMap() as EscapedIdentifierMap; + const seen = createEscapedIdentifierMap(); const Property = 1; const GetAccessor = 2; const SetAccessor = 4; @@ -24171,7 +24171,7 @@ namespace ts { } function checkGrammarJsxElement(node: JsxOpeningLikeElement) { - const seen = createMap() as EscapedIdentifierMap; + const seen = createEscapedIdentifierMap(); for (const attr of node.attributes.properties) { if (attr.kind === SyntaxKind.JsxSpreadAttribute) { diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 129c5be1ba0de..eb87e9a957223 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -47,6 +47,11 @@ namespace ts { return new MapCtr(); } + /** Create a new escaped identifier map. */ + export function createEscapedIdentifierMap(): EscapedIdentifierMap { + return new MapCtr() as EscapedIdentifierMap; + } + /* @internal */ export function createSymbolTable(symbols?: Symbol[]): SymbolTable { const result = createMap() as SymbolTable; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 587ba4b81734a..95a5ba86c9f8d 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -681,7 +681,7 @@ namespace ts { parseDiagnostics = []; parsingContext = 0; - identifiers = createMap() as EscapedIdentifierMap; + identifiers = createEscapedIdentifierMap(); identifierCount = 0; nodeCount = 0; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 6c1b721e4eb2f..1a78a033228e2 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -580,7 +580,7 @@ namespace ts { if (!classifiableNames) { // Initialize a checker so that all our files are bound. getTypeChecker(); - classifiableNames = createMap() as EscapedIdentifierMap; + classifiableNames = createEscapedIdentifierMap(); for (const sourceFile of files) { copyEntries(sourceFile.classifiableNames, classifiableNames); diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 15e80af407306..7313397579866 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -2647,7 +2647,7 @@ namespace ts { const name = node.symbol && node.symbol.name; if (name) { if (!currentScopeFirstDeclarationsOfName) { - currentScopeFirstDeclarationsOfName = createMap() as EscapedIdentifierMap; + currentScopeFirstDeclarationsOfName = createEscapedIdentifierMap(); } if (!currentScopeFirstDeclarationsOfName.has(name)) { diff --git a/src/services/completions.ts b/src/services/completions.ts index f131c0329f864..a76f5398b150b 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1447,7 +1447,7 @@ namespace ts.Completions { * do not occur at the current position and have not otherwise been typed. */ function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ImportOrExportSpecifier[]): Symbol[] { - const existingImportsOrExports = createMap() as EscapedIdentifierMap; + const existingImportsOrExports = createEscapedIdentifierMap(); for (const element of namedImportsOrExports) { // If this is the current item we are editing right now, do not filter it out @@ -1477,7 +1477,7 @@ namespace ts.Completions { return contextualMemberSymbols; } - const existingMemberNames = createMap() as EscapedIdentifierMap; + const existingMemberNames = createEscapedIdentifierMap(); for (const m of existingMembers) { // Ignore omitted expressions for missing members if (m.kind !== SyntaxKind.PropertyAssignment && @@ -1522,7 +1522,7 @@ namespace ts.Completions { * @returns Symbols to be suggested in an class element depending on existing memebers and symbol flags */ function filterClassMembersList(baseSymbols: Symbol[], implementingTypeSymbols: Symbol[], existingMembers: ClassElement[], currentClassElementModifierFlags: ModifierFlags): Symbol[] { - const existingMemberNames = createMap() as EscapedIdentifierMap; + const existingMemberNames = createEscapedIdentifierMap(); for (const m of existingMembers) { // Ignore omitted expressions for missing members if (m.kind !== SyntaxKind.PropertyDeclaration && @@ -1575,7 +1575,7 @@ namespace ts.Completions { * do not occur at the current position and have not otherwise been typed. */ function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray): Symbol[] { - const seenNames = createMap() as EscapedIdentifierMap; + const seenNames = createEscapedIdentifierMap(); for (const attr of attributes) { // If this is the current item we are editing right now, do not filter it out if (isCurrentlyEditingNode(attr)) { diff --git a/src/services/services.ts b/src/services/services.ts index 810c853a81f31..f5ae8802f37d2 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2093,7 +2093,7 @@ namespace ts { } function initializeNameTable(sourceFile: SourceFile): void { - const nameTable = createMap() as EscapedIdentifierMap; + const nameTable = createEscapedIdentifierMap(); walk(sourceFile); sourceFile.nameTable = nameTable; From 44118898004f9442758ac2a27a50573a14f95cad Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 5 Jul 2017 10:36:47 -0700 Subject: [PATCH 05/25] Update forEachEntry type accuracy --- src/compiler/core.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index eb87e9a957223..3e9d5f179b7ea 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1016,13 +1016,13 @@ namespace ts { * Calls `callback` for each entry in the map, returning the first truthy result. * Use `map.forEach` instead for normal iteration. */ - export function forEachEntry(map: EscapedIdentifierMap, callback: (value: T, key: string) => U | undefined): U | undefined; + export function forEachEntry(map: EscapedIdentifierMap, callback: (value: T, key: EscapedIdentifier) => U | undefined): U | undefined; export function forEachEntry(map: Map, callback: (value: T, key: string) => U | undefined): U | undefined; - export function forEachEntry(map: EscapedIdentifierMap | Map, callback: (value: T, key: string) => U | undefined): U | undefined { + export function forEachEntry(map: EscapedIdentifierMap | Map, callback: (value: T, key: (string & EscapedIdentifier)) => U | undefined): U | undefined { const iterator = map.entries(); for (let { value: pair, done } = iterator.next(); !done; { value: pair, done } = iterator.next()) { const [key, value] = pair; - const result = callback(value, key as string); + const result = callback(value, key as (string & EscapedIdentifier)); if (result) { return result; } From 47f7fbd0a9986b972c7dd2d47a8c59efa93f1337 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 5 Jul 2017 10:38:12 -0700 Subject: [PATCH 06/25] Just use escaped names for ActiveLabel --- src/compiler/binder.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 0c691e4dc4667..5abab502777bd 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -10,7 +10,7 @@ namespace ts { } interface ActiveLabel { - name: string; + name: EscapedIdentifier; breakTarget: FlowLabel; continueTarget: FlowLabel; referenced: boolean; @@ -1007,7 +1007,7 @@ namespace ts { currentFlow = unreachableFlow; } - function findActiveLabel(name: string) { + function findActiveLabel(name: EscapedIdentifier) { if (activeLabels) { for (const label of activeLabels) { if (label.name === name) { @@ -1029,7 +1029,7 @@ namespace ts { function bindBreakOrContinueStatement(node: BreakOrContinueStatement): void { bind(node.label); if (node.label) { - const activeLabel = findActiveLabel(unescapeIdentifier(node.label.text)); + const activeLabel = findActiveLabel(node.label.text); if (activeLabel) { activeLabel.referenced = true; bindBreakOrContinueFlow(node, activeLabel.breakTarget, activeLabel.continueTarget); @@ -1170,7 +1170,7 @@ namespace ts { bindEach(node.statements); } - function pushActiveLabel(name: string, breakTarget: FlowLabel, continueTarget: FlowLabel): ActiveLabel { + function pushActiveLabel(name: EscapedIdentifier, breakTarget: FlowLabel, continueTarget: FlowLabel): ActiveLabel { const activeLabel = { name, breakTarget, @@ -1190,7 +1190,7 @@ namespace ts { const postStatementLabel = createBranchLabel(); bind(node.label); addAntecedent(preStatementLabel, currentFlow); - const activeLabel = pushActiveLabel(unescapeIdentifier(node.label.text), postStatementLabel, preStatementLabel); + const activeLabel = pushActiveLabel(node.label.text, postStatementLabel, preStatementLabel); bind(node.statement); popActiveLabel(); if (!activeLabel.referenced && !options.allowUnusedLabels) { From 7f22f390114ecb3e3283a9f57c2d20367116797b Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 5 Jul 2017 10:42:34 -0700 Subject: [PATCH 07/25] Remove casts from getPropertyNameForPropertyNameNode --- src/compiler/utilities.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index bdc094c266879..fafece141ab8c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1960,8 +1960,11 @@ namespace ts { } export function getPropertyNameForPropertyNameNode(name: DeclarationName): EscapedIdentifier { - if (name.kind === SyntaxKind.Identifier || name.kind === SyntaxKind.StringLiteral || name.kind === SyntaxKind.NumericLiteral) { - return name.text as EscapedIdentifier; + if (name.kind === SyntaxKind.Identifier) { + return name.text; + } + if (name.kind === SyntaxKind.StringLiteral || name.kind === SyntaxKind.NumericLiteral) { + return escapeIdentifier(name.text); } if (name.kind === SyntaxKind.ComputedPropertyName) { const nameExpression = name.expression; @@ -1970,7 +1973,7 @@ namespace ts { return getPropertyNameForKnownSymbolName(unescapeIdentifier(rightHandSideName)); } else if (nameExpression.kind === SyntaxKind.StringLiteral || nameExpression.kind === SyntaxKind.NumericLiteral) { - return (nameExpression).text as EscapedIdentifier; + return escapeIdentifier((nameExpression).text); } } From f88f21aa7d9259dcd29969e312f028c8c5f21e7d Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 5 Jul 2017 10:56:22 -0700 Subject: [PATCH 08/25] This pattern has occurred a few times, could use a helper function. --- src/compiler/binder.ts | 4 +-- src/compiler/checker.ts | 2 +- src/compiler/factory.ts | 2 +- src/compiler/transformers/module/system.ts | 2 +- src/compiler/utilities.ts | 30 ++++++++++++++++++++++ src/services/completions.ts | 2 +- src/services/navigationBar.ts | 4 +-- src/services/services.ts | 17 +----------- src/services/utilities.ts | 2 +- 9 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 5abab502777bd..14d6e6f1515a5 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -230,7 +230,7 @@ namespace ts { const name = getNameOfDeclaration(node); if (name) { if (isAmbientModule(node)) { - const moduleName = name.kind === SyntaxKind.Identifier ? unescapeIdentifier((name).text) : (name).text; + const moduleName = getTextOfIdentifierOrLiteral(name); return (isGlobalScopeAugmentation(node) ? "__global" : `"${moduleName}"`) as EscapedIdentifier; } if (name.kind === SyntaxKind.ComputedPropertyName) { @@ -243,7 +243,7 @@ namespace ts { Debug.assert(isWellKnownSymbolSyntactically(nameExpression)); return getPropertyNameForKnownSymbolName(unescapeIdentifier((nameExpression).name.text)); } - return name.kind === SyntaxKind.Identifier ? (name).text : ((name).text && escapeIdentifier((name).text)); // A literal expression used as a symbol name _must_ be escaped + return getEscapedTextOfIdentifierOrLiteral(name); } switch (node.kind) { case SyntaxKind.Constructor: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3b0d413a2a1ef..da37ca37c941a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21565,7 +21565,7 @@ namespace ts { if (isGlobalAugmentation) { error(node.name, Diagnostics.Augmentations_for_the_global_scope_can_only_be_directly_nested_in_external_modules_or_ambient_module_declarations); } - else if (isExternalModuleNameRelative(node.name.kind === SyntaxKind.Identifier ? unescapeIdentifier(node.name.text) : node.name.text)) { + else if (isExternalModuleNameRelative(getTextOfIdentifierOrLiteral(node.name))) { error(node.name, Diagnostics.Ambient_module_declaration_cannot_specify_relative_module_name); } } diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 4c086b78a4e36..35388b8af2264 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -99,7 +99,7 @@ namespace ts { } function createLiteralFromNode(sourceNode: StringLiteral | NumericLiteral | Identifier): StringLiteral { - const node = createStringLiteral(sourceNode.kind === SyntaxKind.Identifier ? unescapeIdentifier(sourceNode.text) : sourceNode.text); + const node = createStringLiteral(getTextOfIdentifierOrLiteral(sourceNode)); node.textSourceNode = sourceNode; return node; } diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 0049c50f23af0..46fcb2d4ba056 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -1055,7 +1055,7 @@ namespace ts { if (hasModifier(decl, ModifierFlags.Export)) { const exportName = hasModifier(decl, ModifierFlags.Default) ? createLiteral("default") : decl.name; statements = appendExportStatement(statements, exportName, getLocalName(decl)); - excludeName = exportName.kind === SyntaxKind.Identifier ? unescapeIdentifier(exportName.text) : exportName.text; + excludeName = getTextOfIdentifierOrLiteral(exportName); } if (decl.name) { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index fafece141ab8c..aad502b5519d7 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1980,6 +1980,36 @@ namespace ts { return undefined; } + export function getTextOfIdentifierOrLiteral(node: Identifier | LiteralLikeNode) { + if (node) { + if (node.kind === SyntaxKind.Identifier) { + return unescapeIdentifier((node as Identifier).text); + } + if (node.kind === SyntaxKind.StringLiteral || + node.kind === SyntaxKind.NumericLiteral) { + + return (node as LiteralLikeNode).text; + } + } + + return undefined; + } + + export function getEscapedTextOfIdentifierOrLiteral(node: Identifier | LiteralLikeNode) { + if (node) { + if (node.kind === SyntaxKind.Identifier) { + return (node as Identifier).text; + } + if (node.kind === SyntaxKind.StringLiteral || + node.kind === SyntaxKind.NumericLiteral) { + + return escapeIdentifier((node as LiteralLikeNode).text); + } + } + + return undefined; + } + export function getPropertyNameForKnownSymbolName(symbolName: string): EscapedIdentifier { return "__@" + symbolName as EscapedIdentifier; } diff --git a/src/services/completions.ts b/src/services/completions.ts index a76f5398b150b..a2a03f834fa1d 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1507,7 +1507,7 @@ namespace ts.Completions { // NOTE: if one only performs this step when m.name is an identifier, // things like '__proto__' are not filtered out. const name = getNameOfDeclaration(m); - existingName = name.kind === SyntaxKind.Identifier ? name.text : escapeIdentifier((name as LiteralExpression).text); // Literals used as identifiers must be escaped to be valid symbol names + existingName = getEscapedTextOfIdentifierOrLiteral(name as (Identifier | LiteralExpression)); } existingMemberNames.set(existingName, true); diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 4a97faedbc0dc..26b681d0c1785 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -580,12 +580,12 @@ namespace ts.NavigationBar { // Otherwise, we need to aggregate each identifier to build up the qualified name. const result: string[] = []; - result.push(moduleDeclaration.name.kind === SyntaxKind.Identifier ? unescapeIdentifier(moduleDeclaration.name.text) : moduleDeclaration.name.text); + result.push(getTextOfIdentifierOrLiteral(moduleDeclaration.name)); while (moduleDeclaration.body && moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) { moduleDeclaration = moduleDeclaration.body; - result.push(moduleDeclaration.name.kind === SyntaxKind.Identifier ? unescapeIdentifier(moduleDeclaration.name.text) : moduleDeclaration.name.text); + result.push(getTextOfIdentifierOrLiteral(moduleDeclaration.name)); } return result.join("."); diff --git a/src/services/services.ts b/src/services/services.ts index f5ae8802f37d2..4c6965fb2f9e6 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -607,21 +607,6 @@ namespace ts { return undefined; } - function getTextOfIdentifierOrLiteral(node: Node) { - if (node) { - if (node.kind === SyntaxKind.Identifier) { - return unescapeIdentifier((node).text); - } - if (node.kind === SyntaxKind.StringLiteral || - node.kind === SyntaxKind.NumericLiteral) { - - return (node).text; - } - } - - return undefined; - } - function visit(node: Node): void { switch (node.kind) { case SyntaxKind.FunctionDeclaration: @@ -2113,7 +2098,7 @@ namespace ts { node.parent.kind === SyntaxKind.ExternalModuleReference || isArgumentOfElementAccessExpression(node) || isLiteralComputedPropertyDeclarationName(node)) { - setNameTable((node).text as EscapedIdentifier, node); // Literal expressions are escaped + setNameTable((node).text, node); } break; default: diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 7e8f27c4c3827..f29b01c5f88ab 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1272,7 +1272,7 @@ namespace ts { // If this is an export or import specifier it could have been renamed using the 'as' syntax. // If so we want to search for whatever is under the cursor. if (isImportOrExportSpecifierName(location) || isStringOrNumericLiteral(location) && location.parent.kind === SyntaxKind.ComputedPropertyName) { - return location.kind === SyntaxKind.Identifier ? unescapeIdentifier((location as Identifier).text) : (location as LiteralLikeNode).text; + return getTextOfIdentifierOrLiteral(location); } // Try to get the local symbol if we're dealing with an 'export default' From af300410d3d07cbe56cbdc4f106462f7ea599a73 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 5 Jul 2017 11:01:38 -0700 Subject: [PATCH 09/25] Remove duplicated helper --- src/services/navigateTo.ts | 19 ++----------------- src/services/services.ts | 6 +++--- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index b79fd36fbd372..470b422c8c7d9 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -83,26 +83,11 @@ namespace ts.NavigateTo { return true; } - function getTextOfIdentifierOrLiteral(node: Node) { - if (node) { - if (node.kind === SyntaxKind.Identifier) { - return unescapeIdentifier((node).text); - } - if (node.kind === SyntaxKind.StringLiteral || - node.kind === SyntaxKind.NumericLiteral) { - - return (node).text; - } - } - - return undefined; - } - function tryAddSingleDeclarationName(declaration: Declaration, containers: string[]) { if (declaration) { const name = getNameOfDeclaration(declaration); if (name) { - const text = getTextOfIdentifierOrLiteral(name); + const text = getTextOfIdentifierOrLiteral(name as (Identifier | LiteralExpression)); if (text !== undefined) { containers.unshift(text); } @@ -123,7 +108,7 @@ namespace ts.NavigateTo { // // [X.Y.Z]() { } function tryAddComputedPropertyName(expression: Expression, containers: string[], includeLastPortion: boolean): boolean { - const text = getTextOfIdentifierOrLiteral(expression); + const text = getTextOfIdentifierOrLiteral(expression as LiteralExpression); if (text !== undefined) { if (includeLastPortion) { containers.unshift(text); diff --git a/src/services/services.ts b/src/services/services.ts index 4c6965fb2f9e6..c34c45f5974e4 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -589,7 +589,7 @@ namespace ts { function getDeclarationName(declaration: Declaration) { const name = getNameOfDeclaration(declaration); if (name) { - const result = getTextOfIdentifierOrLiteral(name); + const result = getTextOfIdentifierOrLiteral(name as (Identifier | LiteralExpression)); if (result !== undefined) { return result; } @@ -600,7 +600,7 @@ namespace ts { return unescapeIdentifier((expr).name.text); } - return getTextOfIdentifierOrLiteral(expr); + return getTextOfIdentifierOrLiteral(expr as (Identifier | LiteralExpression)); } } @@ -2098,7 +2098,7 @@ namespace ts { node.parent.kind === SyntaxKind.ExternalModuleReference || isArgumentOfElementAccessExpression(node) || isLiteralComputedPropertyDeclarationName(node)) { - setNameTable((node).text, node); + setNameTable(getEscapedTextOfIdentifierOrLiteral((node)), node); } break; default: From 5d9ea3aefd0aecc108f35de868a7562beeccafb1 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 5 Jul 2017 11:21:01 -0700 Subject: [PATCH 10/25] Remove unneeded check, use helper --- src/compiler/binder.ts | 2 +- src/services/findAllReferences.ts | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 14d6e6f1515a5..031a3b6d93fda 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -237,7 +237,7 @@ namespace ts { const nameExpression = (name).expression; // treat computed property names where expression is string/numeric literal as just string/numeric literal if (isStringOrNumericLiteral(nameExpression)) { - return nameExpression.text && escapeIdentifier(nameExpression.text); + return escapeIdentifier(nameExpression.text); } Debug.assert(isWellKnownSymbolSyntactically(nameExpression)); diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index ecfb4c77320ab..1a55add0d1140 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -1568,10 +1568,7 @@ namespace ts.FindAllReferences.Core { } return undefined; } - if (node.name.kind === SyntaxKind.Identifier) { - return unescapeIdentifier(node.name.text); - } - return node.name.text; + return getTextOfIdentifierOrLiteral(node.name); } /** Gets all symbols for one property. Does not get symbols for every property. */ From 352c13d87f2a5030c805f211543628a345655803 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 5 Jul 2017 11:30:13 -0700 Subject: [PATCH 11/25] Identifiers list is no longer escaped strings --- src/compiler/declarationEmitter.ts | 6 +++--- src/compiler/emitter.ts | 2 +- src/compiler/parser.ts | 9 ++++----- src/compiler/types.ts | 2 +- src/services/services.ts | 2 +- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index ee8e461360920..753080cc6a081 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -61,7 +61,7 @@ namespace ts { let resultHasExternalModuleIndicator: boolean; let currentText: string; let currentLineMap: number[]; - let currentIdentifiers: EscapedIdentifierMap; + let currentIdentifiers: Map; let isCurrentFileExternalModule: boolean; let reportedDeclarationError = false; let errorNameNode: DeclarationName; @@ -608,14 +608,14 @@ namespace ts { // Note that export default is only allowed at most once in a module, so we // do not need to keep track of created temp names. function getExportTempVariableName(baseName: string): string { - if (!currentIdentifiers.has(escapeIdentifier(baseName))) { + if (!currentIdentifiers.has(baseName)) { return baseName; } let count = 0; while (true) { count++; const name = baseName + "_" + count; - if (!currentIdentifiers.has(escapeIdentifier(name))) { + if (!currentIdentifiers.has(name)) { return name; } } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 3d0e4b3e3fa86..2fe27c3980fcd 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2833,7 +2833,7 @@ namespace ts { */ function isUniqueName(name: string): boolean { return !(hasGlobalName && hasGlobalName(name)) - && !currentSourceFile.identifiers.has(escapeIdentifier(name)) + && !currentSourceFile.identifiers.has(name) && !generatedNames.has(name); } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 95a5ba86c9f8d..bbcc4d96b420d 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -536,7 +536,7 @@ namespace ts { let currentToken: SyntaxKind; let sourceText: string; let nodeCount: number; - let identifiers: EscapedIdentifierMap; + let identifiers: Map; let identifierCount: number; let parsingContext: ParsingContext; @@ -681,7 +681,7 @@ namespace ts { parseDiagnostics = []; parsingContext = 0; - identifiers = createEscapedIdentifierMap(); + identifiers = createMap(); identifierCount = 0; nodeCount = 0; @@ -1182,8 +1182,7 @@ namespace ts { return finishNode(result); } - function internIdentifier(input: string): EscapedIdentifier { - const text = escapeIdentifier(input); + function internIdentifier(text: string): string { let identifier = identifiers.get(text); if (identifier === undefined) { identifiers.set(text, identifier = text); @@ -1203,7 +1202,7 @@ namespace ts { if (token() !== SyntaxKind.Identifier) { node.originalKeywordKind = token(); } - node.text = internIdentifier(scanner.getTokenValue()); + node.text = escapeIdentifier(internIdentifier(scanner.getTokenValue())); nextToken(); return finishNode(node); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 9c1501508bd60..15d3ef1848c2a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2336,7 +2336,7 @@ namespace ts { // The first node that causes this file to be a CommonJS module /* @internal */ commonJsModuleIndicator: Node; - /* @internal */ identifiers: EscapedIdentifierMap; + /* @internal */ identifiers: Map; /* @internal */ nodeCount: number; /* @internal */ identifierCount: number; /* @internal */ symbolCount: number; diff --git a/src/services/services.ts b/src/services/services.ts index c34c45f5974e4..9bf68f629d379 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -508,7 +508,7 @@ namespace ts { public scriptKind: ScriptKind; public languageVersion: ScriptTarget; public languageVariant: LanguageVariant; - public identifiers: EscapedIdentifierMap; + public identifiers: Map; public nameTable: EscapedIdentifierMap; public resolvedModules: Map; public resolvedTypeReferenceDirectiveNames: Map; From b371e7ad147ec0a311838532dea607d4d47bf62d Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 5 Jul 2017 12:45:56 -0700 Subject: [PATCH 12/25] Extract repeated string-getting code into helper --- src/compiler/checker.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index da37ca37c941a..27692690e7532 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1105,11 +1105,11 @@ namespace ts { if (suggestedNameNotFoundMessage && suggestionCount < maximumSuggestionCount) { suggestion = getSuggestionForNonexistentSymbol(originalLocation, name, meaning); if (suggestion) { - error(errorLocation, suggestedNameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg as Identifier), unescapeIdentifier(suggestion)); + error(errorLocation, suggestedNameNotFoundMessage, diagnosticName(nameArg), unescapeIdentifier(suggestion)); } } if (!suggestion) { - error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg as Identifier)); + error(errorLocation, nameNotFoundMessage, diagnosticName(nameArg)); } suggestionCount++; } @@ -1124,7 +1124,7 @@ namespace ts { // to a local variable in the constructor where the code will be emitted. const propertyName = (propertyWithInvalidInitializer).name; error(errorLocation, Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, - declarationNameToString(propertyName), typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg as Identifier)); + declarationNameToString(propertyName), diagnosticName(nameArg)); return undefined; } @@ -1159,6 +1159,10 @@ namespace ts { return result; } + function diagnosticName(nameArg: EscapedIdentifier | Identifier) { + return typeof nameArg === "string" ? unescapeIdentifier(nameArg as EscapedIdentifier) : declarationNameToString(nameArg as Identifier); + } + function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) { for (const decl of symbol.declarations) { if (decl.kind === SyntaxKind.TypeParameter && decl.parent === container) { @@ -1186,7 +1190,7 @@ namespace ts { // Check to see if a static member exists. const constructorType = getTypeOfSymbol(classSymbol); if (getPropertyOfType(constructorType, name)) { - error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg as Identifier), symbolToString(classSymbol)); + error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, diagnosticName(nameArg), symbolToString(classSymbol)); return true; } @@ -1195,7 +1199,7 @@ namespace ts { if (location === container && !(getModifierFlags(location) & ModifierFlags.Static)) { const instanceType = (getDeclaredTypeOfSymbol(classSymbol)).thisType; if (getPropertyOfType(instanceType, name)) { - error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg as Identifier)); + error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, diagnosticName(nameArg)); return true; } } From ba0071e4450c0856d224af1cf9446a3d59543f45 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 5 Jul 2017 13:11:27 -0700 Subject: [PATCH 13/25] Rename type and associated functions --- src/compiler/binder.ts | 84 ++--- src/compiler/checker.ts | 384 ++++++++++----------- src/compiler/commandLineParser.ts | 2 +- src/compiler/core.ts | 24 +- src/compiler/emitter.ts | 6 +- src/compiler/factory.ts | 8 +- src/compiler/parser.ts | 6 +- src/compiler/program.ts | 4 +- src/compiler/transformers/destructuring.ts | 2 +- src/compiler/transformers/es2015.ts | 12 +- src/compiler/transformers/es2017.ts | 2 +- src/compiler/transformers/es5.ts | 2 +- src/compiler/transformers/esnext.ts | 2 +- src/compiler/transformers/generators.ts | 16 +- src/compiler/transformers/jsx.ts | 6 +- src/compiler/transformers/module/module.ts | 2 +- src/compiler/transformers/module/system.ts | 10 +- src/compiler/transformers/ts.ts | 8 +- src/compiler/transformers/utilities.ts | 18 +- src/compiler/types.ts | 28 +- src/compiler/utilities.ts | 32 +- src/services/classifier.ts | 4 +- src/services/completions.ts | 12 +- src/services/documentHighlights.ts | 2 +- src/services/findAllReferences.ts | 18 +- src/services/goToDefinition.ts | 2 +- src/services/importTracker.ts | 4 +- src/services/jsDoc.ts | 6 +- src/services/navigateTo.ts | 4 +- src/services/navigationBar.ts | 6 +- src/services/pathCompletions.ts | 2 +- src/services/services.ts | 20 +- src/services/signatureHelp.ts | 2 +- src/services/types.ts | 2 +- 34 files changed, 371 insertions(+), 371 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 031a3b6d93fda..6c054fe99c3df 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -10,7 +10,7 @@ namespace ts { } interface ActiveLabel { - name: EscapedIdentifier; + name: UnderscoreEscapedString; breakTarget: FlowLabel; continueTarget: FlowLabel; referenced: boolean; @@ -132,8 +132,8 @@ namespace ts { let inStrictMode: boolean; let symbolCount = 0; - let Symbol: { new (flags: SymbolFlags, name: EscapedIdentifier): Symbol }; - let classifiableNames: EscapedIdentifierMap; + let Symbol: { new (flags: SymbolFlags, name: UnderscoreEscapedString): Symbol }; + let classifiableNames: UnderscoreEscapedMap; const unreachableFlow: FlowNode = { flags: FlowFlags.Unreachable }; const reportedUnreachableFlow: FlowNode = { flags: FlowFlags.Unreachable }; @@ -147,7 +147,7 @@ namespace ts { options = opts; languageVersion = getEmitScriptTarget(options); inStrictMode = bindInStrictMode(file, opts); - classifiableNames = createEscapedIdentifierMap(); + classifiableNames = createUnderscoreEscapedMap(); symbolCount = 0; skipTransformFlagAggregation = file.isDeclarationFile; @@ -191,7 +191,7 @@ namespace ts { } } - function createSymbol(flags: SymbolFlags, name: EscapedIdentifier): Symbol { + function createSymbol(flags: SymbolFlags, name: UnderscoreEscapedString): Symbol { symbolCount++; return new Symbol(flags, name); } @@ -226,63 +226,63 @@ namespace ts { // Should not be called on a declaration with a computed property name, // unless it is a well known Symbol. - function getDeclarationName(node: Declaration): EscapedIdentifier { + function getDeclarationName(node: Declaration): UnderscoreEscapedString { const name = getNameOfDeclaration(node); if (name) { if (isAmbientModule(node)) { const moduleName = getTextOfIdentifierOrLiteral(name); - return (isGlobalScopeAugmentation(node) ? "__global" : `"${moduleName}"`) as EscapedIdentifier; + return (isGlobalScopeAugmentation(node) ? "__global" : `"${moduleName}"`) as UnderscoreEscapedString; } if (name.kind === SyntaxKind.ComputedPropertyName) { const nameExpression = (name).expression; // treat computed property names where expression is string/numeric literal as just string/numeric literal if (isStringOrNumericLiteral(nameExpression)) { - return escapeIdentifier(nameExpression.text); + return escapeLeadingUnderscores(nameExpression.text); } Debug.assert(isWellKnownSymbolSyntactically(nameExpression)); - return getPropertyNameForKnownSymbolName(unescapeIdentifier((nameExpression).name.text)); + return getPropertyNameForKnownSymbolName(unescapeLeadingUnderscores((nameExpression).name.text)); } return getEscapedTextOfIdentifierOrLiteral(name); } switch (node.kind) { case SyntaxKind.Constructor: - return "__constructor" as EscapedIdentifier; + return "__constructor" as UnderscoreEscapedString; case SyntaxKind.FunctionType: case SyntaxKind.CallSignature: - return "__call" as EscapedIdentifier; + return "__call" as UnderscoreEscapedString; case SyntaxKind.ConstructorType: case SyntaxKind.ConstructSignature: - return "__new" as EscapedIdentifier; + return "__new" as UnderscoreEscapedString; case SyntaxKind.IndexSignature: - return "__index" as EscapedIdentifier; + return "__index" as UnderscoreEscapedString; case SyntaxKind.ExportDeclaration: - return "__export" as EscapedIdentifier; + return "__export" as UnderscoreEscapedString; case SyntaxKind.ExportAssignment: - return ((node).isExportEquals ? "export=" : "default") as EscapedIdentifier; + return ((node).isExportEquals ? "export=" : "default") as UnderscoreEscapedString; case SyntaxKind.BinaryExpression: if (getSpecialPropertyAssignmentKind(node as BinaryExpression) === SpecialPropertyAssignmentKind.ModuleExports) { // module.exports = ... - return "export=" as EscapedIdentifier; + return "export=" as UnderscoreEscapedString; } Debug.fail("Unknown binary declaration kind"); break; case SyntaxKind.FunctionDeclaration: case SyntaxKind.ClassDeclaration: - return (hasModifier(node, ModifierFlags.Default) ? "default" : undefined) as EscapedIdentifier; + return (hasModifier(node, ModifierFlags.Default) ? "default" : undefined) as UnderscoreEscapedString; case SyntaxKind.JSDocFunctionType: - return (isJSDocConstructSignature(node) ? "__new" : "__call") as EscapedIdentifier; + return (isJSDocConstructSignature(node) ? "__new" : "__call") as UnderscoreEscapedString; case SyntaxKind.Parameter: // Parameters with names are handled at the top of this function. Parameters // without names can only come from JSDocFunctionTypes. Debug.assert(node.parent.kind === SyntaxKind.JSDocFunctionType); const functionType = node.parent; const index = indexOf(functionType.parameters, node); - return "arg" + index as EscapedIdentifier; + return "arg" + index as UnderscoreEscapedString; case SyntaxKind.JSDocTypedefTag: const parentNode = node.parent && node.parent.parent; - let nameFromParentNode: EscapedIdentifier; + let nameFromParentNode: UnderscoreEscapedString; if (parentNode && parentNode.kind === SyntaxKind.VariableStatement) { if ((parentNode).declarationList.declarations.length > 0) { const nameIdentifier = (parentNode).declarationList.declarations[0].name; @@ -296,7 +296,7 @@ namespace ts { } function getDisplayName(node: Declaration): string { - return (node as NamedDeclaration).name ? declarationNameToString((node as NamedDeclaration).name) : unescapeIdentifier(getDeclarationName(node)); + return (node as NamedDeclaration).name ? declarationNameToString((node as NamedDeclaration).name) : unescapeLeadingUnderscores(getDeclarationName(node)); } /** @@ -313,11 +313,11 @@ namespace ts { const isDefaultExport = hasModifier(node, ModifierFlags.Default); // The exported symbol for an export default function/class node is always named "default" - const name = isDefaultExport && parent ? ("default" as EscapedIdentifier) : getDeclarationName(node); + const name = isDefaultExport && parent ? ("default" as UnderscoreEscapedString) : getDeclarationName(node); let symbol: Symbol; if (name === undefined) { - symbol = createSymbol(SymbolFlags.None, "__missing" as EscapedIdentifier); + symbol = createSymbol(SymbolFlags.None, "__missing" as UnderscoreEscapedString); } else { // Check and see if the symbol table already has a symbol with this name. If not, @@ -1007,7 +1007,7 @@ namespace ts { currentFlow = unreachableFlow; } - function findActiveLabel(name: EscapedIdentifier) { + function findActiveLabel(name: UnderscoreEscapedString) { if (activeLabels) { for (const label of activeLabels) { if (label.name === name) { @@ -1170,7 +1170,7 @@ namespace ts { bindEach(node.statements); } - function pushActiveLabel(name: EscapedIdentifier, breakTarget: FlowLabel, continueTarget: FlowLabel): ActiveLabel { + function pushActiveLabel(name: UnderscoreEscapedString, breakTarget: FlowLabel, continueTarget: FlowLabel): ActiveLabel { const activeLabel = { name, breakTarget, @@ -1646,7 +1646,7 @@ namespace ts { const symbol = createSymbol(SymbolFlags.Signature, getDeclarationName(node)); addDeclarationToSymbol(symbol, node, SymbolFlags.Signature); - const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type" as EscapedIdentifier); + const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type" as UnderscoreEscapedString); addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral); typeLiteralSymbol.members = createSymbolTable(); typeLiteralSymbol.members.set(symbol.name, symbol); @@ -1659,7 +1659,7 @@ namespace ts { } if (inStrictMode) { - const seen = createEscapedIdentifierMap(); + const seen = createUnderscoreEscapedMap(); for (const prop of node.properties) { if (prop.kind === SyntaxKind.SpreadAssignment || prop.name.kind !== SyntaxKind.Identifier) { @@ -1694,18 +1694,18 @@ namespace ts { } } - return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__object" as EscapedIdentifier); + return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__object" as UnderscoreEscapedString); } function bindJsxAttributes(node: JsxAttributes) { - return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__jsxAttributes" as EscapedIdentifier); + return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__jsxAttributes" as UnderscoreEscapedString); } function bindJsxAttribute(node: JsxAttribute, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { return declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } - function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: EscapedIdentifier) { + function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: UnderscoreEscapedString) { const symbol = createSymbol(symbolFlags, name); addDeclarationToSymbol(symbol, node, symbolFlags); } @@ -1804,7 +1804,7 @@ namespace ts { // otherwise report generic error message. const span = getErrorSpanForNode(file, name); file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, - getStrictModeEvalOrArgumentsMessage(contextNode), unescapeIdentifier(identifier.text))); + getStrictModeEvalOrArgumentsMessage(contextNode), unescapeLeadingUnderscores(identifier.text))); } } } @@ -1896,8 +1896,8 @@ namespace ts { file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); } - function getDestructuringParameterName(node: Declaration): EscapedIdentifier { - return "__" + indexOf((node.parent).parameters, node) as EscapedIdentifier; + function getDestructuringParameterName(node: Declaration): UnderscoreEscapedString { + return "__" + indexOf((node.parent).parameters, node) as UnderscoreEscapedString; } function bind(node: Node): void { @@ -2191,7 +2191,7 @@ namespace ts { } function bindAnonymousTypeWorker(node: TypeLiteralNode | MappedTypeNode | JSDocTypeLiteral | JSDocRecordType) { - return bindAnonymousDeclaration(node, SymbolFlags.TypeLiteral, "__type" as EscapedIdentifier); + return bindAnonymousDeclaration(node, SymbolFlags.TypeLiteral, "__type" as UnderscoreEscapedString); } function checkTypePredicate(node: TypePredicateNode) { @@ -2213,7 +2213,7 @@ namespace ts { } function bindSourceFileAsExternalModule() { - bindAnonymousDeclaration(file, SymbolFlags.ValueModule, `"${removeFileExtension(file.fileName)}"` as EscapedIdentifier); + bindAnonymousDeclaration(file, SymbolFlags.ValueModule, `"${removeFileExtension(file.fileName)}"` as UnderscoreEscapedString); } function bindExportAssignment(node: ExportAssignment | BinaryExpression) { @@ -2404,11 +2404,11 @@ namespace ts { } } - function lookupSymbolForName(name: EscapedIdentifier) { + function lookupSymbolForName(name: UnderscoreEscapedString) { return (container.symbol && container.symbol.exports && container.symbol.exports.get(name)) || (container.locals && container.locals.get(name)); } - function bindPropertyAssignment(functionName: EscapedIdentifier, propertyAccessExpression: PropertyAccessExpression, isPrototypeProperty: boolean) { + function bindPropertyAssignment(functionName: UnderscoreEscapedString, propertyAccessExpression: PropertyAccessExpression, isPrototypeProperty: boolean) { let targetSymbol = lookupSymbolForName(functionName); if (targetSymbol && isDeclarationOfFunctionOrClassExpression(targetSymbol)) { @@ -2441,7 +2441,7 @@ namespace ts { bindBlockScopedDeclaration(node, SymbolFlags.Class, SymbolFlags.ClassExcludes); } else { - const bindingName = node.name ? node.name.text : "__class" as EscapedIdentifier; + const bindingName = node.name ? node.name.text : "__class" as UnderscoreEscapedString; bindAnonymousDeclaration(node, SymbolFlags.Class, bindingName); // Add name of class expression into the map for semantic classifier if (node.name) { @@ -2460,13 +2460,13 @@ namespace ts { // Note: we check for this here because this class may be merging into a module. The // module might have an exported variable called 'prototype'. We can't allow that as // that would clash with the built-in 'prototype' for the class. - const prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype" as EscapedIdentifier); + const prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype" as UnderscoreEscapedString); const symbolExport = symbol.exports.get(prototypeSymbol.name); if (symbolExport) { if (node.name) { node.name.parent = node; } - file.bindDiagnostics.push(createDiagnosticForNode(symbolExport.declarations[0], Diagnostics.Duplicate_identifier_0, unescapeIdentifier(prototypeSymbol.name))); + file.bindDiagnostics.push(createDiagnosticForNode(symbolExport.declarations[0], Diagnostics.Duplicate_identifier_0, unescapeLeadingUnderscores(prototypeSymbol.name))); } symbol.exports.set(prototypeSymbol.name, prototypeSymbol); prototypeSymbol.parent = symbol; @@ -2554,7 +2554,7 @@ namespace ts { node.flowNode = currentFlow; } checkStrictModeFunctionName(node); - const bindingName = node.name ? node.name.text : "__function" as EscapedIdentifier; + const bindingName = node.name ? node.name.text : "__function" as UnderscoreEscapedString; return bindAnonymousDeclaration(node, SymbolFlags.Function, bindingName); } @@ -2568,7 +2568,7 @@ namespace ts { } return hasDynamicName(node) - ? bindAnonymousDeclaration(node, symbolFlags, "__computed" as EscapedIdentifier) + ? bindAnonymousDeclaration(node, symbolFlags, "__computed" as UnderscoreEscapedString) : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 27692690e7532..c352e2c6da92c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -71,9 +71,9 @@ namespace ts { const emitResolver = createResolver(); const nodeBuilder = createNodeBuilder(); - const undefinedSymbol = createSymbol(SymbolFlags.Property, "undefined" as EscapedIdentifier); + const undefinedSymbol = createSymbol(SymbolFlags.Property, "undefined" as UnderscoreEscapedString); undefinedSymbol.declarations = []; - const argumentsSymbol = createSymbol(SymbolFlags.Property, "arguments" as EscapedIdentifier); + const argumentsSymbol = createSymbol(SymbolFlags.Property, "arguments" as UnderscoreEscapedString); /** This will be set during calls to `getResolvedSignature` where services determines an apparent number of arguments greater than what is actually provided. */ let apparentArgumentCount: number | undefined; @@ -101,11 +101,11 @@ namespace ts { getSymbolsOfParameterPropertyDeclaration: (parameter, parameterName) => { parameter = getParseTreeNode(parameter, isParameter); Debug.assert(parameter !== undefined, "Cannot get symbols of a synthetic parameter that cannot be resolved to a parse-tree node."); - return getSymbolsOfParameterPropertyDeclaration(parameter, escapeIdentifier(parameterName)); + return getSymbolsOfParameterPropertyDeclaration(parameter, escapeLeadingUnderscores(parameterName)); }, getDeclaredTypeOfSymbol, getPropertiesOfType, - getPropertyOfType: (type, name) => getPropertyOfType(type, escapeIdentifier(name)), + getPropertyOfType: (type, name) => getPropertyOfType(type, escapeLeadingUnderscores(name)), getIndexInfoOfType, getSignaturesOfType, getIndexTypeOfType, @@ -176,7 +176,7 @@ namespace ts { }, isValidPropertyAccess: (node, propertyName) => { node = getParseTreeNode(node, isPropertyAccessOrQualifiedName); - return node ? isValidPropertyAccess(node, escapeIdentifier(propertyName)) : false; + return node ? isValidPropertyAccess(node, escapeLeadingUnderscores(propertyName)) : false; }, getSignatureFromDeclaration: declaration => { declaration = getParseTreeNode(declaration, isFunctionLike); @@ -211,7 +211,7 @@ namespace ts { node = getParseTreeNode(node, isParameter); return node ? isOptionalParameter(node) : false; }, - tryGetMemberInModuleExports: (name, symbol) => tryGetMemberInModuleExports(escapeIdentifier(name), symbol), + tryGetMemberInModuleExports: (name, symbol) => tryGetMemberInModuleExports(escapeLeadingUnderscores(name), symbol), tryFindAmbientModuleWithoutAugmentations: moduleName => { // we deliberately exclude augmentations // since we are only interested in declarations of the module itself @@ -219,13 +219,13 @@ namespace ts { }, getApparentType, getAllPossiblePropertiesOfType, - getSuggestionForNonexistentProperty: (node, type) => unescapeIdentifier(getSuggestionForNonexistentProperty(node, type)), - getSuggestionForNonexistentSymbol: (location, name, meaning) => unescapeIdentifier(getSuggestionForNonexistentSymbol(location, escapeIdentifier(name), meaning)), + getSuggestionForNonexistentProperty: (node, type) => unescapeLeadingUnderscores(getSuggestionForNonexistentProperty(node, type)), + getSuggestionForNonexistentSymbol: (location, name, meaning) => unescapeLeadingUnderscores(getSuggestionForNonexistentSymbol(location, escapeLeadingUnderscores(name), meaning)), getBaseConstraintOfType, - getJsxNamespace: () => unescapeIdentifier(getJsxNamespace()), + getJsxNamespace: () => unescapeLeadingUnderscores(getJsxNamespace()), resolveNameAtLocation(location: Node, name: string, meaning: SymbolFlags): Symbol | undefined { location = getParseTreeNode(location); - return resolveName(location, escapeIdentifier(name), meaning, /*nameNotFoundMessage*/ undefined, escapeIdentifier(name)); + return resolveName(location, escapeLeadingUnderscores(name), meaning, /*nameNotFoundMessage*/ undefined, escapeLeadingUnderscores(name)); }, }; @@ -236,8 +236,8 @@ namespace ts { const indexedAccessTypes = createMap(); const evolvingArrayTypes: EvolvingArrayType[] = []; - const unknownSymbol = createSymbol(SymbolFlags.Property, "unknown" as EscapedIdentifier); - const resolvingSymbol = createSymbol(0, "__resolving__" as EscapedIdentifier); + const unknownSymbol = createSymbol(SymbolFlags.Property, "unknown" as UnderscoreEscapedString); + const resolvingSymbol = createSymbol(0, "__resolving__" as UnderscoreEscapedString); const anyType = createIntrinsicType(TypeFlags.Any, "any"); const autoType = createIntrinsicType(TypeFlags.Any, "any"); @@ -259,7 +259,7 @@ namespace ts { const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - const emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type" as EscapedIdentifier); + const emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type" as UnderscoreEscapedString); emptyTypeLiteralSymbol.members = createSymbolTable(); const emptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, emptyArray, emptyArray, undefined, undefined); @@ -444,25 +444,25 @@ namespace ts { }); const typeofType = createTypeofType(); - let _jsxNamespace: EscapedIdentifier; + let _jsxNamespace: UnderscoreEscapedString; let _jsxFactoryEntity: EntityName; - let _jsxElementPropertiesName: EscapedIdentifier; + let _jsxElementPropertiesName: UnderscoreEscapedString; let _hasComputedJsxElementPropertiesName = false; - let _jsxElementChildrenPropertyName: EscapedIdentifier; + let _jsxElementChildrenPropertyName: UnderscoreEscapedString; let _hasComputedJsxElementChildrenPropertyName = false; /** Things we lazy load from the JSX namespace */ - const jsxTypes = createEscapedIdentifierMap(); + const jsxTypes = createUnderscoreEscapedMap(); const JsxNames = { - JSX: "JSX" as EscapedIdentifier, - IntrinsicElements: "IntrinsicElements" as EscapedIdentifier, - ElementClass: "ElementClass" as EscapedIdentifier, - ElementAttributesPropertyNameContainer: "ElementAttributesProperty" as EscapedIdentifier, - ElementChildrenAttributeNameContainer: "ElementChildrenAttribute" as EscapedIdentifier, - Element: "Element" as EscapedIdentifier, - IntrinsicAttributes: "IntrinsicAttributes" as EscapedIdentifier, - IntrinsicClassAttributes: "IntrinsicClassAttributes" as EscapedIdentifier + JSX: "JSX" as UnderscoreEscapedString, + IntrinsicElements: "IntrinsicElements" as UnderscoreEscapedString, + ElementClass: "ElementClass" as UnderscoreEscapedString, + ElementAttributesPropertyNameContainer: "ElementAttributesProperty" as UnderscoreEscapedString, + ElementChildrenAttributeNameContainer: "ElementChildrenAttribute" as UnderscoreEscapedString, + Element: "Element" as UnderscoreEscapedString, + IntrinsicAttributes: "IntrinsicAttributes" as UnderscoreEscapedString, + IntrinsicClassAttributes: "IntrinsicClassAttributes" as UnderscoreEscapedString }; const subtypeRelation = createMap(); @@ -496,9 +496,9 @@ namespace ts { return checker; - function getJsxNamespace(): EscapedIdentifier { + function getJsxNamespace(): UnderscoreEscapedString { if (!_jsxNamespace) { - _jsxNamespace = "React" as EscapedIdentifier; + _jsxNamespace = "React" as UnderscoreEscapedString; if (compilerOptions.jsxFactory) { _jsxFactoryEntity = parseIsolatedEntityName(compilerOptions.jsxFactory, languageVersion); if (_jsxFactoryEntity) { @@ -506,7 +506,7 @@ namespace ts { } } else if (compilerOptions.reactNamespace) { - _jsxNamespace = escapeIdentifier(compilerOptions.reactNamespace); + _jsxNamespace = escapeLeadingUnderscores(compilerOptions.reactNamespace); } } return _jsxNamespace; @@ -526,7 +526,7 @@ namespace ts { diagnostics.add(diagnostic); } - function createSymbol(flags: SymbolFlags, name: EscapedIdentifier) { + function createSymbol(flags: SymbolFlags, name: UnderscoreEscapedString) { symbolCount++; const symbol = (new Symbol(flags | SymbolFlags.Transient, name)); symbol.checkFlags = 0; @@ -675,7 +675,7 @@ namespace ts { const targetSymbol = target.get(id); if (targetSymbol) { // Error on redeclarations - forEach(targetSymbol.declarations, addDeclarationDiagnostic(unescapeIdentifier(id), message)); + forEach(targetSymbol.declarations, addDeclarationDiagnostic(unescapeLeadingUnderscores(id), message)); } else { target.set(id, sourceSymbol); @@ -706,7 +706,7 @@ namespace ts { return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(node); } - function getSymbol(symbols: SymbolTable, name: EscapedIdentifier, meaning: SymbolFlags): Symbol { + function getSymbol(symbols: SymbolTable, name: UnderscoreEscapedString, meaning: SymbolFlags): Symbol { if (meaning) { const symbol = symbols.get(name); if (symbol) { @@ -732,7 +732,7 @@ namespace ts { * @param parameterName a name of the parameter to get the symbols for. * @return a tuple of two symbols */ - function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: EscapedIdentifier): [Symbol, Symbol] { + function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: UnderscoreEscapedString): [Symbol, Symbol] { const constructorDeclaration = parameter.parent; const classDeclaration = parameter.parent.parent; @@ -855,20 +855,20 @@ namespace ts { // the given name can be found. function resolveName( location: Node | undefined, - name: EscapedIdentifier, + name: UnderscoreEscapedString, meaning: SymbolFlags, nameNotFoundMessage: DiagnosticMessage | undefined, - nameArg: EscapedIdentifier | Identifier, + nameArg: UnderscoreEscapedString | Identifier, suggestedNameNotFoundMessage?: DiagnosticMessage): Symbol { return resolveNameHelper(location, name, meaning, nameNotFoundMessage, nameArg, getSymbol, suggestedNameNotFoundMessage); } function resolveNameHelper( location: Node | undefined, - name: EscapedIdentifier, + name: UnderscoreEscapedString, meaning: SymbolFlags, nameNotFoundMessage: DiagnosticMessage, - nameArg: EscapedIdentifier | Identifier, + nameArg: UnderscoreEscapedString | Identifier, lookup: typeof getSymbol, suggestedNameNotFoundMessage?: DiagnosticMessage): Symbol { const originalLocation = location; // needed for did-you-mean error reporting, which gathers candidates starting from the original location @@ -933,7 +933,7 @@ namespace ts { // It's an external module. First see if the module has an export default and if the local // name of that export default matches. - if (result = moduleExports.get("default" as EscapedIdentifier)) { + if (result = moduleExports.get("default" as UnderscoreEscapedString)) { const localSymbol = getLocalSymbolForExportDefault(result); if (localSymbol && (result.flags & meaning) && localSymbol.name === name) { break loop; @@ -1101,11 +1101,11 @@ namespace ts { !checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) && !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) && !checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation, name, meaning)) { - let suggestion: EscapedIdentifier | undefined; + let suggestion: UnderscoreEscapedString | undefined; if (suggestedNameNotFoundMessage && suggestionCount < maximumSuggestionCount) { suggestion = getSuggestionForNonexistentSymbol(originalLocation, name, meaning); if (suggestion) { - error(errorLocation, suggestedNameNotFoundMessage, diagnosticName(nameArg), unescapeIdentifier(suggestion)); + error(errorLocation, suggestedNameNotFoundMessage, diagnosticName(nameArg), unescapeLeadingUnderscores(suggestion)); } } if (!suggestion) { @@ -1152,15 +1152,15 @@ namespace ts { if (result && isInExternalModule && (meaning & SymbolFlags.Value) === SymbolFlags.Value) { const decls = result.declarations; if (decls && decls.length === 1 && decls[0].kind === SyntaxKind.NamespaceExportDeclaration) { - error(errorLocation, Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, unescapeIdentifier(name)); + error(errorLocation, Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, unescapeLeadingUnderscores(name)); } } } return result; } - function diagnosticName(nameArg: EscapedIdentifier | Identifier) { - return typeof nameArg === "string" ? unescapeIdentifier(nameArg as EscapedIdentifier) : declarationNameToString(nameArg as Identifier); + function diagnosticName(nameArg: UnderscoreEscapedString | Identifier) { + return typeof nameArg === "string" ? unescapeLeadingUnderscores(nameArg as UnderscoreEscapedString) : declarationNameToString(nameArg as Identifier); } function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) { @@ -1173,7 +1173,7 @@ namespace ts { return false; } - function checkAndReportErrorForMissingPrefix(errorLocation: Node, name: EscapedIdentifier, nameArg: EscapedIdentifier | Identifier): boolean { + function checkAndReportErrorForMissingPrefix(errorLocation: Node, name: UnderscoreEscapedString, nameArg: UnderscoreEscapedString | Identifier): boolean { if ((errorLocation.kind === SyntaxKind.Identifier && (isTypeReferenceIdentifier(errorLocation)) || isInTypeQuery(errorLocation))) { return false; } @@ -1236,11 +1236,11 @@ namespace ts { } } - function checkAndReportErrorForUsingTypeAsNamespace(errorLocation: Node, name: EscapedIdentifier, meaning: SymbolFlags): boolean { + function checkAndReportErrorForUsingTypeAsNamespace(errorLocation: Node, name: UnderscoreEscapedString, meaning: SymbolFlags): boolean { if (meaning === SymbolFlags.Namespace) { const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined)); if (symbol) { - error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_namespace_here, unescapeIdentifier(name)); + error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_namespace_here, unescapeLeadingUnderscores(name)); return true; } } @@ -1248,33 +1248,33 @@ namespace ts { return false; } - function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: EscapedIdentifier, meaning: SymbolFlags): boolean { + function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: UnderscoreEscapedString, meaning: SymbolFlags): boolean { if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule)) { if (name === "any" || name === "string" || name === "number" || name === "boolean" || name === "never") { - error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeIdentifier(name)); + error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeLeadingUnderscores(name)); return true; } const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined)); if (symbol && !(symbol.flags & SymbolFlags.NamespaceModule)) { - error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeIdentifier(name)); + error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeLeadingUnderscores(name)); return true; } } return false; } - function checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation: Node, name: EscapedIdentifier, meaning: SymbolFlags): boolean { + function checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation: Node, name: UnderscoreEscapedString, meaning: SymbolFlags): boolean { if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule & ~SymbolFlags.Type)) { const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.NamespaceModule & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined)); if (symbol) { - error(errorLocation, Diagnostics.Cannot_use_namespace_0_as_a_value, unescapeIdentifier(name)); + error(errorLocation, Diagnostics.Cannot_use_namespace_0_as_a_value, unescapeLeadingUnderscores(name)); return true; } } else if (meaning & (SymbolFlags.Type & ~SymbolFlags.NamespaceModule & ~SymbolFlags.Value)) { const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.NamespaceModule & ~SymbolFlags.Type, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined)); if (symbol) { - error(errorLocation, Diagnostics.Cannot_use_namespace_0_as_a_type, unescapeIdentifier(name)); + error(errorLocation, Diagnostics.Cannot_use_namespace_0_as_a_type, unescapeLeadingUnderscores(name)); return true; } } @@ -1339,10 +1339,10 @@ namespace ts { exportDefaultSymbol = moduleSymbol; } else { - const exportValue = moduleSymbol.exports.get("export=" as EscapedIdentifier); + const exportValue = moduleSymbol.exports.get("export=" as UnderscoreEscapedString); exportDefaultSymbol = exportValue - ? getPropertyOfType(getTypeOfSymbol(exportValue), "default" as EscapedIdentifier) - : resolveSymbol(moduleSymbol.exports.get("default" as EscapedIdentifier), dontResolveAlias); + ? getPropertyOfType(getTypeOfSymbol(exportValue), "default" as UnderscoreEscapedString) + : resolveSymbol(moduleSymbol.exports.get("default" as UnderscoreEscapedString), dontResolveAlias); } if (!exportDefaultSymbol && !allowSyntheticDefaultImports) { @@ -1394,13 +1394,13 @@ namespace ts { return result; } - function getExportOfModule(symbol: Symbol, name: EscapedIdentifier, dontResolveAlias: boolean): Symbol { + function getExportOfModule(symbol: Symbol, name: UnderscoreEscapedString, dontResolveAlias: boolean): Symbol { if (symbol.flags & SymbolFlags.Module) { return resolveSymbol(getExportsOfSymbol(symbol).get(name), dontResolveAlias); } } - function getPropertyOfVariable(symbol: Symbol, name: EscapedIdentifier): Symbol { + function getPropertyOfVariable(symbol: Symbol, name: UnderscoreEscapedString): Symbol { if (symbol.flags & SymbolFlags.Variable) { const typeAnnotation = (symbol.valueDeclaration).type; if (typeAnnotation) { @@ -1421,7 +1421,7 @@ namespace ts { let symbolFromVariable: Symbol; // First check if module was specified with "export=". If so, get the member from the resolved type - if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get("export=" as EscapedIdentifier)) { + if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get("export=" as UnderscoreEscapedString)) { symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name.text); } else { @@ -1738,7 +1738,7 @@ namespace ts { // An external module with an 'export =' declaration resolves to the target of the 'export =' declaration, // and an external module with no 'export =' declaration resolves to the module itself. function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol { - return moduleSymbol && getMergedSymbol(resolveSymbol(moduleSymbol.exports.get("export=" as EscapedIdentifier), dontResolveAlias)) || moduleSymbol; + return moduleSymbol && getMergedSymbol(resolveSymbol(moduleSymbol.exports.get("export=" as UnderscoreEscapedString), dontResolveAlias)) || moduleSymbol; } // An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export =' @@ -1753,7 +1753,7 @@ namespace ts { } function hasExportAssignmentSymbol(moduleSymbol: Symbol): boolean { - return moduleSymbol.exports.get("export=" as EscapedIdentifier) !== undefined; + return moduleSymbol.exports.get("export=" as UnderscoreEscapedString) !== undefined; } function getExportsOfModuleAsArray(moduleSymbol: Symbol): Symbol[] { @@ -1769,7 +1769,7 @@ namespace ts { return exports; } - function tryGetMemberInModuleExports(memberName: EscapedIdentifier, moduleSymbol: Symbol): Symbol | undefined { + function tryGetMemberInModuleExports(memberName: UnderscoreEscapedString, moduleSymbol: Symbol): Symbol | undefined { const symbolTable = getExportsOfModule(moduleSymbol); if (symbolTable) { return symbolTable.get(memberName); @@ -1790,7 +1790,7 @@ namespace ts { exportsWithDuplicate: ExportDeclaration[]; } - type ExportCollisionTrackerTable = EscapedIdentifierMap; + type ExportCollisionTrackerTable = UnderscoreEscapedMap; /** * Extends one symbol table with another while collecting information on name collisions for error message generation into the `lookupTable` argument @@ -1838,7 +1838,7 @@ namespace ts { visitedSymbols.push(symbol); const symbols = cloneMap(symbol.exports); // All export * declarations are collected in an __export symbol by the binder - const exportStars = symbol.exports.get("__export" as EscapedIdentifier); + const exportStars = symbol.exports.get("__export" as UnderscoreEscapedString); if (exportStars) { const nestedSymbols = createSymbolTable(); const lookupTable = createMap() as ExportCollisionTrackerTable; @@ -1862,7 +1862,7 @@ namespace ts { node, Diagnostics.Module_0_has_already_exported_a_member_named_1_Consider_explicitly_re_exporting_to_resolve_the_ambiguity, lookupTable.get(id).specifierText, - unescapeIdentifier(id) + unescapeLeadingUnderscores(id) )); } }); @@ -1939,7 +1939,7 @@ namespace ts { // or the @ symbol. A third underscore indicates an escaped form of an identifer that started // with at least two underscores. The @ character indicates that the name is denoted by a well known ES // Symbol instance. - function isReservedMemberName(name: EscapedIdentifier) { + function isReservedMemberName(name: UnderscoreEscapedString) { return (name as string).charCodeAt(0) === CharacterCodes._ && (name as string).charCodeAt(1) === CharacterCodes._ && (name as string).charCodeAt(2) !== CharacterCodes._ && @@ -2856,7 +2856,7 @@ namespace ts { parameterDeclaration.name.kind === SyntaxKind.Identifier ? setEmitFlags(getSynthesizedClone(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) : cloneBindingName(parameterDeclaration.name) : - unescapeIdentifier(parameterSymbol.name); + unescapeLeadingUnderscores(parameterSymbol.name); const questionToken = isOptionalParameter(parameterDeclaration) ? createToken(SyntaxKind.QuestionToken) : undefined; let parameterType = getTypeOfSymbol(parameterSymbol); @@ -2992,7 +2992,7 @@ namespace ts { return "(Anonymous function)"; } } - return unescapeIdentifier(symbol.name); + return unescapeLeadingUnderscores(symbol.name); } } @@ -3079,7 +3079,7 @@ namespace ts { return "(Anonymous function)"; } } - return unescapeIdentifier(symbol.name); + return unescapeLeadingUnderscores(symbol.name); } function getSymbolDisplayBuilder(): SymbolDisplayBuilder { @@ -3536,7 +3536,7 @@ namespace ts { continue; } if (getDeclarationModifierFlagsFromSymbol(p) & (ModifierFlags.Private | ModifierFlags.Protected)) { - writer.reportPrivateInBaseOfClassExpression(unescapeIdentifier(p.name)); + writer.reportPrivateInBaseOfClassExpression(unescapeLeadingUnderscores(p.name)); } } const t = getTypeOfSymbol(p); @@ -4048,7 +4048,7 @@ namespace ts { } // Return the type of the given property in the given type, or undefined if no such property exists - function getTypeOfPropertyOfType(type: Type, name: EscapedIdentifier): Type { + function getTypeOfPropertyOfType(type: Type, name: UnderscoreEscapedString): Type { const prop = getPropertyOfType(type, name); return prop ? getTypeOfSymbol(prop) : undefined; } @@ -4079,7 +4079,7 @@ namespace ts { } const members = createSymbolTable(); - const names = createEscapedIdentifierMap(); + const names = createUnderscoreEscapedMap(); for (const name of properties) { names.set(getTextOfPropertyName(name), true); } @@ -4166,7 +4166,7 @@ namespace ts { // Use specific property type when parent is a tuple or numeric index type when parent is an array const propName = "" + indexOf(pattern.elements, declaration); type = isTupleLikeType(parentType) - ? getTypeOfPropertyOfType(parentType, propName as EscapedIdentifier) + ? getTypeOfPropertyOfType(parentType, propName as UnderscoreEscapedString) : elementType; if (!type) { if (isTupleType(parentType)) { @@ -5333,8 +5333,8 @@ namespace ts { if (!(type).declaredProperties) { const symbol = type.symbol; (type).declaredProperties = getNamedMembers(symbol.members); - (type).declaredCallSignatures = getSignaturesOfSymbol(symbol.members.get("__call" as EscapedIdentifier)); - (type).declaredConstructSignatures = getSignaturesOfSymbol(symbol.members.get("__new" as EscapedIdentifier)); + (type).declaredCallSignatures = getSignaturesOfSymbol(symbol.members.get("__call" as UnderscoreEscapedString)); + (type).declaredConstructSignatures = getSignaturesOfSymbol(symbol.members.get("__new" as UnderscoreEscapedString)); (type).declaredStringIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.String); (type).declaredNumberIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.Number); } @@ -5625,8 +5625,8 @@ namespace ts { } else if (symbol.flags & SymbolFlags.TypeLiteral) { const members = symbol.members; - const callSignatures = getSignaturesOfSymbol(members.get("__call" as EscapedIdentifier)); - const constructSignatures = getSignaturesOfSymbol(members.get("__new" as EscapedIdentifier)); + const callSignatures = getSignaturesOfSymbol(members.get("__call" as UnderscoreEscapedString)); + const constructSignatures = getSignaturesOfSymbol(members.get("__new" as UnderscoreEscapedString)); const stringIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.String); const numberIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.Number); setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); @@ -5641,7 +5641,7 @@ namespace ts { } if (symbol.flags & SymbolFlags.Class) { const classType = getDeclaredTypeOfClassOrInterface(symbol); - constructSignatures = getSignaturesOfSymbol(symbol.members.get("__constructor" as EscapedIdentifier)); + constructSignatures = getSignaturesOfSymbol(symbol.members.get("__constructor" as UnderscoreEscapedString)); if (!constructSignatures.length) { constructSignatures = getDefaultConstructSignatures(classType); } @@ -5709,7 +5709,7 @@ namespace ts { // If the current iteration type constituent is a string literal type, create a property. // Otherwise, for type string create a string index signature. if (t.flags & TypeFlags.StringLiteral) { - const propName = escapeIdentifier((t).value); + const propName = escapeLeadingUnderscores((t).value); const modifiersProp = getPropertyOfType(modifiersType, propName); const isOptional = templateOptional || !!(modifiersProp && modifiersProp.flags & SymbolFlags.Optional); const prop = createSymbol(SymbolFlags.Property | (isOptional ? SymbolFlags.Optional : 0), propName); @@ -5811,7 +5811,7 @@ namespace ts { /** If the given type is an object type and that type has a property by the given name, * return the symbol for that property. Otherwise return undefined. */ - function getPropertyOfObjectType(type: Type, name: EscapedIdentifier): Symbol { + function getPropertyOfObjectType(type: Type, name: UnderscoreEscapedString): Symbol { if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); const symbol = resolved.members.get(name); @@ -6006,7 +6006,7 @@ namespace ts { t; } - function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: EscapedIdentifier): Symbol { + function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: UnderscoreEscapedString): Symbol { let props: Symbol[]; const types = containingType.types; const isUnion = containingType.flags & TypeFlags.Union; @@ -6077,7 +6077,7 @@ namespace ts { // constituents, in which case the isPartial flag is set when the containing type is union type. We need // these partial properties when identifying discriminant properties, but otherwise they are filtered out // and do not appear to be present in the union type. - function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: EscapedIdentifier): Symbol { + function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: UnderscoreEscapedString): Symbol { const properties = type.propertyCache || (type.propertyCache = createSymbolTable()); let property = properties.get(name); if (!property) { @@ -6089,7 +6089,7 @@ namespace ts { return property; } - function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: EscapedIdentifier): Symbol { + function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: UnderscoreEscapedString): Symbol { const property = getUnionOrIntersectionProperty(type, name); // We need to filter out partial properties in union types return property && !(getCheckFlags(property) & CheckFlags.Partial) ? property : undefined; @@ -6103,7 +6103,7 @@ namespace ts { * @param type a type to look up property from * @param name a name of property to look up in a given type */ - function getPropertyOfType(type: Type, name: EscapedIdentifier): Symbol | undefined { + function getPropertyOfType(type: Type, name: UnderscoreEscapedString): Symbol | undefined { type = getApparentType(type); if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); @@ -6230,7 +6230,7 @@ namespace ts { if (isExternalModuleNameRelative(moduleName)) { return undefined; } - const symbol = getSymbol(globals, `"${moduleName}"` as EscapedIdentifier, SymbolFlags.ValueModule); + const symbol = getSymbol(globals, `"${moduleName}"` as UnderscoreEscapedString, SymbolFlags.ValueModule); // merged symbol is module declaration symbol combined with all augmentations return symbol && withAugmentations ? getMergedSymbol(symbol) : symbol; } @@ -6394,7 +6394,7 @@ namespace ts { let hasRestLikeParameter = hasRestParameter(declaration); if (!hasRestLikeParameter && isInJavaScriptFile(declaration) && containsArgumentsReference(declaration)) { hasRestLikeParameter = true; - const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args" as EscapedIdentifier); + const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args" as UnderscoreEscapedString); syntheticArgsSymbol.type = anyArrayType; syntheticArgsSymbol.isRestParameter = true; parameters.push(syntheticArgsSymbol); @@ -6599,7 +6599,7 @@ namespace ts { } function getIndexSymbol(symbol: Symbol): Symbol { - return symbol.members.get("__index" as EscapedIdentifier); + return symbol.members.get("__index" as UnderscoreEscapedString); } function getIndexDeclarationOfSymbol(symbol: Symbol, kind: IndexKind): SignatureDeclaration { @@ -6969,88 +6969,88 @@ namespace ts { } const type = getDeclaredTypeOfSymbol(symbol); if (!(type.flags & TypeFlags.Object)) { - error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_be_a_class_or_interface_type, unescapeIdentifier(symbol.name)); + error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_be_a_class_or_interface_type, unescapeLeadingUnderscores(symbol.name)); return arity ? emptyGenericType : emptyObjectType; } if (length((type).typeParameters) !== arity) { - error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_have_1_type_parameter_s, unescapeIdentifier(symbol.name), arity); + error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_have_1_type_parameter_s, unescapeLeadingUnderscores(symbol.name), arity); return arity ? emptyGenericType : emptyObjectType; } return type; } - function getGlobalValueSymbol(name: EscapedIdentifier, reportErrors: boolean): Symbol { + function getGlobalValueSymbol(name: UnderscoreEscapedString, reportErrors: boolean): Symbol { return getGlobalSymbol(name, SymbolFlags.Value, reportErrors ? Diagnostics.Cannot_find_global_value_0 : undefined); } - function getGlobalTypeSymbol(name: EscapedIdentifier, reportErrors: boolean): Symbol { + function getGlobalTypeSymbol(name: UnderscoreEscapedString, reportErrors: boolean): Symbol { return getGlobalSymbol(name, SymbolFlags.Type, reportErrors ? Diagnostics.Cannot_find_global_type_0 : undefined); } - function getGlobalSymbol(name: EscapedIdentifier, meaning: SymbolFlags, diagnostic: DiagnosticMessage): Symbol { + function getGlobalSymbol(name: UnderscoreEscapedString, meaning: SymbolFlags, diagnostic: DiagnosticMessage): Symbol { return resolveName(undefined, name, meaning, diagnostic, name); } - function getGlobalType(name: EscapedIdentifier, arity: 0, reportErrors: boolean): ObjectType; - function getGlobalType(name: EscapedIdentifier, arity: number, reportErrors: boolean): GenericType; - function getGlobalType(name: EscapedIdentifier, arity: number, reportErrors: boolean): ObjectType { + function getGlobalType(name: UnderscoreEscapedString, arity: 0, reportErrors: boolean): ObjectType; + function getGlobalType(name: UnderscoreEscapedString, arity: number, reportErrors: boolean): GenericType; + function getGlobalType(name: UnderscoreEscapedString, arity: number, reportErrors: boolean): ObjectType { const symbol = getGlobalTypeSymbol(name, reportErrors); return symbol || reportErrors ? getTypeOfGlobalSymbol(symbol, arity) : undefined; } function getGlobalTypedPropertyDescriptorType() { - return deferredGlobalTypedPropertyDescriptorType || (deferredGlobalTypedPropertyDescriptorType = getGlobalType("TypedPropertyDescriptor" as EscapedIdentifier, /*arity*/ 1, /*reportErrors*/ true)) || emptyGenericType; + return deferredGlobalTypedPropertyDescriptorType || (deferredGlobalTypedPropertyDescriptorType = getGlobalType("TypedPropertyDescriptor" as UnderscoreEscapedString, /*arity*/ 1, /*reportErrors*/ true)) || emptyGenericType; } function getGlobalTemplateStringsArrayType() { - return deferredGlobalTemplateStringsArrayType || (deferredGlobalTemplateStringsArrayType = getGlobalType("TemplateStringsArray" as EscapedIdentifier, /*arity*/ 0, /*reportErrors*/ true)) || emptyObjectType; + return deferredGlobalTemplateStringsArrayType || (deferredGlobalTemplateStringsArrayType = getGlobalType("TemplateStringsArray" as UnderscoreEscapedString, /*arity*/ 0, /*reportErrors*/ true)) || emptyObjectType; } function getGlobalESSymbolConstructorSymbol(reportErrors: boolean) { - return deferredGlobalESSymbolConstructorSymbol || (deferredGlobalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol" as EscapedIdentifier, reportErrors)); + return deferredGlobalESSymbolConstructorSymbol || (deferredGlobalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol" as UnderscoreEscapedString, reportErrors)); } function getGlobalESSymbolType(reportErrors: boolean) { - return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol" as EscapedIdentifier, /*arity*/ 0, reportErrors)) || emptyObjectType; + return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol" as UnderscoreEscapedString, /*arity*/ 0, reportErrors)) || emptyObjectType; } function getGlobalPromiseType(reportErrors: boolean) { - return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise" as EscapedIdentifier, /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise" as UnderscoreEscapedString, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalPromiseConstructorSymbol(reportErrors: boolean): Symbol | undefined { - return deferredGlobalPromiseConstructorSymbol || (deferredGlobalPromiseConstructorSymbol = getGlobalValueSymbol("Promise" as EscapedIdentifier, reportErrors)); + return deferredGlobalPromiseConstructorSymbol || (deferredGlobalPromiseConstructorSymbol = getGlobalValueSymbol("Promise" as UnderscoreEscapedString, reportErrors)); } function getGlobalPromiseConstructorLikeType(reportErrors: boolean) { - return deferredGlobalPromiseConstructorLikeType || (deferredGlobalPromiseConstructorLikeType = getGlobalType("PromiseConstructorLike" as EscapedIdentifier, /*arity*/ 0, reportErrors)) || emptyObjectType; + return deferredGlobalPromiseConstructorLikeType || (deferredGlobalPromiseConstructorLikeType = getGlobalType("PromiseConstructorLike" as UnderscoreEscapedString, /*arity*/ 0, reportErrors)) || emptyObjectType; } function getGlobalAsyncIterableType(reportErrors: boolean) { - return deferredGlobalAsyncIterableType || (deferredGlobalAsyncIterableType = getGlobalType("AsyncIterable" as EscapedIdentifier, /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIterableType || (deferredGlobalAsyncIterableType = getGlobalType("AsyncIterable" as UnderscoreEscapedString, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalAsyncIteratorType(reportErrors: boolean) { - return deferredGlobalAsyncIteratorType || (deferredGlobalAsyncIteratorType = getGlobalType("AsyncIterator" as EscapedIdentifier, /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIteratorType || (deferredGlobalAsyncIteratorType = getGlobalType("AsyncIterator" as UnderscoreEscapedString, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalAsyncIterableIteratorType(reportErrors: boolean) { - return deferredGlobalAsyncIterableIteratorType || (deferredGlobalAsyncIterableIteratorType = getGlobalType("AsyncIterableIterator" as EscapedIdentifier, /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIterableIteratorType || (deferredGlobalAsyncIterableIteratorType = getGlobalType("AsyncIterableIterator" as UnderscoreEscapedString, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIterableType(reportErrors: boolean) { - return deferredGlobalIterableType || (deferredGlobalIterableType = getGlobalType("Iterable" as EscapedIdentifier, /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalIterableType || (deferredGlobalIterableType = getGlobalType("Iterable" as UnderscoreEscapedString, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIteratorType(reportErrors: boolean) { - return deferredGlobalIteratorType || (deferredGlobalIteratorType = getGlobalType("Iterator" as EscapedIdentifier, /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalIteratorType || (deferredGlobalIteratorType = getGlobalType("Iterator" as UnderscoreEscapedString, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIterableIteratorType(reportErrors: boolean) { - return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType("IterableIterator" as EscapedIdentifier, /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType("IterableIterator" as UnderscoreEscapedString, /*arity*/ 1, reportErrors)) || emptyGenericType; } - function getGlobalTypeOrUndefined(name: EscapedIdentifier, arity = 0): ObjectType { + function getGlobalTypeOrUndefined(name: UnderscoreEscapedString, arity = 0): ObjectType { const symbol = getGlobalSymbol(name, SymbolFlags.Type, /*diagnostic*/ undefined); return symbol && getTypeOfGlobalSymbol(symbol, arity); } @@ -7059,7 +7059,7 @@ namespace ts { * Returns a type that is inside a namespace at the global scope, e.g. * getExportedTypeFromNamespace('JSX', 'Element') returns the JSX.Element type */ - function getExportedTypeFromNamespace(namespace: EscapedIdentifier, name: EscapedIdentifier): Type { + function getExportedTypeFromNamespace(namespace: UnderscoreEscapedString, name: UnderscoreEscapedString): Type { const namespaceSymbol = getGlobalSymbol(namespace, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined); const typeSymbol = namespaceSymbol && getSymbol(namespaceSymbol.exports, name, SymbolFlags.Type); return typeSymbol && getDeclaredTypeOfSymbol(typeSymbol); @@ -7117,7 +7117,7 @@ namespace ts { for (let i = 0; i < arity; i++) { const typeParameter = createType(TypeFlags.TypeParameter); typeParameters.push(typeParameter); - const property = createSymbol(SymbolFlags.Property, "" + i as EscapedIdentifier); + const property = createSymbol(SymbolFlags.Property, "" + i as UnderscoreEscapedString); property.type = typeParameter; properties.push(property); } @@ -7459,7 +7459,7 @@ namespace ts { function getLiteralTypeFromPropertyName(prop: Symbol) { return getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier || startsWith(prop.name as string, "__@") ? neverType : - getLiteralType(unescapeIdentifier(prop.name)); + getLiteralType(unescapeLeadingUnderscores(prop.name)); } function getLiteralTypeFromPropertyNames(type: Type) { @@ -7496,9 +7496,9 @@ namespace ts { function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode, cacheSymbol: boolean) { const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined; const propName = indexType.flags & TypeFlags.StringOrNumberLiteral ? - escapeIdentifier("" + (indexType).value) : + escapeLeadingUnderscores("" + (indexType).value) : accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false) ? - getPropertyNameForKnownSymbolName(unescapeIdentifier(((accessExpression.argumentExpression).name).text)) : + getPropertyNameForKnownSymbolName(unescapeLeadingUnderscores(((accessExpression.argumentExpression).name).text)) : undefined; if (propName !== undefined) { const prop = getPropertyOfType(objectType, propName); @@ -7687,7 +7687,7 @@ namespace ts { } const members = createSymbolTable(); - const skippedPrivateMembers = createEscapedIdentifierMap(); + const skippedPrivateMembers = createUnderscoreEscapedMap(); let stringIndexInfo: IndexInfo; let numberIndexInfo: IndexInfo; if (left === emptyObjectType) { @@ -8496,8 +8496,8 @@ namespace ts { if (!related) { if (reportErrors) { errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, - unescapeIdentifier(sourceParams[i < sourceMax ? i : sourceMax].name), - unescapeIdentifier(targetParams[i < targetMax ? i : targetMax].name)); + unescapeLeadingUnderscores(sourceParams[i < sourceMax ? i : sourceMax].name), + unescapeLeadingUnderscores(targetParams[i < targetMax ? i : targetMax].name)); } return Ternary.False; } @@ -8646,7 +8646,7 @@ namespace ts { const targetProperty = getPropertyOfType(targetEnumType, property.name); if (!targetProperty || !(targetProperty.flags & SymbolFlags.EnumMember)) { if (errorReporter) { - errorReporter(Diagnostics.Property_0_is_missing_in_type_1, unescapeIdentifier(property.name), + errorReporter(Diagnostics.Property_0_is_missing_in_type_1, unescapeLeadingUnderscores(property.name), typeToString(getDeclaredTypeOfSymbol(targetSymbol), /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); } enumRelation.set(id, false); @@ -9898,7 +9898,7 @@ namespace ts { } function isTupleLikeType(type: Type): boolean { - return !!getPropertyOfType(type, "0" as EscapedIdentifier); + return !!getPropertyOfType(type, "0" as UnderscoreEscapedString); } function isUnitType(type: Type): boolean { @@ -10122,7 +10122,7 @@ namespace ts { const t = getTypeOfSymbol(p); if (t.flags & TypeFlags.ContainsWideningType) { if (!reportWideningErrorsInType(t)) { - error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, unescapeIdentifier(p.name), typeToString(getWidenedType(t))); + error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, unescapeLeadingUnderscores(p.name), typeToString(getWidenedType(t))); } errorReported = true; } @@ -10753,7 +10753,7 @@ namespace ts { return undefined; } - function isDiscriminantProperty(type: Type, name: EscapedIdentifier) { + function isDiscriminantProperty(type: Type, name: UnderscoreEscapedString) { if (type && type.flags & TypeFlags.Union) { const prop = getUnionOrIntersectionProperty(type, name); if (prop && getCheckFlags(prop) & CheckFlags.SyntheticProperty) { @@ -10834,7 +10834,7 @@ namespace ts { // check. This gives us a quicker out in the common case where an object type is not a function. const resolved = resolveStructuredTypeMembers(type); return !!(resolved.callSignatures.length || resolved.constructSignatures.length || - resolved.members.get("bind" as EscapedIdentifier) && isTypeSubtypeOf(type, globalFunctionType)); + resolved.members.get("bind" as UnderscoreEscapedString) && isTypeSubtypeOf(type, globalFunctionType)); } function getTypeFacts(type: Type): TypeFacts { @@ -10912,7 +10912,7 @@ namespace ts { } function getTypeOfDestructuredArrayElement(type: Type, index: number) { - return isTupleLikeType(type) && getTypeOfPropertyOfType(type, "" + index as EscapedIdentifier) || + return isTupleLikeType(type) && getTypeOfPropertyOfType(type, "" + index as UnderscoreEscapedString) || checkIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || unknownType; } @@ -11745,7 +11745,7 @@ namespace ts { } let targetType: Type; - const prototypeProperty = getPropertyOfType(rightType, "prototype" as EscapedIdentifier); + const prototypeProperty = getPropertyOfType(rightType, "prototype" as UnderscoreEscapedString); if (prototypeProperty) { // Target type is type of the prototype property const prototypePropertyType = getTypeOfSymbol(prototypeProperty); @@ -12836,7 +12836,7 @@ namespace ts { return undefined; } - function getTypeOfPropertyOfContextualType(type: Type, name: EscapedIdentifier) { + function getTypeOfPropertyOfContextualType(type: Type, name: UnderscoreEscapedString) { return mapType(type, t => { const prop = t.flags & TypeFlags.StructuredType ? getPropertyOfType(t, name) : undefined; return prop ? getTypeOfSymbol(prop) : undefined; @@ -12896,7 +12896,7 @@ namespace ts { const type = getApparentTypeOfContextualType(arrayLiteral); if (type) { const index = indexOf(arrayLiteral.elements, node); - return getTypeOfPropertyOfContextualType(type, "" + index as EscapedIdentifier) + return getTypeOfPropertyOfContextualType(type, "" + index as UnderscoreEscapedString) || getIndexTypeOfContextualType(type, IndexKind.Number) || getIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false, /*checkAssignability*/ false); } @@ -13228,11 +13228,11 @@ namespace ts { return isTypeAny(type) || isTypeOfKind(type, kind); } - function isInfinityOrNaNString(name: string | EscapedIdentifier): boolean { + function isInfinityOrNaNString(name: string | UnderscoreEscapedString): boolean { return name === "Infinity" || name === "-Infinity" || name === "NaN"; } - function isNumericLiteralName(name: string | EscapedIdentifier) { + function isNumericLiteralName(name: string | UnderscoreEscapedString) { // The intent of numeric names is that // - they are names with text in a numeric form, and that // - setting properties/indexing with them is always equivalent to doing so with the numeric literal 'numLit', @@ -13498,7 +13498,7 @@ namespace ts { /** * Returns true iff the JSX element name would be a valid JS identifier, ignoring restrictions about keywords not being identifiers */ - function isUnhyphenatedJsxName(name: string | EscapedIdentifier) { + function isUnhyphenatedJsxName(name: string | UnderscoreEscapedString) { // - is the only character supported in JSX attribute names that isn't valid in JavaScript identifiers return (name as string).indexOf("-") < 0; } @@ -13615,7 +13615,7 @@ namespace ts { // This is because children element will overwrite the value from attributes. // Note: we will not warn "children" attribute overwritten if "children" attribute is specified in object spread. if (explicitlySpecifyChildrenAttribute) { - error(attributes, Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, unescapeIdentifier(jsxChildrenPropertyName)); + error(attributes, Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, unescapeLeadingUnderscores(jsxChildrenPropertyName)); } // If there are children in the body of JSX element, create dummy attribute "children" with anyType so that it will pass the attribute checking process @@ -13640,7 +13640,7 @@ namespace ts { * @param symbol a symbol of JsxAttributes containing attributes corresponding to attributesTable * @param attributesTable a symbol table of attributes property */ - function createJsxAttributesType(symbol: Symbol, attributesTable: EscapedIdentifierMap) { + function createJsxAttributesType(symbol: Symbol, attributesTable: UnderscoreEscapedMap) { const result = createAnonymousType(symbol, attributesTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined); result.flags |= TypeFlags.JsxAttributes | TypeFlags.ContainsObjectLiteral; result.objectFlags |= ObjectFlags.ObjectLiteral; @@ -13657,7 +13657,7 @@ namespace ts { return createJsxAttributesTypeFromAttributesProperty(node.parent as JsxOpeningLikeElement, /*filter*/ undefined, checkMode); } - function getJsxType(name: EscapedIdentifier) { + function getJsxType(name: UnderscoreEscapedString) { let jsxType = jsxTypes.get(name); if (jsxType === undefined) { jsxTypes.set(name, jsxType = getExportedTypeFromNamespace(JsxNames.JSX, name) || unknownType); @@ -13691,12 +13691,12 @@ namespace ts { } // Wasn't found - error(node, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeIdentifier((node.tagName).text), "JSX." + JsxNames.IntrinsicElements); + error(node, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores((node.tagName).text), "JSX." + JsxNames.IntrinsicElements); return links.resolvedSymbol = unknownSymbol; } else { if (noImplicitAny) { - error(node, Diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, unescapeIdentifier(JsxNames.IntrinsicElements)); + error(node, Diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, unescapeLeadingUnderscores(JsxNames.IntrinsicElements)); } return links.resolvedSymbol = unknownSymbol; } @@ -13749,7 +13749,7 @@ namespace ts { * @param nameOfAttribPropContainer a string of value JsxNames.ElementAttributesPropertyNameContainer or JsxNames.ElementChildrenAttributeNameContainer * if other string is given or the container doesn't exist, return undefined. */ - function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: EscapedIdentifier): EscapedIdentifier { + function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: UnderscoreEscapedString): UnderscoreEscapedString { // JSX const jsxNamespace = getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined); // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [symbol] @@ -13761,7 +13761,7 @@ namespace ts { if (propertiesOfJsxElementAttribPropInterface) { // Element Attributes has zero properties, so the element attributes type will be the class instance type if (propertiesOfJsxElementAttribPropInterface.length === 0) { - return "" as EscapedIdentifier; + return "" as UnderscoreEscapedString; } // Element Attributes has one property, so the element attributes type will be the type of the corresponding // property of the class instance type @@ -13770,7 +13770,7 @@ namespace ts { } else if (propertiesOfJsxElementAttribPropInterface.length > 1) { // More than one property on ElementAttributesProperty is an error - error(jsxElementAttribPropInterfaceSym.declarations[0], Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, unescapeIdentifier(nameOfAttribPropContainer)); + error(jsxElementAttribPropInterfaceSym.declarations[0], Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, unescapeLeadingUnderscores(nameOfAttribPropContainer)); } } return undefined; @@ -13790,7 +13790,7 @@ namespace ts { return _jsxElementPropertiesName; } - function getJsxElementChildrenPropertyname(): EscapedIdentifier { + function getJsxElementChildrenPropertyname(): UnderscoreEscapedString { if (!_hasComputedJsxElementChildrenPropertyName) { _hasComputedJsxElementChildrenPropertyName = true; _jsxElementChildrenPropertyName = getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer); @@ -13948,7 +13948,7 @@ namespace ts { // Hello World const intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements); if (intrinsicElementsType !== unknownType) { - const stringLiteralTypeName = escapeIdentifier((elementType).value); + const stringLiteralTypeName = escapeLeadingUnderscores((elementType).value); const intrinsicProp = getPropertyOfType(intrinsicElementsType, stringLiteralTypeName); if (intrinsicProp) { return getTypeOfSymbol(intrinsicProp); @@ -13957,7 +13957,7 @@ namespace ts { if (indexSignatureType) { return indexSignatureType; } - error(openingLikeElement, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeIdentifier(stringLiteralTypeName), "JSX." + JsxNames.IntrinsicElements); + error(openingLikeElement, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(stringLiteralTypeName), "JSX." + JsxNames.IntrinsicElements); } // If we need to report an error, we already done so here. So just return any to prevent any more error downstream return anyType; @@ -14190,7 +14190,7 @@ namespace ts { * @param name a property name to search * @param isComparingJsxAttributes a boolean flag indicating whether we are searching in JsxAttributesType */ - function isKnownProperty(targetType: Type, name: EscapedIdentifier, isComparingJsxAttributes: boolean): boolean { + function isKnownProperty(targetType: Type, name: UnderscoreEscapedString, isComparingJsxAttributes: boolean): boolean { if (targetType.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(targetType); if (resolved.stringIndexInfo || @@ -14240,7 +14240,7 @@ namespace ts { // If the targetAttributesType is an emptyObjectType, indicating that there is no property named 'props' on this instance type. // but there exists a sourceAttributesType, we need to explicitly give an error as normal assignability check allow excess properties and will pass. if (targetAttributesType === emptyObjectType && (isTypeAny(sourceAttributesType) || (sourceAttributesType).properties.length > 0)) { - error(openingLikeElement, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, unescapeIdentifier(getJsxElementPropertiesName())); + error(openingLikeElement, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, unescapeLeadingUnderscores(getJsxElementPropertiesName())); } else { // Check if sourceAttributesType assignable to targetAttributesType though this check will allow excess properties @@ -14250,7 +14250,7 @@ namespace ts { if (isSourceAttributeTypeAssignableToTarget && !isTypeAny(sourceAttributesType) && !isTypeAny(targetAttributesType)) { for (const attribute of openingLikeElement.attributes.properties) { if (isJsxAttribute(attribute) && !isKnownProperty(targetAttributesType, attribute.name.text, /*isComparingJsxAttributes*/ true)) { - error(attribute, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeIdentifier(attribute.name.text), typeToString(targetAttributesType)); + error(attribute, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(attribute.name.text), typeToString(targetAttributesType)); // We break here so that errors won't be cascading break; } @@ -14435,13 +14435,13 @@ namespace ts { if (prop.valueDeclaration) { if (isInPropertyInitializer(node) && !isBlockScopedNameDeclaredBeforeUse(prop.valueDeclaration, right)) { - error(right, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, unescapeIdentifier(right.text)); + error(right, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, unescapeLeadingUnderscores(right.text)); } if (prop.valueDeclaration.kind === SyntaxKind.ClassDeclaration && node.parent && node.parent.kind !== SyntaxKind.TypeReference && !isInAmbientContext(prop.valueDeclaration) && !isBlockScopedNameDeclaredBeforeUse(prop.valueDeclaration, right)) { - error(right, Diagnostics.Class_0_used_before_its_declaration, unescapeIdentifier(right.text)); + error(right, Diagnostics.Class_0_used_before_its_declaration, unescapeLeadingUnderscores(right.text)); } } @@ -14456,7 +14456,7 @@ namespace ts { if (assignmentKind) { if (isReferenceToReadonlyEntity(node, prop) || isReferenceThroughNamespaceImport(node)) { - error(right, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, unescapeIdentifier(right.text)); + error(right, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, unescapeLeadingUnderscores(right.text)); return unknownType; } } @@ -14493,12 +14493,12 @@ namespace ts { diagnostics.add(createDiagnosticForNodeFromMessageChain(propNode, errorInfo)); } - function getSuggestionForNonexistentProperty(node: Identifier, containingType: Type): EscapedIdentifier | undefined { - const suggestion = getSpellingSuggestionForName(unescapeIdentifier(node.text), getPropertiesOfType(containingType), SymbolFlags.Value); + function getSuggestionForNonexistentProperty(node: Identifier, containingType: Type): UnderscoreEscapedString | undefined { + const suggestion = getSpellingSuggestionForName(unescapeLeadingUnderscores(node.text), getPropertiesOfType(containingType), SymbolFlags.Value); return suggestion && suggestion.name; } - function getSuggestionForNonexistentSymbol(location: Node, name: EscapedIdentifier, meaning: SymbolFlags): EscapedIdentifier { + function getSuggestionForNonexistentSymbol(location: Node, name: UnderscoreEscapedString, meaning: SymbolFlags): UnderscoreEscapedString { const result = resolveNameHelper(location, name, meaning, /*nameNotFoundMessage*/ undefined, name, (symbols, name, meaning) => { const symbol = getSymbol(symbols, name, meaning); if (symbol) { @@ -14507,7 +14507,7 @@ namespace ts { // However, resolveNameHelper will continue and call this callback again, so we'll eventually get a correct suggestion. return symbol; } - return getSpellingSuggestionForName(unescapeIdentifier(name), arrayFrom(symbols.values()), meaning); + return getSpellingSuggestionForName(unescapeLeadingUnderscores(name), arrayFrom(symbols.values()), meaning); }); if (result) { return result.name; @@ -14541,7 +14541,7 @@ namespace ts { } name = name.toLowerCase(); for (const candidate of symbols) { - let candidateName = unescapeIdentifier(candidate.name); + let candidateName = unescapeLeadingUnderscores(candidate.name); if (candidate.flags & meaning && candidateName && Math.abs(candidateName.length - name.length) < maximumLengthDifference) { @@ -14603,7 +14603,7 @@ namespace ts { return false; } - function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: EscapedIdentifier): boolean { + function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: UnderscoreEscapedString): boolean { const left = node.kind === SyntaxKind.PropertyAccessExpression ? (node).expression : (node).left; @@ -14614,7 +14614,7 @@ namespace ts { function isValidPropertyAccessWithType( node: PropertyAccessExpression | QualifiedName, left: LeftHandSideExpression | QualifiedName, - propertyName: EscapedIdentifier, + propertyName: UnderscoreEscapedString, type: Type): boolean { if (type !== unknownType && !isTypeAny(type)) { @@ -15356,7 +15356,7 @@ namespace ts { const element = node; switch (element.name.kind) { case SyntaxKind.Identifier: - return getLiteralType(unescapeIdentifier((element.name).text)); + return getLiteralType(unescapeLeadingUnderscores((element.name).text)); case SyntaxKind.NumericLiteral: case SyntaxKind.StringLiteral: return getLiteralType((element.name).text); @@ -17068,7 +17068,7 @@ namespace ts { const element = elements[elementIndex]; if (element.kind !== SyntaxKind.OmittedExpression) { if (element.kind !== SyntaxKind.SpreadElement) { - const propName = "" + elementIndex as EscapedIdentifier; + const propName = "" + elementIndex as UnderscoreEscapedString; const type = isTypeAny(sourceType) ? sourceType : isTupleLikeType(sourceType) @@ -18082,8 +18082,8 @@ namespace ts { Property = Getter | Setter } - const instanceNames = createEscapedIdentifierMap(); - const staticNames = createEscapedIdentifierMap(); + const instanceNames = createUnderscoreEscapedMap(); + const staticNames = createUnderscoreEscapedMap(); for (const member of node.members) { if (member.kind === SyntaxKind.Constructor) { for (const param of (member as ConstructorDeclaration).parameters) { @@ -18119,7 +18119,7 @@ namespace ts { } } - function addName(names: EscapedIdentifierMap, location: Node, name: EscapedIdentifier, meaning: Declaration) { + function addName(names: UnderscoreEscapedMap, location: Node, name: UnderscoreEscapedString, meaning: Declaration) { const prev = names.get(name); if (prev) { if (prev & Declaration.Method) { @@ -18183,7 +18183,7 @@ namespace ts { memberName = member.name.text; break; case SyntaxKind.Identifier: - memberName = unescapeIdentifier(member.name.text); + memberName = unescapeLeadingUnderscores(member.name.text); break; default: continue; @@ -18893,7 +18893,7 @@ namespace ts { return typeAsPromise.promisedTypeOfPromise = (promise).typeArguments[0]; } - const thenFunction = getTypeOfPropertyOfType(promise, "then" as EscapedIdentifier); + const thenFunction = getTypeOfPropertyOfType(promise, "then" as UnderscoreEscapedString); if (isTypeAny(thenFunction)) { return undefined; } @@ -19025,7 +19025,7 @@ namespace ts { // of a runtime problem. If the user wants to return this value from an async // function, they would need to wrap it in some other value. If they want it to // be treated as a promise, they can cast to . - const thenFunction = getTypeOfPropertyOfType(type, "then" as EscapedIdentifier); + const thenFunction = getTypeOfPropertyOfType(type, "then" as UnderscoreEscapedString); if (thenFunction && getSignaturesOfType(thenFunction, SignatureKind.Call).length > 0) { if (errorNode) { Debug.assert(!!diagnosticMessage); @@ -19134,7 +19134,7 @@ namespace ts { const collidingSymbol = getSymbol(node.locals, rootName.text, SymbolFlags.Value); if (collidingSymbol) { error(collidingSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions, - unescapeIdentifier(rootName.text), + unescapeLeadingUnderscores(rootName.text), entityNameToString(promiseConstructorName)); return unknownType; } @@ -19483,11 +19483,11 @@ namespace ts { !isParameterPropertyDeclaration(parameter) && !parameterIsThisKeyword(parameter) && !parameterNameStartsWithUnderscore(name)) { - error(name, Diagnostics._0_is_declared_but_never_used, unescapeIdentifier(local.name)); + error(name, Diagnostics._0_is_declared_but_never_used, unescapeLeadingUnderscores(local.name)); } } else if (compilerOptions.noUnusedLocals) { - forEach(local.declarations, d => errorUnusedLocal(getNameOfDeclaration(d) || d, unescapeIdentifier(local.name))); + forEach(local.declarations, d => errorUnusedLocal(getNameOfDeclaration(d) || d, unescapeLeadingUnderscores(local.name))); } } }); @@ -19520,7 +19520,7 @@ namespace ts { } function isIdentifierThatStartsWithUnderScore(node: Node) { - return node.kind === SyntaxKind.Identifier && unescapeIdentifier((node).text).charCodeAt(0) === CharacterCodes._; + return node.kind === SyntaxKind.Identifier && unescapeLeadingUnderscores((node).text).charCodeAt(0) === CharacterCodes._; } function checkUnusedClassMembers(node: ClassDeclaration | ClassExpression): void { @@ -19529,13 +19529,13 @@ namespace ts { for (const member of node.members) { if (member.kind === SyntaxKind.MethodDeclaration || member.kind === SyntaxKind.PropertyDeclaration) { if (!member.symbol.isReferenced && getModifierFlags(member) & ModifierFlags.Private) { - error(member.name, Diagnostics._0_is_declared_but_never_used, unescapeIdentifier(member.symbol.name)); + error(member.name, Diagnostics._0_is_declared_but_never_used, unescapeLeadingUnderscores(member.symbol.name)); } } else if (member.kind === SyntaxKind.Constructor) { for (const parameter of (member).parameters) { if (!parameter.symbol.isReferenced && getModifierFlags(parameter) & ModifierFlags.Private) { - error(parameter.name, Diagnostics.Property_0_is_declared_but_never_used, unescapeIdentifier(parameter.symbol.name)); + error(parameter.name, Diagnostics.Property_0_is_declared_but_never_used, unescapeLeadingUnderscores(parameter.symbol.name)); } } } @@ -19556,7 +19556,7 @@ namespace ts { } for (const typeParameter of node.typeParameters) { if (!getMergedSymbol(typeParameter.symbol).isReferenced) { - error(typeParameter.name, Diagnostics._0_is_declared_but_never_used, unescapeIdentifier(typeParameter.symbol.name)); + error(typeParameter.name, Diagnostics._0_is_declared_but_never_used, unescapeLeadingUnderscores(typeParameter.symbol.name)); } } } @@ -19569,7 +19569,7 @@ namespace ts { if (!local.isReferenced && !local.exportSymbol) { for (const declaration of local.declarations) { if (!isAmbientModule(declaration)) { - errorUnusedLocal(getNameOfDeclaration(declaration), unescapeIdentifier(local.name)); + errorUnusedLocal(getNameOfDeclaration(declaration), unescapeLeadingUnderscores(local.name)); } } } @@ -20462,7 +20462,7 @@ namespace ts { } // Both async and non-async iterators must have a `next` method. - const nextMethod = getTypeOfPropertyOfType(type, "next" as EscapedIdentifier); + const nextMethod = getTypeOfPropertyOfType(type, "next" as UnderscoreEscapedString); if (isTypeAny(nextMethod)) { return undefined; } @@ -20490,7 +20490,7 @@ namespace ts { } } - const nextValue = nextResult && getTypeOfPropertyOfType(nextResult, "value" as EscapedIdentifier); + const nextValue = nextResult && getTypeOfPropertyOfType(nextResult, "value" as UnderscoreEscapedString); if (!nextValue) { if (errorNode) { error(errorNode, isAsyncIterator @@ -21171,7 +21171,7 @@ namespace ts { } type InheritanceInfoMap = { prop: Symbol; containingType: Type }; - const seen = createEscapedIdentifierMap(); + const seen = createUnderscoreEscapedMap(); forEach(resolveDeclaredMembers(type).declaredProperties, p => { seen.set(p.name, { prop: p, containingType: type }); }); let ok = true; @@ -21370,7 +21370,7 @@ namespace ts { if (type.symbol && type.symbol.flags & SymbolFlags.Enum) { const name = expr.kind === SyntaxKind.PropertyAccessExpression ? (expr).name.text : - ((expr).argumentExpression).text as EscapedIdentifier; + ((expr).argumentExpression).text as UnderscoreEscapedString; return evaluateEnumMember(expr, type.symbol, name); } } @@ -21379,7 +21379,7 @@ namespace ts { return undefined; } - function evaluateEnumMember(expr: Expression, enumSymbol: Symbol, name: EscapedIdentifier) { + function evaluateEnumMember(expr: Expression, enumSymbol: Symbol, name: UnderscoreEscapedString) { const memberSymbol = enumSymbol.exports.get(name); if (memberSymbol) { const declaration = memberSymbol.valueDeclaration; @@ -21844,7 +21844,7 @@ namespace ts { const symbol = resolveName(exportedName, exportedName.text, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined); if (symbol && (symbol === undefinedSymbol || isGlobalSourceFile(getDeclarationContainer(symbol.declarations[0])))) { - error(exportedName, Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, unescapeIdentifier(exportedName.text)); + error(exportedName, Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, unescapeLeadingUnderscores(exportedName.text)); } else { markExportAsReferenced(node); @@ -21902,7 +21902,7 @@ namespace ts { const moduleSymbol = getSymbolOfNode(node); const links = getSymbolLinks(moduleSymbol); if (!links.exportsChecked) { - const exportEqualsSymbol = moduleSymbol.exports.get("export=" as EscapedIdentifier); + const exportEqualsSymbol = moduleSymbol.exports.get("export=" as UnderscoreEscapedString); if (exportEqualsSymbol && hasExportedMembers(moduleSymbol)) { const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration; if (!isTopLevelInExternalModuleAugmentation(declaration)) { @@ -21929,7 +21929,7 @@ namespace ts { if (exportedDeclarationsCount > 1) { for (const declaration of declarations) { if (isNotOverload(declaration)) { - diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, unescapeIdentifier(id))); + diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, unescapeLeadingUnderscores(id))); } } } @@ -22615,7 +22615,7 @@ namespace ts { if (objectType === unknownType) return undefined; const apparentType = getApparentType(objectType); if (apparentType === unknownType) return undefined; - return getPropertyOfType(apparentType, (node).text as EscapedIdentifier); + return getPropertyOfType(apparentType, (node).text as UnderscoreEscapedString); } break; } @@ -23208,7 +23208,7 @@ namespace ts { } function hasGlobalName(name: string): boolean { - return globals.has(escapeIdentifier(name)); + return globals.has(escapeLeadingUnderscores(name)); } function getReferencedValueSymbol(reference: Identifier, startInDeclarationContainer?: boolean): Symbol { @@ -23452,23 +23452,23 @@ namespace ts { addToSymbolTable(globals, builtinGlobals, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0); getSymbolLinks(undefinedSymbol).type = undefinedWideningType; - getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments" as EscapedIdentifier, /*arity*/ 0, /*reportErrors*/ true); + getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments" as UnderscoreEscapedString, /*arity*/ 0, /*reportErrors*/ true); getSymbolLinks(unknownSymbol).type = unknownType; // Initialize special types - globalArrayType = getGlobalType("Array" as EscapedIdentifier, /*arity*/ 1, /*reportErrors*/ true); - globalObjectType = getGlobalType("Object" as EscapedIdentifier, /*arity*/ 0, /*reportErrors*/ true); - globalFunctionType = getGlobalType("Function" as EscapedIdentifier, /*arity*/ 0, /*reportErrors*/ true); - globalStringType = getGlobalType("String" as EscapedIdentifier, /*arity*/ 0, /*reportErrors*/ true); - globalNumberType = getGlobalType("Number" as EscapedIdentifier, /*arity*/ 0, /*reportErrors*/ true); - globalBooleanType = getGlobalType("Boolean" as EscapedIdentifier, /*arity*/ 0, /*reportErrors*/ true); - globalRegExpType = getGlobalType("RegExp" as EscapedIdentifier, /*arity*/ 0, /*reportErrors*/ true); + globalArrayType = getGlobalType("Array" as UnderscoreEscapedString, /*arity*/ 1, /*reportErrors*/ true); + globalObjectType = getGlobalType("Object" as UnderscoreEscapedString, /*arity*/ 0, /*reportErrors*/ true); + globalFunctionType = getGlobalType("Function" as UnderscoreEscapedString, /*arity*/ 0, /*reportErrors*/ true); + globalStringType = getGlobalType("String" as UnderscoreEscapedString, /*arity*/ 0, /*reportErrors*/ true); + globalNumberType = getGlobalType("Number" as UnderscoreEscapedString, /*arity*/ 0, /*reportErrors*/ true); + globalBooleanType = getGlobalType("Boolean" as UnderscoreEscapedString, /*arity*/ 0, /*reportErrors*/ true); + globalRegExpType = getGlobalType("RegExp" as UnderscoreEscapedString, /*arity*/ 0, /*reportErrors*/ true); anyArrayType = createArrayType(anyType); autoArrayType = createArrayType(autoType); - globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray" as EscapedIdentifier, /*arity*/ 1); + globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray" as UnderscoreEscapedString, /*arity*/ 1); anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; - globalThisType = getGlobalTypeOrUndefined("ThisType" as EscapedIdentifier, /*arity*/ 1); + globalThisType = getGlobalTypeOrUndefined("ThisType" as UnderscoreEscapedString, /*arity*/ 1); } function checkExternalEmitHelpers(location: Node, helpers: ExternalEmitHelpers) { @@ -23481,7 +23481,7 @@ namespace ts { for (let helper = ExternalEmitHelpers.FirstEmitHelper; helper <= ExternalEmitHelpers.LastEmitHelper; helper <<= 1) { if (uncheckedHelpers & helper) { const name = getHelperName(helper); - const symbol = getSymbol(helpersModule.exports, escapeIdentifier(name), SymbolFlags.Value); + const symbol = getSymbol(helpersModule.exports, escapeLeadingUnderscores(name), SymbolFlags.Value); if (!symbol) { error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_but_module_0_has_no_exported_member_1, externalHelpersModuleNameText, name); } @@ -24085,7 +24085,7 @@ namespace ts { } function checkGrammarObjectLiteralExpression(node: ObjectLiteralExpression, inDestructuring: boolean) { - const seen = createEscapedIdentifierMap(); + const seen = createUnderscoreEscapedMap(); const Property = 1; const GetAccessor = 2; const SetAccessor = 4; @@ -24175,7 +24175,7 @@ namespace ts { } function checkGrammarJsxElement(node: JsxOpeningLikeElement) { - const seen = createEscapedIdentifierMap(); + const seen = createUnderscoreEscapedMap(); for (const attr of node.attributes.properties) { if (attr.kind === SyntaxKind.JsxSpreadAttribute) { @@ -24480,7 +24480,7 @@ namespace ts { function checkESModuleMarker(name: Identifier | BindingPattern): boolean { if (name.kind === SyntaxKind.Identifier) { - if (unescapeIdentifier(name.text) === "__esModule") { + if (unescapeLeadingUnderscores(name.text) === "__esModule") { return grammarErrorOnNode(name, Diagnostics.Identifier_expected_esModule_is_reserved_as_an_exported_marker_when_transforming_ECMAScript_modules); } } @@ -24732,7 +24732,7 @@ namespace ts { function getAmbientModules(): Symbol[] { const result: Symbol[] = []; globals.forEach((global, sym) => { - if (ambientModuleSymbolRegex.test(unescapeIdentifier(sym))) { + if (ambientModuleSymbolRegex.test(unescapeLeadingUnderscores(sym))) { result.push(global); } }); diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 6288f5ad18293..422789f420fea 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1047,7 +1047,7 @@ namespace ts { errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.name, Diagnostics.String_literal_with_double_quotes_expected)); } - const keyText = unescapeIdentifier(getTextOfPropertyName(element.name)); + const keyText = unescapeLeadingUnderscores(getTextOfPropertyName(element.name)); const option = knownOptions ? knownOptions.get(keyText) : undefined; if (extraKeyDiagnosticMessage && !option) { errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.name, extraKeyDiagnosticMessage, keyText)); diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 3e9d5f179b7ea..7e96d828b5a71 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -48,8 +48,8 @@ namespace ts { } /** Create a new escaped identifier map. */ - export function createEscapedIdentifierMap(): EscapedIdentifierMap { - return new MapCtr() as EscapedIdentifierMap; + export function createUnderscoreEscapedMap(): UnderscoreEscapedMap { + return new MapCtr() as UnderscoreEscapedMap; } /* @internal */ @@ -1016,13 +1016,13 @@ namespace ts { * Calls `callback` for each entry in the map, returning the first truthy result. * Use `map.forEach` instead for normal iteration. */ - export function forEachEntry(map: EscapedIdentifierMap, callback: (value: T, key: EscapedIdentifier) => U | undefined): U | undefined; + export function forEachEntry(map: UnderscoreEscapedMap, callback: (value: T, key: UnderscoreEscapedString) => U | undefined): U | undefined; export function forEachEntry(map: Map, callback: (value: T, key: string) => U | undefined): U | undefined; - export function forEachEntry(map: EscapedIdentifierMap | Map, callback: (value: T, key: (string & EscapedIdentifier)) => U | undefined): U | undefined { + export function forEachEntry(map: UnderscoreEscapedMap | Map, callback: (value: T, key: (string & UnderscoreEscapedString)) => U | undefined): U | undefined { const iterator = map.entries(); for (let { value: pair, done } = iterator.next(); !done; { value: pair, done } = iterator.next()) { const [key, value] = pair; - const result = callback(value, key as (string & EscapedIdentifier)); + const result = callback(value, key as (string & UnderscoreEscapedString)); if (result) { return result; } @@ -1031,12 +1031,12 @@ namespace ts { } /** `forEachEntry` for just keys. */ - export function forEachKey(map: EscapedIdentifierMap<{}>, callback: (key: EscapedIdentifier) => T | undefined): T | undefined; + export function forEachKey(map: UnderscoreEscapedMap<{}>, callback: (key: UnderscoreEscapedString) => T | undefined): T | undefined; export function forEachKey(map: Map<{}>, callback: (key: string) => T | undefined): T | undefined; - export function forEachKey(map: EscapedIdentifierMap<{}> | Map<{}>, callback: (key: string & EscapedIdentifier) => T | undefined): T | undefined { + export function forEachKey(map: UnderscoreEscapedMap<{}> | Map<{}>, callback: (key: string & UnderscoreEscapedString) => T | undefined): T | undefined { const iterator = map.keys(); for (let { value: key, done } = iterator.next(); !done; { value: key, done } = iterator.next()) { - const result = callback(key as string & EscapedIdentifier); + const result = callback(key as string & UnderscoreEscapedString); if (result) { return result; } @@ -1045,9 +1045,9 @@ namespace ts { } /** Copy entries from `source` to `target`. */ - export function copyEntries(source: EscapedIdentifierMap, target: EscapedIdentifierMap): void; + export function copyEntries(source: UnderscoreEscapedMap, target: UnderscoreEscapedMap): void; export function copyEntries(source: Map, target: Map): void; - export function copyEntries | Map>(source: U, target: U): void { + export function copyEntries | Map>(source: U, target: U): void { (source as Map).forEach((value, key) => { (target as Map).set(key, value); }); @@ -2296,13 +2296,13 @@ namespace ts { getTokenConstructor(): new (kind: TKind, pos?: number, end?: number) => Token; getIdentifierConstructor(): new (kind: SyntaxKind.Identifier, pos?: number, end?: number) => Identifier; getSourceFileConstructor(): new (kind: SyntaxKind.SourceFile, pos?: number, end?: number) => SourceFile; - getSymbolConstructor(): new (flags: SymbolFlags, name: EscapedIdentifier) => Symbol; + getSymbolConstructor(): new (flags: SymbolFlags, name: UnderscoreEscapedString) => Symbol; getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type; getSignatureConstructor(): new (checker: TypeChecker) => Signature; getSourceMapSourceConstructor(): new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource; } - function Symbol(this: Symbol, flags: SymbolFlags, name: EscapedIdentifier) { + function Symbol(this: Symbol, flags: SymbolFlags, name: UnderscoreEscapedString) { this.flags = flags; this.name = name; this.declarations = undefined; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 2fe27c3980fcd..ff1ce72692e62 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2761,7 +2761,7 @@ namespace ts { return generateName(node); } else if (isIdentifier(node) && (nodeIsSynthesized(node) || !node.parent)) { - return unescapeIdentifier(node.text); + return unescapeLeadingUnderscores(node.text); } else if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { return getTextOfNode((node).textSourceNode, includeTrivia); @@ -2843,7 +2843,7 @@ namespace ts { function isUniqueLocalName(name: string, container: Node): boolean { for (let node = container; isNodeDescendantOf(node, container); node = node.nextContainer) { if (node.locals) { - const local = node.locals.get(escapeIdentifier(name)); + const local = node.locals.get(escapeLeadingUnderscores(name)); // We conservatively include alias symbols to cover cases where they're emitted as locals if (local && local.flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) { return false; @@ -2981,7 +2981,7 @@ namespace ts { case GeneratedIdentifierKind.Loop: return makeTempVariableName(TempFlags._i); case GeneratedIdentifierKind.Unique: - return makeUniqueName(unescapeIdentifier(name.text)); + return makeUniqueName(unescapeLeadingUnderscores(name.text)); } Debug.fail("Unsupported GeneratedIdentifierKind."); diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 35388b8af2264..af009047bd4f3 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -112,7 +112,7 @@ namespace ts { export function createIdentifier(text: string, typeArguments: TypeNode[]): Identifier; export function createIdentifier(text: string, typeArguments?: TypeNode[]): Identifier { const node = createSynthesizedNode(SyntaxKind.Identifier); - node.text = escapeIdentifier(text); + node.text = escapeLeadingUnderscores(text); node.originalKeywordKind = text ? stringToToken(text) : SyntaxKind.Unknown; node.autoGenerateKind = GeneratedIdentifierKind.None; node.autoGenerateId = 0; @@ -124,7 +124,7 @@ namespace ts { export function updateIdentifier(node: Identifier, typeArguments: NodeArray | undefined): Identifier { return node.typeArguments !== typeArguments - ? updateNode(createIdentifier(unescapeIdentifier(node.text), typeArguments), node) + ? updateNode(createIdentifier(unescapeLeadingUnderscores(node.text), typeArguments), node) : node; } @@ -2643,12 +2643,12 @@ namespace ts { function createJsxFactoryExpressionFromEntityName(jsxFactory: EntityName, parent: JsxOpeningLikeElement): Expression { if (isQualifiedName(jsxFactory)) { const left = createJsxFactoryExpressionFromEntityName(jsxFactory.left, parent); - const right = createIdentifier(unescapeIdentifier(jsxFactory.right.text)); + const right = createIdentifier(unescapeLeadingUnderscores(jsxFactory.right.text)); right.text = jsxFactory.right.text; return createPropertyAccess(left, right); } else { - return createReactNamespace(unescapeIdentifier(jsxFactory.text), parent); + return createReactNamespace(unescapeLeadingUnderscores(jsxFactory.text), parent); } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index bbcc4d96b420d..ed5701aeb95e9 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1178,7 +1178,7 @@ namespace ts { } const result = createNode(kind, scanner.getStartPos()); - (result).text = "" as EscapedIdentifier; + (result).text = "" as UnderscoreEscapedString; return finishNode(result); } @@ -1202,7 +1202,7 @@ namespace ts { if (token() !== SyntaxKind.Identifier) { node.originalKeywordKind = token(); } - node.text = escapeIdentifier(internIdentifier(scanner.getTokenValue())); + node.text = escapeLeadingUnderscores(internIdentifier(scanner.getTokenValue())); nextToken(); return finishNode(node); } @@ -6992,7 +6992,7 @@ namespace ts { const pos = scanner.getTokenPos(); const end = scanner.getTextPos(); const result = createNode(SyntaxKind.Identifier, pos); - result.text = escapeIdentifier(content.substring(pos, end)); + result.text = escapeLeadingUnderscores(content.substring(pos, end)); finishNode(result, end); nextJSDocToken(); diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 1a78a033228e2..b276a68ec5bbf 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -405,7 +405,7 @@ namespace ts { let commonSourceDirectory: string; let diagnosticsProducingTypeChecker: TypeChecker; let noDiagnosticsTypeChecker: TypeChecker; - let classifiableNames: EscapedIdentifierMap; + let classifiableNames: UnderscoreEscapedMap; let modifiedFilePaths: Path[] | undefined; const cachedSemanticDiagnosticsForFile: DiagnosticCache = {}; @@ -580,7 +580,7 @@ namespace ts { if (!classifiableNames) { // Initialize a checker so that all our files are bound. getTypeChecker(); - classifiableNames = createEscapedIdentifierMap(); + classifiableNames = createUnderscoreEscapedMap(); for (const sourceFile of files) { copyEntries(sourceFile.classifiableNames, classifiableNames); diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index 4bc1f936d83d9..eca28ee814bbf 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -415,7 +415,7 @@ namespace ts { return createElementAccess(value, argumentExpression); } else { - const name = createIdentifier(unescapeIdentifier(propertyName.text)); + const name = createIdentifier(unescapeLeadingUnderscores(propertyName.text)); return createPropertyAccess(value, name); } } diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index d25ffef1a4b6a..2ad133880ea51 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -661,7 +661,7 @@ namespace ts { // - break/continue is non-labeled and located in non-converted loop/switch statement const jump = node.kind === SyntaxKind.BreakStatement ? Jump.Break : Jump.Continue; const canUseBreakOrContinue = - (node.label && convertedLoopState.labels && convertedLoopState.labels.get(unescapeIdentifier(node.label.text))) || + (node.label && convertedLoopState.labels && convertedLoopState.labels.get(unescapeLeadingUnderscores(node.label.text))) || (!node.label && (convertedLoopState.allowedNonLabeledJumps & jump)); if (!canUseBreakOrContinue) { @@ -680,11 +680,11 @@ namespace ts { else { if (node.kind === SyntaxKind.BreakStatement) { labelMarker = `break-${node.label.text}`; - setLabeledJump(convertedLoopState, /*isBreak*/ true, unescapeIdentifier(node.label.text), labelMarker); + setLabeledJump(convertedLoopState, /*isBreak*/ true, unescapeLeadingUnderscores(node.label.text), labelMarker); } else { labelMarker = `continue-${node.label.text}`; - setLabeledJump(convertedLoopState, /*isBreak*/ false, unescapeIdentifier(node.label.text), labelMarker); + setLabeledJump(convertedLoopState, /*isBreak*/ false, unescapeLeadingUnderscores(node.label.text), labelMarker); } } let returnExpression: Expression = createLiteral(labelMarker); @@ -2236,11 +2236,11 @@ namespace ts { } function recordLabel(node: LabeledStatement) { - convertedLoopState.labels.set(unescapeIdentifier(node.label.text), unescapeIdentifier(node.label.text)); + convertedLoopState.labels.set(unescapeLeadingUnderscores(node.label.text), unescapeLeadingUnderscores(node.label.text)); } function resetLabel(node: LabeledStatement) { - convertedLoopState.labels.set(unescapeIdentifier(node.label.text), undefined); + convertedLoopState.labels.set(unescapeLeadingUnderscores(node.label.text), undefined); } function visitLabeledStatement(node: LabeledStatement): VisitResult { @@ -3053,7 +3053,7 @@ namespace ts { else { loopParameters.push(createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name)); if (resolver.getNodeCheckFlags(decl) & NodeCheckFlags.NeedsLoopOutParameter) { - const outParamName = createUniqueName("out_" + unescapeIdentifier(name.text)); + const outParamName = createUniqueName("out_" + unescapeLeadingUnderscores(name.text)); loopOutParameters.push({ originalName: name, outParamName }); } } diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index d2fc430de830c..79d0b57e7644f 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -369,7 +369,7 @@ namespace ts { function substitutePropertyAccessExpression(node: PropertyAccessExpression) { if (node.expression.kind === SyntaxKind.SuperKeyword) { return createSuperAccessInAsyncMethod( - createLiteral(unescapeIdentifier(node.name.text)), + createLiteral(unescapeLeadingUnderscores(node.name.text)), node ); } diff --git a/src/compiler/transformers/es5.ts b/src/compiler/transformers/es5.ts index 4cc5840cbc8e9..0fad92675870b 100644 --- a/src/compiler/transformers/es5.ts +++ b/src/compiler/transformers/es5.ts @@ -111,7 +111,7 @@ namespace ts { * @param name An Identifier */ function trySubstituteReservedName(name: Identifier) { - const token = name.originalKeywordKind || (nodeIsSynthesized(name) ? stringToToken(unescapeIdentifier(name.text)) : undefined); + const token = name.originalKeywordKind || (nodeIsSynthesized(name) ? stringToToken(unescapeLeadingUnderscores(name.text)) : undefined); if (token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord) { return setTextRange(createLiteral(name), name); } diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index ea9e07a6e0422..0b332c237f75e 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -776,7 +776,7 @@ namespace ts { function substitutePropertyAccessExpression(node: PropertyAccessExpression) { if (node.expression.kind === SyntaxKind.SuperKeyword) { return createSuperAccessInAsyncMethod( - createLiteral(unescapeIdentifier(node.name.text)), + createLiteral(unescapeLeadingUnderscores(node.name.text)), node ); } diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 31e2cf7bab135..ee03d57983cbf 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -1635,14 +1635,14 @@ namespace ts { } function transformAndEmitContinueStatement(node: ContinueStatement): void { - const label = findContinueTarget(node.label ? unescapeIdentifier(node.label.text) : undefined); + const label = findContinueTarget(node.label ? unescapeLeadingUnderscores(node.label.text) : undefined); Debug.assert(label > 0, "Expected continue statment to point to a valid Label."); emitBreak(label, /*location*/ node); } function visitContinueStatement(node: ContinueStatement): Statement { if (inStatementContainingYield) { - const label = findContinueTarget(node.label && unescapeIdentifier(node.label.text)); + const label = findContinueTarget(node.label && unescapeLeadingUnderscores(node.label.text)); if (label > 0) { return createInlineBreak(label, /*location*/ node); } @@ -1652,14 +1652,14 @@ namespace ts { } function transformAndEmitBreakStatement(node: BreakStatement): void { - const label = findBreakTarget(node.label ? unescapeIdentifier(node.label.text) : undefined); + const label = findBreakTarget(node.label ? unescapeLeadingUnderscores(node.label.text) : undefined); Debug.assert(label > 0, "Expected break statment to point to a valid Label."); emitBreak(label, /*location*/ node); } function visitBreakStatement(node: BreakStatement): Statement { if (inStatementContainingYield) { - const label = findBreakTarget(node.label && unescapeIdentifier(node.label.text)); + const label = findBreakTarget(node.label && unescapeLeadingUnderscores(node.label.text)); if (label > 0) { return createInlineBreak(label, /*location*/ node); } @@ -1838,7 +1838,7 @@ namespace ts { // /*body*/ // .endlabeled // .mark endLabel - beginLabeledBlock(unescapeIdentifier(node.label.text)); + beginLabeledBlock(unescapeLeadingUnderscores(node.label.text)); transformAndEmitEmbeddedStatement(node.statement); endLabeledBlock(); } @@ -1849,7 +1849,7 @@ namespace ts { function visitLabeledStatement(node: LabeledStatement) { if (inStatementContainingYield) { - beginScriptLabeledBlock(unescapeIdentifier(node.label.text)); + beginScriptLabeledBlock(unescapeLeadingUnderscores(node.label.text)); } node = visitEachChild(node, visitor, context); @@ -1950,7 +1950,7 @@ namespace ts { } function substituteExpressionIdentifier(node: Identifier) { - if (!isGeneratedIdentifier(node) && renamedCatchVariables && renamedCatchVariables.has(unescapeIdentifier(node.text))) { + if (!isGeneratedIdentifier(node) && renamedCatchVariables && renamedCatchVariables.has(unescapeLeadingUnderscores(node.text))) { const original = getOriginalNode(node); if (isIdentifier(original) && original.parent) { const declaration = resolver.getReferencedValueDeclaration(original); @@ -2123,7 +2123,7 @@ namespace ts { hoistVariableDeclaration(variable.name); } else { - const text = unescapeIdentifier((variable.name).text); + const text = unescapeLeadingUnderscores((variable.name).text); name = declareLocal(text); if (!renamedCatchVariables) { renamedCatchVariables = createMap(); diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index 2d3a228e4c58f..eab5f69bd4f23 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -253,7 +253,7 @@ namespace ts { else { const name = (node).tagName; if (isIdentifier(name) && isIntrinsicJsxName(name.text)) { - return createLiteral(unescapeIdentifier(name.text)); + return createLiteral(unescapeLeadingUnderscores(name.text)); } else { return createExpressionFromEntityName(name); @@ -268,11 +268,11 @@ namespace ts { */ function getAttributeName(node: JsxAttribute): StringLiteral | Identifier { const name = node.name; - if (/^[A-Za-z_]\w*$/.test(unescapeIdentifier(name.text))) { + if (/^[A-Za-z_]\w*$/.test(unescapeLeadingUnderscores(name.text))) { return name; } else { - return createLiteral(unescapeIdentifier(name.text)); + return createLiteral(unescapeLeadingUnderscores(name.text)); } } diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 84fef26001ea3..1e73e3a4af6b1 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -1225,7 +1225,7 @@ namespace ts { */ function appendExportsOfDeclaration(statements: Statement[] | undefined, decl: Declaration): Statement[] | undefined { const name = getDeclarationName(decl); - const exportSpecifiers = currentModuleInfo.exportSpecifiers.get(unescapeIdentifier(name.text)); + const exportSpecifiers = currentModuleInfo.exportSpecifiers.get(unescapeLeadingUnderscores(name.text)); if (exportSpecifiers) { for (const exportSpecifier of exportSpecifiers) { statements = appendExportStatement(statements, exportSpecifier.name, name, /*location*/ exportSpecifier.name); diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 46fcb2d4ba056..42898aba798e4 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -353,7 +353,7 @@ namespace ts { // write name of indirectly exported entry, i.e. 'export {x} from ...' exportedNames.push( createPropertyAssignment( - createLiteral(unescapeIdentifier((element.name || element.propertyName).text)), + createLiteral(unescapeLeadingUnderscores((element.name || element.propertyName).text)), createTrue() ) ); @@ -504,10 +504,10 @@ namespace ts { for (const e of (entry).exportClause.elements) { properties.push( createPropertyAssignment( - createLiteral(unescapeIdentifier(e.name.text)), + createLiteral(unescapeLeadingUnderscores(e.name.text)), createElementAccess( parameterName, - createLiteral(unescapeIdentifier((e.propertyName || e.name).text)) + createLiteral(unescapeLeadingUnderscores((e.propertyName || e.name).text)) ) ) ); @@ -1028,7 +1028,7 @@ namespace ts { let excludeName: string; if (exportSelf) { statements = appendExportStatement(statements, decl.name, getLocalName(decl)); - excludeName = unescapeIdentifier(decl.name.text); + excludeName = unescapeLeadingUnderscores(decl.name.text); } statements = appendExportsOfDeclaration(statements, decl, excludeName); @@ -1080,7 +1080,7 @@ namespace ts { } const name = getDeclarationName(decl); - const exportSpecifiers = moduleInfo.exportSpecifiers.get(unescapeIdentifier(name.text)); + const exportSpecifiers = moduleInfo.exportSpecifiers.get(unescapeLeadingUnderscores(name.text)); if (exportSpecifiers) { for (const exportSpecifier of exportSpecifiers) { if (exportSpecifier.name.text !== excludeName) { diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 7313397579866..1c4c945d29273 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -65,7 +65,7 @@ namespace ts { let currentNamespace: ModuleDeclaration; let currentNamespaceContainerName: Identifier; let currentScope: SourceFile | Block | ModuleBlock | CaseBlock; - let currentScopeFirstDeclarationsOfName: EscapedIdentifierMap; + let currentScopeFirstDeclarationsOfName: UnderscoreEscapedMap; /** * Keeps track of whether expression substitution has been enabled for specific edge cases. @@ -2007,7 +2007,7 @@ namespace ts { : (name).expression; } else if (isIdentifier(name)) { - return createLiteral(unescapeIdentifier(name.text)); + return createLiteral(unescapeLeadingUnderscores(name.text)); } else { return getSynthesizedClone(name); @@ -2647,7 +2647,7 @@ namespace ts { const name = node.symbol && node.symbol.name; if (name) { if (!currentScopeFirstDeclarationsOfName) { - currentScopeFirstDeclarationsOfName = createEscapedIdentifierMap(); + currentScopeFirstDeclarationsOfName = createUnderscoreEscapedMap(); } if (!currentScopeFirstDeclarationsOfName.has(name)) { @@ -3210,7 +3210,7 @@ namespace ts { function getClassAliasIfNeeded(node: ClassDeclaration) { if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference) { enableSubstitutionForClassAliases(); - const classAlias = createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? unescapeIdentifier(node.name.text) : "default"); + const classAlias = createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? unescapeLeadingUnderscores(node.name.text) : "default"); classAliases[getOriginalNodeId(node)] = classAlias; hoistVariableDeclaration(classAlias); return classAlias; diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index 32b359525cee4..d3743274d6590 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -58,9 +58,9 @@ namespace ts { else { // export { x, y } for (const specifier of (node).exportClause.elements) { - if (!uniqueExports.get(unescapeIdentifier(specifier.name.text))) { + if (!uniqueExports.get(unescapeLeadingUnderscores(specifier.name.text))) { const name = specifier.propertyName || specifier.name; - exportSpecifiers.add(unescapeIdentifier(name.text), specifier); + exportSpecifiers.add(unescapeLeadingUnderscores(name.text), specifier); const decl = resolver.getReferencedImportDeclaration(name) || resolver.getReferencedValueDeclaration(name); @@ -69,7 +69,7 @@ namespace ts { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(decl), specifier.name); } - uniqueExports.set(unescapeIdentifier(specifier.name.text), true); + uniqueExports.set(unescapeLeadingUnderscores(specifier.name.text), true); exportedNames = append(exportedNames, specifier.name); } } @@ -103,9 +103,9 @@ namespace ts { else { // export function x() { } const name = (node).name; - if (!uniqueExports.get(unescapeIdentifier(name.text))) { + if (!uniqueExports.get(unescapeLeadingUnderscores(name.text))) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name); - uniqueExports.set(unescapeIdentifier(name.text), true); + uniqueExports.set(unescapeLeadingUnderscores(name.text), true); exportedNames = append(exportedNames, name); } } @@ -124,9 +124,9 @@ namespace ts { else { // export class x { } const name = (node).name; - if (!uniqueExports.get(unescapeIdentifier(name.text))) { + if (!uniqueExports.get(unescapeLeadingUnderscores(name.text))) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name); - uniqueExports.set(unescapeIdentifier(name.text), true); + uniqueExports.set(unescapeLeadingUnderscores(name.text), true); exportedNames = append(exportedNames, name); } } @@ -158,8 +158,8 @@ namespace ts { } } else if (!isGeneratedIdentifier(decl.name)) { - if (!uniqueExports.get(unescapeIdentifier(decl.name.text))) { - uniqueExports.set(unescapeIdentifier(decl.name.text), true); + if (!uniqueExports.get(unescapeLeadingUnderscores(decl.name.text))) { + uniqueExports.set(unescapeLeadingUnderscores(decl.name.text), true); exportedNames = append(exportedNames, decl.name); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 15d3ef1848c2a..cba1c48b2239b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -589,7 +589,7 @@ namespace ts { * Text of identifier (with escapes converted to characters). * If the identifier begins with two underscores, this will begin with three. */ - text: EscapedIdentifier; + text: UnderscoreEscapedString; originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later /*@internal*/ autoGenerateKind?: GeneratedIdentifierKind; // Specifies whether to auto-generate the text for an identifier. /*@internal*/ autoGenerateId?: number; // Ensures unique generated identifiers get unique names, but clones get the same name. @@ -2357,7 +2357,7 @@ namespace ts { // Stores a line map for the file. // This field should never be used directly to obtain line map, use getLineMap function instead. /* @internal */ lineMap: number[]; - /* @internal */ classifiableNames?: EscapedIdentifierMap; + /* @internal */ classifiableNames?: UnderscoreEscapedMap; // Stores a mapping 'external module reference text' -> 'resolved file name' | undefined // It is used to resolve module names in the checker. // Content of this field should never be used directly - use getResolvedModuleFileName/setResolvedModuleFileName functions instead @@ -2463,7 +2463,7 @@ namespace ts { /* @internal */ getDiagnosticsProducingTypeChecker(): TypeChecker; /* @internal */ dropDiagnosticsProducingTypeChecker(): void; - /* @internal */ getClassifiableNames(): EscapedIdentifierMap; + /* @internal */ getClassifiableNames(): UnderscoreEscapedMap; /* @internal */ getNodeCount(): number; /* @internal */ getIdentifierCount(): number; @@ -2937,7 +2937,7 @@ namespace ts { export interface Symbol { flags: SymbolFlags; // Symbol flags - name: EscapedIdentifier; // Name of symbol + name: UnderscoreEscapedString; // Name of symbol declarations?: Declaration[]; // Declarations associated with this symbol valueDeclaration?: Declaration; // First value declaration of the symbol members?: SymbolTable; // Class, interface or literal instance members @@ -3005,24 +3005,24 @@ namespace ts { isRestParameter?: boolean; } - export type EscapedIdentifier = (string & { __escapedIdentifier: void }) | (void & { __escapedIdentifier: void }); + export type UnderscoreEscapedString = (string & { __escapedIdentifier: void }) | (void & { __escapedIdentifier: void }); /** EscapedStringMap based on ES6 Map interface. */ - export interface EscapedIdentifierMap { - get(key: EscapedIdentifier): T | undefined; - has(key: EscapedIdentifier): boolean; - set(key: EscapedIdentifier, value: T): this; - delete(key: EscapedIdentifier): boolean; + export interface UnderscoreEscapedMap { + get(key: UnderscoreEscapedString): T | undefined; + has(key: UnderscoreEscapedString): boolean; + set(key: UnderscoreEscapedString, value: T): this; + delete(key: UnderscoreEscapedString): boolean; clear(): void; - forEach(action: (value: T, key: EscapedIdentifier) => void): void; + forEach(action: (value: T, key: UnderscoreEscapedString) => void): void; readonly size: number; - keys(): Iterator; + keys(): Iterator; values(): Iterator; - entries(): Iterator<[EscapedIdentifier, T]>; + entries(): Iterator<[UnderscoreEscapedString, T]>; } /** SymbolTable based on ES6 Map interface. */ - export type SymbolTable = EscapedIdentifierMap; + export type SymbolTable = UnderscoreEscapedMap; /** Represents a "prefix*suffix" pattern. */ /* @internal */ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index aad502b5519d7..84ead689e1ef7 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -351,8 +351,8 @@ namespace ts { } // Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__' - export function escapeIdentifier(identifier: string): EscapedIdentifier { - return (identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier) as EscapedIdentifier; + export function escapeLeadingUnderscores(identifier: string): UnderscoreEscapedString { + return (identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier) as UnderscoreEscapedString; } // Make an identifier from an external module name by extracting the string after the last "/" and replacing @@ -467,16 +467,16 @@ namespace ts { return info.declaration ? declarationNameToString(info.declaration.parameters[0].name) : undefined; } - export function getTextOfPropertyName(name: PropertyName): EscapedIdentifier { + export function getTextOfPropertyName(name: PropertyName): UnderscoreEscapedString { switch (name.kind) { case SyntaxKind.Identifier: return (name).text; case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: - return (name).text as EscapedIdentifier; + return (name).text as UnderscoreEscapedString; case SyntaxKind.ComputedPropertyName: if (isStringOrNumericLiteral((name).expression)) { - return ((name).expression).text as EscapedIdentifier; + return ((name).expression).text as UnderscoreEscapedString; } } @@ -486,7 +486,7 @@ namespace ts { export function entityNameToString(name: EntityNameOrEntityNameExpression): string { switch (name.kind) { case SyntaxKind.Identifier: - return getFullWidth(name) === 0 ? unescapeIdentifier(name.text) : getTextOfNode(name); + return getFullWidth(name) === 0 ? unescapeLeadingUnderscores(name.text) : getTextOfNode(name); case SyntaxKind.QualifiedName: return entityNameToString(name.left) + "." + entityNameToString(name.right); case SyntaxKind.PropertyAccessExpression: @@ -1959,21 +1959,21 @@ namespace ts { return isPropertyAccessExpression(node) && isESSymbolIdentifier(node.expression); } - export function getPropertyNameForPropertyNameNode(name: DeclarationName): EscapedIdentifier { + export function getPropertyNameForPropertyNameNode(name: DeclarationName): UnderscoreEscapedString { if (name.kind === SyntaxKind.Identifier) { return name.text; } if (name.kind === SyntaxKind.StringLiteral || name.kind === SyntaxKind.NumericLiteral) { - return escapeIdentifier(name.text); + return escapeLeadingUnderscores(name.text); } if (name.kind === SyntaxKind.ComputedPropertyName) { const nameExpression = name.expression; if (isWellKnownSymbolSyntactically(nameExpression)) { const rightHandSideName = (nameExpression).name.text; - return getPropertyNameForKnownSymbolName(unescapeIdentifier(rightHandSideName)); + return getPropertyNameForKnownSymbolName(unescapeLeadingUnderscores(rightHandSideName)); } else if (nameExpression.kind === SyntaxKind.StringLiteral || nameExpression.kind === SyntaxKind.NumericLiteral) { - return escapeIdentifier((nameExpression).text); + return escapeLeadingUnderscores((nameExpression).text); } } @@ -1983,7 +1983,7 @@ namespace ts { export function getTextOfIdentifierOrLiteral(node: Identifier | LiteralLikeNode) { if (node) { if (node.kind === SyntaxKind.Identifier) { - return unescapeIdentifier((node as Identifier).text); + return unescapeLeadingUnderscores((node as Identifier).text); } if (node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NumericLiteral) { @@ -2003,15 +2003,15 @@ namespace ts { if (node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NumericLiteral) { - return escapeIdentifier((node as LiteralLikeNode).text); + return escapeLeadingUnderscores((node as LiteralLikeNode).text); } } return undefined; } - export function getPropertyNameForKnownSymbolName(symbolName: string): EscapedIdentifier { - return "__@" + symbolName as EscapedIdentifier; + export function getPropertyNameForKnownSymbolName(symbolName: string): UnderscoreEscapedString { + return "__@" + symbolName as UnderscoreEscapedString; } /** @@ -2377,7 +2377,7 @@ namespace ts { return escapedCharsMap.get(c) || get16BitUnicodeEscapeSequence(c.charCodeAt(0)); } - export function isIntrinsicJsxName(name: EscapedIdentifier | string) { + export function isIntrinsicJsxName(name: UnderscoreEscapedString | string) { // An escaped identifier had a leading underscore prior to being escaped, which would return true // The escape adds an extra underscore which does not change the result const ch = (name as string).substr(0, 1); @@ -4009,7 +4009,7 @@ namespace ts { * @param identifier The escaped identifier text. * @returns The unescaped identifier text. */ - export function unescapeIdentifier(identifier: EscapedIdentifier): string { + export function unescapeLeadingUnderscores(identifier: UnderscoreEscapedString): string { return (identifier as string).length >= 3 && (identifier as string).charCodeAt(0) === CharacterCodes._ && (identifier as string).charCodeAt(1) === CharacterCodes._ && (identifier as string).charCodeAt(2) === CharacterCodes._ ? (identifier as string).substr(1) : identifier as string; } diff --git a/src/services/classifier.ts b/src/services/classifier.ts index ec30fb478bcfb..0309c1d309236 100644 --- a/src/services/classifier.ts +++ b/src/services/classifier.ts @@ -462,7 +462,7 @@ namespace ts { } /* @internal */ - export function getSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: EscapedIdentifierMap, span: TextSpan): ClassifiedSpan[] { + export function getSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: UnderscoreEscapedMap, span: TextSpan): ClassifiedSpan[] { return convertClassifications(getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span)); } @@ -487,7 +487,7 @@ namespace ts { } /* @internal */ - export function getEncodedSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: EscapedIdentifierMap, span: TextSpan): Classifications { + export function getEncodedSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: UnderscoreEscapedMap, span: TextSpan): Classifications { const result: number[] = []; processNode(sourceFile); diff --git a/src/services/completions.ts b/src/services/completions.ts index a2a03f834fa1d..700978f2cf183 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -88,7 +88,7 @@ namespace ts.Completions { if (pos === position) { return; } - const realName = unescapeIdentifier(name); + const realName = unescapeLeadingUnderscores(name); if (!uniqueNames.get(realName)) { uniqueNames.set(realName, realName); @@ -1447,7 +1447,7 @@ namespace ts.Completions { * do not occur at the current position and have not otherwise been typed. */ function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ImportOrExportSpecifier[]): Symbol[] { - const existingImportsOrExports = createEscapedIdentifierMap(); + const existingImportsOrExports = createUnderscoreEscapedMap(); for (const element of namedImportsOrExports) { // If this is the current item we are editing right now, do not filter it out @@ -1477,7 +1477,7 @@ namespace ts.Completions { return contextualMemberSymbols; } - const existingMemberNames = createEscapedIdentifierMap(); + const existingMemberNames = createUnderscoreEscapedMap(); for (const m of existingMembers) { // Ignore omitted expressions for missing members if (m.kind !== SyntaxKind.PropertyAssignment && @@ -1494,7 +1494,7 @@ namespace ts.Completions { continue; } - let existingName: EscapedIdentifier; + let existingName: UnderscoreEscapedString; if (m.kind === SyntaxKind.BindingElement && (m).propertyName) { // include only identifiers in completion list @@ -1522,7 +1522,7 @@ namespace ts.Completions { * @returns Symbols to be suggested in an class element depending on existing memebers and symbol flags */ function filterClassMembersList(baseSymbols: Symbol[], implementingTypeSymbols: Symbol[], existingMembers: ClassElement[], currentClassElementModifierFlags: ModifierFlags): Symbol[] { - const existingMemberNames = createEscapedIdentifierMap(); + const existingMemberNames = createUnderscoreEscapedMap(); for (const m of existingMembers) { // Ignore omitted expressions for missing members if (m.kind !== SyntaxKind.PropertyDeclaration && @@ -1575,7 +1575,7 @@ namespace ts.Completions { * do not occur at the current position and have not otherwise been typed. */ function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray): Symbol[] { - const seenNames = createEscapedIdentifierMap(); + const seenNames = createUnderscoreEscapedMap(); for (const attr of attributes) { // If this is the current item we are editing right now, do not filter it out if (isCurrentlyEditingNode(attr)) { diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index 3d016d5a8d12d..0a2c8e726fc81 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -248,7 +248,7 @@ namespace ts.DocumentHighlights { case SyntaxKind.ForOfStatement: case SyntaxKind.WhileStatement: case SyntaxKind.DoStatement: - if (!statement.label || isLabeledBy(node, unescapeIdentifier(statement.label.text))) { + if (!statement.label || isLabeledBy(node, unescapeLeadingUnderscores(statement.label.text))) { return node; } break; diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 1a55add0d1140..94ddc7ebeda63 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -122,7 +122,7 @@ namespace ts.FindAllReferences { } case "label": { const { node } = def; - return { node, name: unescapeIdentifier(node.text), kind: ScriptElementKind.label, displayParts: [displayPart(unescapeIdentifier(node.text), SymbolDisplayPartKind.text)] }; + return { node, name: unescapeLeadingUnderscores(node.text), kind: ScriptElementKind.label, displayParts: [displayPart(unescapeLeadingUnderscores(node.text), SymbolDisplayPartKind.text)] }; } case "keyword": { const { node } = def; @@ -357,7 +357,7 @@ namespace ts.FindAllReferences.Core { // Labels if (isLabelName(node)) { if (isJumpStatementTarget(node)) { - const labelDefinition = getTargetLabel((node.parent), unescapeIdentifier((node).text)); + const labelDefinition = getTargetLabel((node.parent), unescapeLeadingUnderscores((node).text)); // if we have a label definition, look within its statement for references, if not, then // the label is undefined and we have no results.. return labelDefinition && getLabelReferencesInNode(labelDefinition.parent, labelDefinition); @@ -432,7 +432,7 @@ namespace ts.FindAllReferences.Core { readonly location: Node; readonly symbol: Symbol; readonly text: string; - readonly escapedText: EscapedIdentifier; + readonly escapedText: UnderscoreEscapedString; /** Only set if `options.implementations` is true. These are the symbols checked to get the implementations of a property access. */ readonly parents: Symbol[] | undefined; @@ -494,7 +494,7 @@ namespace ts.FindAllReferences.Core { createSearch(location: Node, symbol: Symbol, comingFrom: ImportExport | undefined, searchOptions: { text?: string, allSearchSymbols?: Symbol[] } = {}): Search { // Note: if this is an external module symbol, the name doesn't include quotes. const { text = stripQuotes(getDeclaredName(this.checker, symbol, location)), allSearchSymbols = undefined } = searchOptions; - const escapedText = escapeIdentifier(text); + const escapedText = escapeLeadingUnderscores(text); const parents = this.options.implementations && getParentSymbolsOfPropertyAccess(location, symbol, this.checker); return { location, symbol, comingFrom, text, escapedText, parents, @@ -604,7 +604,7 @@ namespace ts.FindAllReferences.Core { if (isObjectBindingPatternElementWithoutPropertyName(symbol)) { const bindingElement = getDeclarationOfKind(symbol, SyntaxKind.BindingElement); const typeOfPattern = checker.getTypeAtLocation(bindingElement.parent); - return typeOfPattern && checker.getPropertyOfType(typeOfPattern, unescapeIdentifier((bindingElement.name).text)); + return typeOfPattern && checker.getPropertyOfType(typeOfPattern, unescapeLeadingUnderscores((bindingElement.name).text)); } return undefined; } @@ -716,7 +716,7 @@ namespace ts.FindAllReferences.Core { function getLabelReferencesInNode(container: Node, targetLabel: Identifier): SymbolAndEntries[] { const references: Entry[] = []; const sourceFile = container.getSourceFile(); - const labelName = unescapeIdentifier(targetLabel.text); + const labelName = unescapeLeadingUnderscores(targetLabel.text); const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container); for (const position of possiblePositions) { const node = getTouchingWord(sourceFile, position, /*includeJsDocComment*/ false); @@ -733,7 +733,7 @@ namespace ts.FindAllReferences.Core { // Compare the length so we filter out strict superstrings of the symbol we are looking for switch (node && node.kind) { case SyntaxKind.Identifier: - return unescapeIdentifier((node as Identifier).text).length === searchSymbolName.length; + return unescapeLeadingUnderscores((node as Identifier).text).length === searchSymbolName.length; case SyntaxKind.StringLiteral: return (isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) && @@ -977,7 +977,7 @@ namespace ts.FindAllReferences.Core { * Reference the constructor and all calls to `new this()`. */ function findOwnConstructorReferences(classSymbol: Symbol, sourceFile: SourceFile, addNode: (node: Node) => void): void { - for (const decl of classSymbol.members.get("__constructor" as EscapedIdentifier).declarations) { + for (const decl of classSymbol.members.get("__constructor" as UnderscoreEscapedString).declarations) { const ctrKeyword = ts.findChildOfKind(decl, ts.SyntaxKind.ConstructorKeyword, sourceFile)!; Debug.assert(decl.kind === SyntaxKind.Constructor && !!ctrKeyword); addNode(ctrKeyword); @@ -1001,7 +1001,7 @@ namespace ts.FindAllReferences.Core { /** Find references to `super` in the constructor of an extending class. */ function findSuperConstructorAccesses(cls: ClassLikeDeclaration, addNode: (node: Node) => void): void { const symbol = cls.symbol; - const ctr = symbol.members.get("__constructor" as EscapedIdentifier); + const ctr = symbol.members.get("__constructor" as UnderscoreEscapedString); if (!ctr) { return; } diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index bc0e7d106c4bf..36a8a4dd613dc 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -26,7 +26,7 @@ namespace ts.GoToDefinition { // Labels if (isJumpStatementTarget(node)) { - const labelName = unescapeIdentifier((node).text); + const labelName = unescapeLeadingUnderscores((node).text); const label = getTargetLabel((node.parent), labelName); return label ? [createDefinitionInfoFromName(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; } diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index 1405bcffe82de..2c7750a42b911 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -602,10 +602,10 @@ namespace ts.FindAllReferences { return forEach(symbol.declarations, decl => { if (isExportAssignment(decl)) { - return isIdentifier(decl.expression) ? unescapeIdentifier(decl.expression.text) : undefined; + return isIdentifier(decl.expression) ? unescapeLeadingUnderscores(decl.expression.text) : undefined; } const name = getNameOfDeclaration(decl); - return name && name.kind === SyntaxKind.Identifier && unescapeIdentifier(name.text); + return name && name.kind === SyntaxKind.Identifier && unescapeLeadingUnderscores(name.text); }); } diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index 6acd3b106704a..63b103097aab6 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -82,7 +82,7 @@ namespace ts.JsDoc { if (tagsForDoc) { tags.push(...tagsForDoc.filter(tag => tag.kind === SyntaxKind.JSDocTag).map(jsDocTag => { return { - name: unescapeIdentifier(jsDocTag.tagName.text), + name: unescapeLeadingUnderscores(jsDocTag.tagName.text), text: jsDocTag.comment }; })); } @@ -133,7 +133,7 @@ namespace ts.JsDoc { } export function getJSDocParameterNameCompletions(tag: JSDocParameterTag): CompletionEntry[] { - const nameThusFar = unescapeIdentifier(tag.name.text); + const nameThusFar = unescapeLeadingUnderscores(tag.name.text); const jsdoc = tag.parent; const fn = jsdoc.parent; if (!ts.isFunctionLike(fn)) return []; @@ -141,7 +141,7 @@ namespace ts.JsDoc { return mapDefined(fn.parameters, param => { if (!isIdentifier(param.name)) return undefined; - const name = unescapeIdentifier(param.name.text); + const name = unescapeLeadingUnderscores(param.name.text); if (jsdoc.tags.some(t => t !== tag && isJSDocParameterTag(t) && t.name.text === name) || nameThusFar !== undefined && !startsWith(name, nameThusFar)) { return undefined; diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index 470b422c8c7d9..f8a0d96806e77 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -119,7 +119,7 @@ namespace ts.NavigateTo { if (expression.kind === SyntaxKind.PropertyAccessExpression) { const propertyAccess = expression; if (includeLastPortion) { - containers.unshift(unescapeIdentifier(propertyAccess.name.text)); + containers.unshift(unescapeLeadingUnderscores(propertyAccess.name.text)); } return tryAddComputedPropertyName(propertyAccess.expression, containers, /*includeLastPortion*/ true); @@ -191,7 +191,7 @@ namespace ts.NavigateTo { fileName: rawItem.fileName, textSpan: createTextSpanFromNode(declaration), // TODO(jfreeman): What should be the containerName when the container has a computed name? - containerName: containerName ? unescapeIdentifier((containerName).text) : "", + containerName: containerName ? unescapeLeadingUnderscores((containerName).text) : "", containerKind: containerName ? getNodeKind(container) : ScriptElementKind.unknown }; } diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 26b681d0c1785..6720225f12517 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -380,7 +380,7 @@ namespace ts.NavigationBar { const declName = getNameOfDeclaration(node); if (declName) { - return unescapeIdentifier(getPropertyNameForPropertyNameNode(declName)); + return unescapeLeadingUnderscores(getPropertyNameForPropertyNameNode(declName)); } switch (node.kind) { case SyntaxKind.FunctionExpression: @@ -442,7 +442,7 @@ namespace ts.NavigationBar { function getJSDocTypedefTagName(node: JSDocTypedefTag): string { if (node.name) { - return unescapeIdentifier(node.name.text); + return unescapeLeadingUnderscores(node.name.text); } else { const parentNode = node.parent && node.parent.parent; @@ -450,7 +450,7 @@ namespace ts.NavigationBar { if ((parentNode).declarationList.declarations.length > 0) { const nameIdentifier = (parentNode).declarationList.declarations[0].name; if (nameIdentifier.kind === SyntaxKind.Identifier) { - return unescapeIdentifier((nameIdentifier).text); + return unescapeLeadingUnderscores((nameIdentifier).text); } } } diff --git a/src/services/pathCompletions.ts b/src/services/pathCompletions.ts index db3235864eaee..bc94fb7dbc5ed 100644 --- a/src/services/pathCompletions.ts +++ b/src/services/pathCompletions.ts @@ -244,7 +244,7 @@ namespace ts.Completions.PathCompletions { const moduleNameFragment = isNestedModule ? fragment.substr(0, fragment.lastIndexOf(directorySeparator)) : undefined; // Get modules that the type checker picked up - const ambientModules = map(typeChecker.getAmbientModules(), sym => stripQuotes(unescapeIdentifier(sym.name))); + const ambientModules = map(typeChecker.getAmbientModules(), sym => stripQuotes(unescapeLeadingUnderscores(sym.name))); let nonRelativeModuleNames = filter(ambientModules, moduleName => startsWith(moduleName, fragment)); // Nested modules of the form "module-name/sub" need to be adjusted to only return the string diff --git a/src/services/services.ts b/src/services/services.ts index 9bf68f629d379..9c462c32377c5 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -304,7 +304,7 @@ namespace ts { class SymbolObject implements Symbol { flags: SymbolFlags; - name: EscapedIdentifier; + name: UnderscoreEscapedString; declarations?: Declaration[]; // Undefined is used to indicate the value has not been computed. If, after computing, the @@ -315,7 +315,7 @@ namespace ts { // symbol has no JSDoc tags, then the empty array will be returned. tags?: JSDocTagInfo[]; - constructor(flags: SymbolFlags, name: EscapedIdentifier) { + constructor(flags: SymbolFlags, name: UnderscoreEscapedString) { this.flags = flags; this.name = name; } @@ -325,7 +325,7 @@ namespace ts { } getName(): string { - return unescapeIdentifier(this.name); + return unescapeLeadingUnderscores(this.name); } getDeclarations(): Declaration[] | undefined { @@ -360,7 +360,7 @@ namespace ts { class IdentifierObject extends TokenOrIdentifierObject implements Identifier { public kind: SyntaxKind.Identifier; - public text: EscapedIdentifier; + public text: UnderscoreEscapedString; _primaryExpressionBrand: any; _memberExpressionBrand: any; _leftHandSideExpressionBrand: any; @@ -509,7 +509,7 @@ namespace ts { public languageVersion: ScriptTarget; public languageVariant: LanguageVariant; public identifiers: Map; - public nameTable: EscapedIdentifierMap; + public nameTable: UnderscoreEscapedMap; public resolvedModules: Map; public resolvedTypeReferenceDirectiveNames: Map; public imports: StringLiteral[]; @@ -597,7 +597,7 @@ namespace ts { if (name.kind === SyntaxKind.ComputedPropertyName) { const expr = (name).expression; if (expr.kind === SyntaxKind.PropertyAccessExpression) { - return unescapeIdentifier((expr).name.text); + return unescapeLeadingUnderscores((expr).name.text); } return getTextOfIdentifierOrLiteral(expr as (Identifier | LiteralExpression)); @@ -2069,7 +2069,7 @@ namespace ts { /* @internal */ /** Names in the name table are escaped, so an identifier `__foo` will have a name table entry `___foo`. */ - export function getNameTable(sourceFile: SourceFile): EscapedIdentifierMap { + export function getNameTable(sourceFile: SourceFile): UnderscoreEscapedMap { if (!sourceFile.nameTable) { initializeNameTable(sourceFile); } @@ -2078,7 +2078,7 @@ namespace ts { } function initializeNameTable(sourceFile: SourceFile): void { - const nameTable = createEscapedIdentifierMap(); + const nameTable = createUnderscoreEscapedMap(); walk(sourceFile); sourceFile.nameTable = nameTable; @@ -2111,7 +2111,7 @@ namespace ts { } } - function setNameTable(text: EscapedIdentifier, node: ts.Node): void { + function setNameTable(text: UnderscoreEscapedString, node: ts.Node): void { nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1); } } @@ -2154,7 +2154,7 @@ namespace ts { export function getPropertySymbolsFromContextualType(typeChecker: TypeChecker, node: ObjectLiteralElement): Symbol[] { const objectLiteral = node.parent; const contextualType = typeChecker.getContextualType(objectLiteral); - const name = unescapeIdentifier(getTextOfPropertyName(node.name)); + const name = unescapeLeadingUnderscores(getTextOfPropertyName(node.name)); if (name && contextualType) { const result: Symbol[] = []; const symbol = contextualType.getProperty(name); diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 3c46e056d2f41..f61853b92af44 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -74,7 +74,7 @@ namespace ts.SignatureHelp { const typeChecker = program.getTypeChecker(); for (const sourceFile of program.getSourceFiles()) { const nameToDeclarations = sourceFile.getNamedDeclarations(); - const declarations = nameToDeclarations.get(unescapeIdentifier(name.text)); + const declarations = nameToDeclarations.get(unescapeLeadingUnderscores(name.text)); if (declarations) { for (const declaration of declarations) { diff --git a/src/services/types.ts b/src/services/types.ts index edd22ca05759b..b690d99f47efa 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -56,7 +56,7 @@ namespace ts { export interface SourceFile { /* @internal */ version: string; /* @internal */ scriptSnapshot: IScriptSnapshot; - /* @internal */ nameTable: EscapedIdentifierMap; + /* @internal */ nameTable: UnderscoreEscapedMap; /* @internal */ getNamedDeclarations(): Map; From e0c7dcc130e481ea3b2a601df97dadd38c554e26 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 6 Jul 2017 09:54:31 -0700 Subject: [PATCH 14/25] Make getName() return UnderscoreEscapedString, add getUnescapedName() --- src/services/codefixes/helpers.ts | 2 +- src/services/codefixes/importFixes.ts | 2 +- src/services/completions.ts | 4 ++-- src/services/findAllReferences.ts | 6 +++--- src/services/importTracker.ts | 6 +++--- src/services/refactors/convertFunctionToEs6Class.ts | 2 +- src/services/services.ts | 6 +++++- src/services/signatureHelp.ts | 4 ++-- src/services/types.ts | 3 ++- src/services/utilities.ts | 2 +- 10 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index cbe288cbff6d2..b45d2448a0a7c 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -205,7 +205,7 @@ namespace ts.codefix { } } const maxNonRestArgs = maxArgsSignature.parameters.length - (maxArgsSignature.hasRestParameter ? 1 : 0); - const maxArgsParameterSymbolNames = maxArgsSignature.parameters.map(symbol => symbol.getName()); + const maxArgsParameterSymbolNames = maxArgsSignature.parameters.map(symbol => symbol.getUnescapedName()); const parameters = createDummyParameters(maxNonRestArgs, maxArgsParameterSymbolNames, minArgumentCount, /*addAnyType*/ true); diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 0bf99c130981e..0fa0b72162b71 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -148,7 +148,7 @@ namespace ts.codefix { else if (isJsxOpeningLikeElement(token.parent) && token.parent.tagName === token) { // The error wasn't for the symbolAtLocation, it was for the JSX tag itself, which needs access to e.g. `React`. symbol = checker.getAliasedSymbol(checker.resolveNameAtLocation(token, checker.getJsxNamespace(), SymbolFlags.Value)); - symbolName = symbol.getName(); + symbolName = symbol.getUnescapedName(); } else { Debug.fail("Either the symbol or the JSX namespace should be a UMD global if we got here"); diff --git a/src/services/completions.ts b/src/services/completions.ts index 700978f2cf183..ff4061b02aea1 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -614,7 +614,7 @@ namespace ts.Completions { if (symbol && symbol.flags & SymbolFlags.HasExports) { // Extract module or enum members const exportedSymbols = typeChecker.getExportsOfModule(symbol); - const isValidValueAccess = (symbol: Symbol) => typeChecker.isValidPropertyAccess((node.parent), symbol.getName()); + const isValidValueAccess = (symbol: Symbol) => typeChecker.isValidPropertyAccess((node.parent), symbol.getUnescapedName()); const isValidTypeAccess = (symbol: Symbol) => symbolCanbeReferencedAtTypeLocation(symbol); const isValidAccess = isRhsOfImportDeclaration ? // Any kind is allowed when dotting off namespace in internal import equals declaration @@ -638,7 +638,7 @@ namespace ts.Completions { if (type) { // Filter private properties for (const symbol of type.getApparentProperties()) { - if (typeChecker.isValidPropertyAccess((node.parent), symbol.getName())) { + if (typeChecker.isValidPropertyAccess((node.parent), symbol.getUnescapedName())) { symbols.push(symbol); } } diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 94ddc7ebeda63..7f67661df4b59 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -1414,7 +1414,7 @@ namespace ts.FindAllReferences.Core { // Property Declaration symbol is a member of the class, so the symbol is stored in its class Declaration.symbol.members if (symbol.valueDeclaration && symbol.valueDeclaration.kind === SyntaxKind.Parameter && isParameterPropertyDeclaration(symbol.valueDeclaration)) { - addRange(result, checker.getSymbolsOfParameterPropertyDeclaration(symbol.valueDeclaration, symbol.getName())); + addRange(result, checker.getSymbolsOfParameterPropertyDeclaration(symbol.valueDeclaration, symbol.getUnescapedName())); } // If this is symbol of binding element without propertyName declaration in Object binding pattern @@ -1433,7 +1433,7 @@ namespace ts.FindAllReferences.Core { // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions if (!implementations && rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { - getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ createSymbolTable(), checker); + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getUnescapedName(), result, /*previousIterationSymbolsCache*/ createSymbolTable(), checker); } } @@ -1551,7 +1551,7 @@ namespace ts.FindAllReferences.Core { } const result: Symbol[] = []; - getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ createSymbolTable(), state.checker); + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getUnescapedName(), result, /*previousIterationSymbolsCache*/ createSymbolTable(), state.checker); return find(result, search.includes); } diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index 2c7750a42b911..deaec5a505942 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -595,17 +595,17 @@ namespace ts.FindAllReferences { return isExternalModuleSymbol(exportingModuleSymbol) ? { exportingModuleSymbol, exportKind } : undefined; } - function symbolName(symbol: Symbol): string | undefined { + function symbolName(symbol: Symbol): UnderscoreEscapedString | undefined { if (symbol.name !== "default") { return symbol.getName(); } return forEach(symbol.declarations, decl => { if (isExportAssignment(decl)) { - return isIdentifier(decl.expression) ? unescapeLeadingUnderscores(decl.expression.text) : undefined; + return isIdentifier(decl.expression) ? decl.expression.text : undefined; } const name = getNameOfDeclaration(decl); - return name && name.kind === SyntaxKind.Identifier && unescapeLeadingUnderscores(name.text); + return name && name.kind === SyntaxKind.Identifier && name.text; }); } diff --git a/src/services/refactors/convertFunctionToEs6Class.ts b/src/services/refactors/convertFunctionToEs6Class.ts index c15123092dc99..a570ef1f2b86e 100644 --- a/src/services/refactors/convertFunctionToEs6Class.ts +++ b/src/services/refactors/convertFunctionToEs6Class.ts @@ -159,7 +159,7 @@ namespace ts.refactor { deleteNode(nodeToDelete); if (!assignmentBinaryExpression.right) { - return createProperty([], modifiers, symbol.getName(), /*questionToken*/ undefined, + return createProperty([], modifiers, symbol.getUnescapedName(), /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined); } diff --git a/src/services/services.ts b/src/services/services.ts index 9c462c32377c5..f82b82be48fb8 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -324,7 +324,11 @@ namespace ts { return this.flags; } - getName(): string { + getName(): UnderscoreEscapedString { + return this.name; + } + + getUnescapedName(): string { return unescapeLeadingUnderscores(this.name); } diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index f61853b92af44..00ab016580550 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -416,7 +416,7 @@ namespace ts.SignatureHelp { typeChecker.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation)); return { - name: parameter.getName(), + name: parameter.getUnescapedName(), documentation: parameter.getDocumentationComment(), displayParts, isOptional: typeChecker.isOptionalParameter(parameter.valueDeclaration) @@ -428,7 +428,7 @@ namespace ts.SignatureHelp { typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, invocation)); return { - name: typeParameter.symbol.getName(), + name: typeParameter.symbol.getUnescapedName(), documentation: emptyArray, displayParts, isOptional: false diff --git a/src/services/types.ts b/src/services/types.ts index b690d99f47efa..b4a0402536423 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -24,7 +24,8 @@ namespace ts { export interface Symbol { getFlags(): SymbolFlags; - getName(): string; + getName(): UnderscoreEscapedString; + getUnescapedName(): string; getDeclarations(): Declaration[] | undefined; getDocumentationComment(): SymbolDisplayPart[]; getJsDocTags(): JSDocTagInfo[]; diff --git a/src/services/utilities.ts b/src/services/utilities.ts index f29b01c5f88ab..8f231c458975e 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1092,7 +1092,7 @@ namespace ts { /** True if the symbol is for an external module, as opposed to a namespace. */ export function isExternalModuleSymbol(moduleSymbol: Symbol): boolean { Debug.assert(!!(moduleSymbol.flags & SymbolFlags.Module)); - return moduleSymbol.getName().charCodeAt(0) === CharacterCodes.doubleQuote; + return moduleSymbol.getUnescapedName().charCodeAt(0) === CharacterCodes.doubleQuote; } /** Returns `true` the first time it encounters a node and `false` afterwards. */ From 50a8c04d8be8edb5b61a17dee043fd3520afa476 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 6 Jul 2017 10:12:52 -0700 Subject: [PATCH 15/25] Add list of internal symbol names to escaped string type to cut back on casting --- src/compiler/binder.ts | 36 +++++++++++++++---------------- src/compiler/checker.ts | 18 ++++++++-------- src/compiler/types.ts | 20 ++++++++++++++++- src/services/findAllReferences.ts | 4 ++-- 4 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 6c054fe99c3df..06c660b7a9a16 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -247,32 +247,32 @@ namespace ts { } switch (node.kind) { case SyntaxKind.Constructor: - return "__constructor" as UnderscoreEscapedString; + return "__constructor"; case SyntaxKind.FunctionType: case SyntaxKind.CallSignature: - return "__call" as UnderscoreEscapedString; + return "__call"; case SyntaxKind.ConstructorType: case SyntaxKind.ConstructSignature: - return "__new" as UnderscoreEscapedString; + return "__new"; case SyntaxKind.IndexSignature: - return "__index" as UnderscoreEscapedString; + return "__index"; case SyntaxKind.ExportDeclaration: - return "__export" as UnderscoreEscapedString; + return "__export"; case SyntaxKind.ExportAssignment: - return ((node).isExportEquals ? "export=" : "default") as UnderscoreEscapedString; + return ((node).isExportEquals ? "export=" : "default"); case SyntaxKind.BinaryExpression: if (getSpecialPropertyAssignmentKind(node as BinaryExpression) === SpecialPropertyAssignmentKind.ModuleExports) { // module.exports = ... - return "export=" as UnderscoreEscapedString; + return "export="; } Debug.fail("Unknown binary declaration kind"); break; case SyntaxKind.FunctionDeclaration: case SyntaxKind.ClassDeclaration: - return (hasModifier(node, ModifierFlags.Default) ? "default" : undefined) as UnderscoreEscapedString; + return (hasModifier(node, ModifierFlags.Default) ? "default" : undefined); case SyntaxKind.JSDocFunctionType: - return (isJSDocConstructSignature(node) ? "__new" : "__call") as UnderscoreEscapedString; + return (isJSDocConstructSignature(node) ? "__new" : "__call"); case SyntaxKind.Parameter: // Parameters with names are handled at the top of this function. Parameters // without names can only come from JSDocFunctionTypes. @@ -313,11 +313,11 @@ namespace ts { const isDefaultExport = hasModifier(node, ModifierFlags.Default); // The exported symbol for an export default function/class node is always named "default" - const name = isDefaultExport && parent ? ("default" as UnderscoreEscapedString) : getDeclarationName(node); + const name = isDefaultExport && parent ? "default" : getDeclarationName(node); let symbol: Symbol; if (name === undefined) { - symbol = createSymbol(SymbolFlags.None, "__missing" as UnderscoreEscapedString); + symbol = createSymbol(SymbolFlags.None, "__missing"); } else { // Check and see if the symbol table already has a symbol with this name. If not, @@ -1646,7 +1646,7 @@ namespace ts { const symbol = createSymbol(SymbolFlags.Signature, getDeclarationName(node)); addDeclarationToSymbol(symbol, node, SymbolFlags.Signature); - const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type" as UnderscoreEscapedString); + const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type"); addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral); typeLiteralSymbol.members = createSymbolTable(); typeLiteralSymbol.members.set(symbol.name, symbol); @@ -1694,11 +1694,11 @@ namespace ts { } } - return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__object" as UnderscoreEscapedString); + return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__object"); } function bindJsxAttributes(node: JsxAttributes) { - return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__jsxAttributes" as UnderscoreEscapedString); + return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__jsxAttributes"); } function bindJsxAttribute(node: JsxAttribute, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { @@ -2191,7 +2191,7 @@ namespace ts { } function bindAnonymousTypeWorker(node: TypeLiteralNode | MappedTypeNode | JSDocTypeLiteral | JSDocRecordType) { - return bindAnonymousDeclaration(node, SymbolFlags.TypeLiteral, "__type" as UnderscoreEscapedString); + return bindAnonymousDeclaration(node, SymbolFlags.TypeLiteral, "__type"); } function checkTypePredicate(node: TypePredicateNode) { @@ -2441,7 +2441,7 @@ namespace ts { bindBlockScopedDeclaration(node, SymbolFlags.Class, SymbolFlags.ClassExcludes); } else { - const bindingName = node.name ? node.name.text : "__class" as UnderscoreEscapedString; + const bindingName = node.name ? node.name.text : "__class"; bindAnonymousDeclaration(node, SymbolFlags.Class, bindingName); // Add name of class expression into the map for semantic classifier if (node.name) { @@ -2554,7 +2554,7 @@ namespace ts { node.flowNode = currentFlow; } checkStrictModeFunctionName(node); - const bindingName = node.name ? node.name.text : "__function" as UnderscoreEscapedString; + const bindingName = node.name ? node.name.text : "__function"; return bindAnonymousDeclaration(node, SymbolFlags.Function, bindingName); } @@ -2568,7 +2568,7 @@ namespace ts { } return hasDynamicName(node) - ? bindAnonymousDeclaration(node, symbolFlags, "__computed" as UnderscoreEscapedString) + ? bindAnonymousDeclaration(node, symbolFlags, "__computed") : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c352e2c6da92c..1dc61a31c513c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -237,7 +237,7 @@ namespace ts { const evolvingArrayTypes: EvolvingArrayType[] = []; const unknownSymbol = createSymbol(SymbolFlags.Property, "unknown" as UnderscoreEscapedString); - const resolvingSymbol = createSymbol(0, "__resolving__" as UnderscoreEscapedString); + const resolvingSymbol = createSymbol(0, "__resolving__"); const anyType = createIntrinsicType(TypeFlags.Any, "any"); const autoType = createIntrinsicType(TypeFlags.Any, "any"); @@ -259,7 +259,7 @@ namespace ts { const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - const emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type" as UnderscoreEscapedString); + const emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type"); emptyTypeLiteralSymbol.members = createSymbolTable(); const emptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, emptyArray, emptyArray, undefined, undefined); @@ -1838,7 +1838,7 @@ namespace ts { visitedSymbols.push(symbol); const symbols = cloneMap(symbol.exports); // All export * declarations are collected in an __export symbol by the binder - const exportStars = symbol.exports.get("__export" as UnderscoreEscapedString); + const exportStars = symbol.exports.get("__export"); if (exportStars) { const nestedSymbols = createSymbolTable(); const lookupTable = createMap() as ExportCollisionTrackerTable; @@ -5333,8 +5333,8 @@ namespace ts { if (!(type).declaredProperties) { const symbol = type.symbol; (type).declaredProperties = getNamedMembers(symbol.members); - (type).declaredCallSignatures = getSignaturesOfSymbol(symbol.members.get("__call" as UnderscoreEscapedString)); - (type).declaredConstructSignatures = getSignaturesOfSymbol(symbol.members.get("__new" as UnderscoreEscapedString)); + (type).declaredCallSignatures = getSignaturesOfSymbol(symbol.members.get("__call")); + (type).declaredConstructSignatures = getSignaturesOfSymbol(symbol.members.get("__new")); (type).declaredStringIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.String); (type).declaredNumberIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.Number); } @@ -5625,8 +5625,8 @@ namespace ts { } else if (symbol.flags & SymbolFlags.TypeLiteral) { const members = symbol.members; - const callSignatures = getSignaturesOfSymbol(members.get("__call" as UnderscoreEscapedString)); - const constructSignatures = getSignaturesOfSymbol(members.get("__new" as UnderscoreEscapedString)); + const callSignatures = getSignaturesOfSymbol(members.get("__call")); + const constructSignatures = getSignaturesOfSymbol(members.get("__new")); const stringIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.String); const numberIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.Number); setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); @@ -5641,7 +5641,7 @@ namespace ts { } if (symbol.flags & SymbolFlags.Class) { const classType = getDeclaredTypeOfClassOrInterface(symbol); - constructSignatures = getSignaturesOfSymbol(symbol.members.get("__constructor" as UnderscoreEscapedString)); + constructSignatures = getSignaturesOfSymbol(symbol.members.get("__constructor")); if (!constructSignatures.length) { constructSignatures = getDefaultConstructSignatures(classType); } @@ -6599,7 +6599,7 @@ namespace ts { } function getIndexSymbol(symbol: Symbol): Symbol { - return symbol.members.get("__index" as UnderscoreEscapedString); + return symbol.members.get("__index"); } function getIndexDeclarationOfSymbol(symbol: Symbol, kind: IndexKind): SignatureDeclaration { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index cba1c48b2239b..7922c20b2e08f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3005,7 +3005,25 @@ namespace ts { isRestParameter?: boolean; } - export type UnderscoreEscapedString = (string & { __escapedIdentifier: void }) | (void & { __escapedIdentifier: void }); + export type InternalSymbolName = + | "__call" // Call signatures + | "__constructor" // Constructor implementations + | "__new" // Constructor signatures + | "__index" // Index signatures + | "__export" // Module export * declarations + | "__global" // Global self-reference + | "__missing" // Indicates missing symbol + | "__type" // Anonymous type literal symbol + | "__object" // Anonymous object literal declaration + | "__jsxAttributes" // Anonymous JSX attributes object literal declaration + | "__class" // Unnamed class expression + | "__function" // Unnamed function expression + | "__computed" // Computed property name declaration with dynamic name + | "__resolving__" // Indicator symbol used to mark partially resolved type aliases + | "export=" // Export assignment symbol + | "default"; // Default export symbol (technically not wholly internal, but included here for usability) + + export type UnderscoreEscapedString = (string & { __escapedIdentifier: void }) | (void & { __escapedIdentifier: void }) | InternalSymbolName; /** EscapedStringMap based on ES6 Map interface. */ export interface UnderscoreEscapedMap { diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 7f67661df4b59..ffc794070caee 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -977,7 +977,7 @@ namespace ts.FindAllReferences.Core { * Reference the constructor and all calls to `new this()`. */ function findOwnConstructorReferences(classSymbol: Symbol, sourceFile: SourceFile, addNode: (node: Node) => void): void { - for (const decl of classSymbol.members.get("__constructor" as UnderscoreEscapedString).declarations) { + for (const decl of classSymbol.members.get("__constructor").declarations) { const ctrKeyword = ts.findChildOfKind(decl, ts.SyntaxKind.ConstructorKeyword, sourceFile)!; Debug.assert(decl.kind === SyntaxKind.Constructor && !!ctrKeyword); addNode(ctrKeyword); @@ -1001,7 +1001,7 @@ namespace ts.FindAllReferences.Core { /** Find references to `super` in the constructor of an extending class. */ function findSuperConstructorAccesses(cls: ClassLikeDeclaration, addNode: (node: Node) => void): void { const symbol = cls.symbol; - const ctr = symbol.members.get("__constructor" as UnderscoreEscapedString); + const ctr = symbol.members.get("__constructor"); if (!ctr) { return; } From 3398d4137dae33826171f3cc4becccb682064f9d Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 6 Jul 2017 10:17:17 -0700 Subject: [PATCH 16/25] Remove outdated comments --- src/compiler/parser.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index ed5701aeb95e9..46bbb552018e3 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1226,8 +1226,8 @@ namespace ts { function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName { if (token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral) { - const node = parseLiteralNode(); // Interning makes the string literal be escaped - we do not want that - internIdentifier(node.text); // We do, however, want to intern the text for the purposes of the identifier list + const node = parseLiteralNode(); + internIdentifier(node.text); return node; } if (allowComputedPropertyNames && token() === SyntaxKind.OpenBracketToken) { @@ -5625,8 +5625,8 @@ namespace ts { node.flags |= NodeFlags.GlobalAugmentation; } else { - node.name = parseLiteralNode(); // Interning as an identifier causes it to be escaped - we do not want that - internIdentifier(node.name.text); // We do, however, want to intern the identifier for completions + node.name = parseLiteralNode(); + internIdentifier(node.name.text); } if (token() === SyntaxKind.OpenBraceToken) { From a4bd2abb97b23fcc5c10f3003b5186c8cd26f0a3 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 6 Jul 2017 12:58:42 -0700 Subject: [PATCH 17/25] Reassign interned values to nodes, just in case --- src/compiler/parser.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 46bbb552018e3..4e90570d1ec87 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1227,7 +1227,7 @@ namespace ts { function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName { if (token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral) { const node = parseLiteralNode(); - internIdentifier(node.text); + node.text = internIdentifier(node.text); return node; } if (allowComputedPropertyNames && token() === SyntaxKind.OpenBracketToken) { @@ -4099,7 +4099,7 @@ namespace ts { indexedAccess.argumentExpression = allowInAnd(parseExpression); if (indexedAccess.argumentExpression.kind === SyntaxKind.StringLiteral || indexedAccess.argumentExpression.kind === SyntaxKind.NumericLiteral) { const literal = indexedAccess.argumentExpression; - internIdentifier(literal.text); + literal.text = internIdentifier(literal.text); } } @@ -5626,7 +5626,7 @@ namespace ts { } else { node.name = parseLiteralNode(); - internIdentifier(node.name.text); + node.name.text = internIdentifier(node.name.text); } if (token() === SyntaxKind.OpenBraceToken) { @@ -5770,7 +5770,7 @@ namespace ts { function parseModuleSpecifier(): Expression { if (token() === SyntaxKind.StringLiteral) { const result = parseLiteralNode(); - internIdentifier((result).text); + result.text = internIdentifier(result.text); return result; } else { From 0967927270ffe3c12057ccf9abcd47208ab41d1c Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 6 Jul 2017 13:06:08 -0700 Subject: [PATCH 18/25] Swap to string enum --- src/compiler/types.ts | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 7922c20b2e08f..a937398d9cfb2 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3005,24 +3005,33 @@ namespace ts { isRestParameter?: boolean; } - export type InternalSymbolName = - | "__call" // Call signatures - | "__constructor" // Constructor implementations - | "__new" // Constructor signatures - | "__index" // Index signatures - | "__export" // Module export * declarations - | "__global" // Global self-reference - | "__missing" // Indicates missing symbol - | "__type" // Anonymous type literal symbol - | "__object" // Anonymous object literal declaration - | "__jsxAttributes" // Anonymous JSX attributes object literal declaration - | "__class" // Unnamed class expression - | "__function" // Unnamed function expression - | "__computed" // Computed property name declaration with dynamic name - | "__resolving__" // Indicator symbol used to mark partially resolved type aliases - | "export=" // Export assignment symbol - | "default"; // Default export symbol (technically not wholly internal, but included here for usability) + export const enum InternalSymbolName { + "__call" = "__call", // Call signatures + "__constructor" = "__constructor", // Constructor implementations + "__new" = "__new", // Constructor signatures + "__index" = "__index", // Index signatures + "__export" = "__export", // Module export * declarations + "__global" = "__global", // Global self-reference + "__missing" = "__missing", // Indicates missing symbol + "__type" = "__type", // Anonymous type literal symbol + "__object" = "__object", // Anonymous object literal declaration + "__jsxAttributes" = "__jsxAttributes", // Anonymous JSX attributes object literal declaration + "__class" = "__class", // Unnamed class expression + "__function" = "__function", // Unnamed function expression + "__computed" = "__computed", // Computed property name declaration with dynamic name + "__resolving__" = "__resolving__", // Indicator symbol used to mark partially resolved type aliases + "export=" = "export=", // Export assignment symbol + "default" = "default", // Default export symbol (technically not wholly internal, but included here for usability) + } + /** + * This represents a string whose leading underscore have been escaped by adding extra leading underscores. + * The shape of this brand is rather unique compared to others we've used. + * Instead of just an intersection of a string and an object, it is that union-ed + * with an intersection of void and an object. This makes it wholly incompatible + * with a normal string (which is good, it cannot be misused on assignment or on usage), + * while still being comparable with a normal string via === (also good) and castable from a string. + */ export type UnderscoreEscapedString = (string & { __escapedIdentifier: void }) | (void & { __escapedIdentifier: void }) | InternalSymbolName; /** EscapedStringMap based on ES6 Map interface. */ From e99b679764d5c32a1cb0af02f9d8a93aced8f789 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 6 Jul 2017 13:10:08 -0700 Subject: [PATCH 19/25] Add deprecated aliases to escapeIdentifier and unescapeIdentifier --- src/compiler/utilities.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 84ead689e1ef7..b16c3b5ccfd7a 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -355,6 +355,14 @@ namespace ts { return (identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier) as UnderscoreEscapedString; } + /** + * @deprecated + * @param identifier The identifier to escape + */ + export function escapeIdentifier(identifier: string): string { + return escapeLeadingUnderscores(identifier) as string; + } + // Make an identifier from an external module name by extracting the string after the last "/" and replacing // all non-alphanumeric characters with underscores export function makeIdentifierFromModuleName(moduleName: string): string { @@ -4013,6 +4021,16 @@ namespace ts { return (identifier as string).length >= 3 && (identifier as string).charCodeAt(0) === CharacterCodes._ && (identifier as string).charCodeAt(1) === CharacterCodes._ && (identifier as string).charCodeAt(2) === CharacterCodes._ ? (identifier as string).substr(1) : identifier as string; } + /** + * Remove extra underscore from escaped identifier text content. + * @deprecated + * @param identifier The escaped identifier text. + * @returns The unescaped identifier text. + */ + export function unescapeIdentifier(id: string): string { + return unescapeLeadingUnderscores(id as UnderscoreEscapedString); + } + export function getNameOfDeclaration(declaration: Declaration): DeclarationName | undefined { if (!declaration) { return undefined; From 3383d8aac17f68d84794342e66b5d841cadf4e2c Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 6 Jul 2017 13:13:11 -0700 Subject: [PATCH 20/25] Add temp var --- src/compiler/utilities.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index b16c3b5ccfd7a..abdbbca8eedb2 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4018,7 +4018,8 @@ namespace ts { * @returns The unescaped identifier text. */ export function unescapeLeadingUnderscores(identifier: UnderscoreEscapedString): string { - return (identifier as string).length >= 3 && (identifier as string).charCodeAt(0) === CharacterCodes._ && (identifier as string).charCodeAt(1) === CharacterCodes._ && (identifier as string).charCodeAt(2) === CharacterCodes._ ? (identifier as string).substr(1) : identifier as string; + const id = identifier as string; + return id.length >= 3 && id.charCodeAt(0) === CharacterCodes._ && id.charCodeAt(1) === CharacterCodes._ && id.charCodeAt(2) === CharacterCodes._ ? id.substr(1) : id; } /** From 5eca8a376a9965191eab189bfa8b9d88ee9be44e Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 6 Jul 2017 13:17:17 -0700 Subject: [PATCH 21/25] Remove unsafe casts --- src/compiler/utilities.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index abdbbca8eedb2..5a9e07bfeb517 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -481,10 +481,10 @@ namespace ts { return (name).text; case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: - return (name).text as UnderscoreEscapedString; + return escapeLeadingUnderscores((name).text); case SyntaxKind.ComputedPropertyName: if (isStringOrNumericLiteral((name).expression)) { - return ((name).expression).text as UnderscoreEscapedString; + return escapeLeadingUnderscores(((name).expression).text); } } From 9424f14df0c6d28aaa0df80bcc8155957835d54f Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 6 Jul 2017 13:35:52 -0700 Subject: [PATCH 22/25] Rename escaped string type as per @sandersn's suggestion, fix string enum usages --- src/compiler/binder.ts | 72 ++++----- src/compiler/checker.ts | 240 +++++++++++++++--------------- src/compiler/core.ts | 16 +- src/compiler/parser.ts | 2 +- src/compiler/program.ts | 4 +- src/compiler/types.ts | 56 +++---- src/compiler/utilities.ts | 18 +-- src/services/classifier.ts | 4 +- src/services/completions.ts | 2 +- src/services/findAllReferences.ts | 6 +- src/services/importTracker.ts | 2 +- src/services/services.ts | 10 +- src/services/types.ts | 2 +- 13 files changed, 217 insertions(+), 217 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 06c660b7a9a16..7d170cf291714 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -10,7 +10,7 @@ namespace ts { } interface ActiveLabel { - name: UnderscoreEscapedString; + name: __String; breakTarget: FlowLabel; continueTarget: FlowLabel; referenced: boolean; @@ -132,8 +132,8 @@ namespace ts { let inStrictMode: boolean; let symbolCount = 0; - let Symbol: { new (flags: SymbolFlags, name: UnderscoreEscapedString): Symbol }; - let classifiableNames: UnderscoreEscapedMap; + let Symbol: { new (flags: SymbolFlags, name: __String): Symbol }; + let classifiableNames: UnderscoreEscapedMap<__String>; const unreachableFlow: FlowNode = { flags: FlowFlags.Unreachable }; const reportedUnreachableFlow: FlowNode = { flags: FlowFlags.Unreachable }; @@ -147,7 +147,7 @@ namespace ts { options = opts; languageVersion = getEmitScriptTarget(options); inStrictMode = bindInStrictMode(file, opts); - classifiableNames = createUnderscoreEscapedMap(); + classifiableNames = createUnderscoreEscapedMap<__String>(); symbolCount = 0; skipTransformFlagAggregation = file.isDeclarationFile; @@ -191,7 +191,7 @@ namespace ts { } } - function createSymbol(flags: SymbolFlags, name: UnderscoreEscapedString): Symbol { + function createSymbol(flags: SymbolFlags, name: __String): Symbol { symbolCount++; return new Symbol(flags, name); } @@ -226,12 +226,12 @@ namespace ts { // Should not be called on a declaration with a computed property name, // unless it is a well known Symbol. - function getDeclarationName(node: Declaration): UnderscoreEscapedString { + function getDeclarationName(node: Declaration): __String { const name = getNameOfDeclaration(node); if (name) { if (isAmbientModule(node)) { const moduleName = getTextOfIdentifierOrLiteral(name); - return (isGlobalScopeAugmentation(node) ? "__global" : `"${moduleName}"`) as UnderscoreEscapedString; + return (isGlobalScopeAugmentation(node) ? "__global" : `"${moduleName}"`) as __String; } if (name.kind === SyntaxKind.ComputedPropertyName) { const nameExpression = (name).expression; @@ -247,42 +247,42 @@ namespace ts { } switch (node.kind) { case SyntaxKind.Constructor: - return "__constructor"; + return InternalSymbolName.Constructor; case SyntaxKind.FunctionType: case SyntaxKind.CallSignature: - return "__call"; + return InternalSymbolName.Call; case SyntaxKind.ConstructorType: case SyntaxKind.ConstructSignature: - return "__new"; + return InternalSymbolName.New; case SyntaxKind.IndexSignature: - return "__index"; + return InternalSymbolName.Index; case SyntaxKind.ExportDeclaration: - return "__export"; + return InternalSymbolName.ExportStar; case SyntaxKind.ExportAssignment: - return ((node).isExportEquals ? "export=" : "default"); + return ((node).isExportEquals ? InternalSymbolName.ExportEquals : InternalSymbolName.Default); case SyntaxKind.BinaryExpression: if (getSpecialPropertyAssignmentKind(node as BinaryExpression) === SpecialPropertyAssignmentKind.ModuleExports) { // module.exports = ... - return "export="; + return InternalSymbolName.ExportEquals; } Debug.fail("Unknown binary declaration kind"); break; case SyntaxKind.FunctionDeclaration: case SyntaxKind.ClassDeclaration: - return (hasModifier(node, ModifierFlags.Default) ? "default" : undefined); + return (hasModifier(node, ModifierFlags.Default) ? InternalSymbolName.Default : undefined); case SyntaxKind.JSDocFunctionType: - return (isJSDocConstructSignature(node) ? "__new" : "__call"); + return (isJSDocConstructSignature(node) ? InternalSymbolName.New : InternalSymbolName.Call); case SyntaxKind.Parameter: // Parameters with names are handled at the top of this function. Parameters // without names can only come from JSDocFunctionTypes. Debug.assert(node.parent.kind === SyntaxKind.JSDocFunctionType); const functionType = node.parent; const index = indexOf(functionType.parameters, node); - return "arg" + index as UnderscoreEscapedString; + return "arg" + index as __String; case SyntaxKind.JSDocTypedefTag: const parentNode = node.parent && node.parent.parent; - let nameFromParentNode: UnderscoreEscapedString; + let nameFromParentNode: __String; if (parentNode && parentNode.kind === SyntaxKind.VariableStatement) { if ((parentNode).declarationList.declarations.length > 0) { const nameIdentifier = (parentNode).declarationList.declarations[0].name; @@ -313,11 +313,11 @@ namespace ts { const isDefaultExport = hasModifier(node, ModifierFlags.Default); // The exported symbol for an export default function/class node is always named "default" - const name = isDefaultExport && parent ? "default" : getDeclarationName(node); + const name = isDefaultExport && parent ? InternalSymbolName.Default : getDeclarationName(node); let symbol: Symbol; if (name === undefined) { - symbol = createSymbol(SymbolFlags.None, "__missing"); + symbol = createSymbol(SymbolFlags.None, InternalSymbolName.Missing); } else { // Check and see if the symbol table already has a symbol with this name. If not, @@ -1007,7 +1007,7 @@ namespace ts { currentFlow = unreachableFlow; } - function findActiveLabel(name: UnderscoreEscapedString) { + function findActiveLabel(name: __String) { if (activeLabels) { for (const label of activeLabels) { if (label.name === name) { @@ -1170,7 +1170,7 @@ namespace ts { bindEach(node.statements); } - function pushActiveLabel(name: UnderscoreEscapedString, breakTarget: FlowLabel, continueTarget: FlowLabel): ActiveLabel { + function pushActiveLabel(name: __String, breakTarget: FlowLabel, continueTarget: FlowLabel): ActiveLabel { const activeLabel = { name, breakTarget, @@ -1646,7 +1646,7 @@ namespace ts { const symbol = createSymbol(SymbolFlags.Signature, getDeclarationName(node)); addDeclarationToSymbol(symbol, node, SymbolFlags.Signature); - const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type"); + const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type); addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral); typeLiteralSymbol.members = createSymbolTable(); typeLiteralSymbol.members.set(symbol.name, symbol); @@ -1694,18 +1694,18 @@ namespace ts { } } - return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__object"); + return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, InternalSymbolName.Object); } function bindJsxAttributes(node: JsxAttributes) { - return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__jsxAttributes"); + return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, InternalSymbolName.JSXAttributes); } function bindJsxAttribute(node: JsxAttribute, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { return declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } - function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: UnderscoreEscapedString) { + function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: __String) { const symbol = createSymbol(symbolFlags, name); addDeclarationToSymbol(symbol, node, symbolFlags); } @@ -1896,8 +1896,8 @@ namespace ts { file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); } - function getDestructuringParameterName(node: Declaration): UnderscoreEscapedString { - return "__" + indexOf((node.parent).parameters, node) as UnderscoreEscapedString; + function getDestructuringParameterName(node: Declaration): __String { + return "__" + indexOf((node.parent).parameters, node) as __String; } function bind(node: Node): void { @@ -2191,7 +2191,7 @@ namespace ts { } function bindAnonymousTypeWorker(node: TypeLiteralNode | MappedTypeNode | JSDocTypeLiteral | JSDocRecordType) { - return bindAnonymousDeclaration(node, SymbolFlags.TypeLiteral, "__type"); + return bindAnonymousDeclaration(node, SymbolFlags.TypeLiteral, InternalSymbolName.Type); } function checkTypePredicate(node: TypePredicateNode) { @@ -2213,7 +2213,7 @@ namespace ts { } function bindSourceFileAsExternalModule() { - bindAnonymousDeclaration(file, SymbolFlags.ValueModule, `"${removeFileExtension(file.fileName)}"` as UnderscoreEscapedString); + bindAnonymousDeclaration(file, SymbolFlags.ValueModule, `"${removeFileExtension(file.fileName)}"` as __String); } function bindExportAssignment(node: ExportAssignment | BinaryExpression) { @@ -2404,11 +2404,11 @@ namespace ts { } } - function lookupSymbolForName(name: UnderscoreEscapedString) { + function lookupSymbolForName(name: __String) { return (container.symbol && container.symbol.exports && container.symbol.exports.get(name)) || (container.locals && container.locals.get(name)); } - function bindPropertyAssignment(functionName: UnderscoreEscapedString, propertyAccessExpression: PropertyAccessExpression, isPrototypeProperty: boolean) { + function bindPropertyAssignment(functionName: __String, propertyAccessExpression: PropertyAccessExpression, isPrototypeProperty: boolean) { let targetSymbol = lookupSymbolForName(functionName); if (targetSymbol && isDeclarationOfFunctionOrClassExpression(targetSymbol)) { @@ -2441,7 +2441,7 @@ namespace ts { bindBlockScopedDeclaration(node, SymbolFlags.Class, SymbolFlags.ClassExcludes); } else { - const bindingName = node.name ? node.name.text : "__class"; + const bindingName = node.name ? node.name.text : InternalSymbolName.Class; bindAnonymousDeclaration(node, SymbolFlags.Class, bindingName); // Add name of class expression into the map for semantic classifier if (node.name) { @@ -2460,7 +2460,7 @@ namespace ts { // Note: we check for this here because this class may be merging into a module. The // module might have an exported variable called 'prototype'. We can't allow that as // that would clash with the built-in 'prototype' for the class. - const prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype" as UnderscoreEscapedString); + const prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype" as __String); const symbolExport = symbol.exports.get(prototypeSymbol.name); if (symbolExport) { if (node.name) { @@ -2554,7 +2554,7 @@ namespace ts { node.flowNode = currentFlow; } checkStrictModeFunctionName(node); - const bindingName = node.name ? node.name.text : "__function"; + const bindingName = node.name ? node.name.text : InternalSymbolName.Function; return bindAnonymousDeclaration(node, SymbolFlags.Function, bindingName); } @@ -2568,7 +2568,7 @@ namespace ts { } return hasDynamicName(node) - ? bindAnonymousDeclaration(node, symbolFlags, "__computed") + ? bindAnonymousDeclaration(node, symbolFlags, InternalSymbolName.Computed) : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1dc61a31c513c..32ef2ba57942e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -71,9 +71,9 @@ namespace ts { const emitResolver = createResolver(); const nodeBuilder = createNodeBuilder(); - const undefinedSymbol = createSymbol(SymbolFlags.Property, "undefined" as UnderscoreEscapedString); + const undefinedSymbol = createSymbol(SymbolFlags.Property, "undefined" as __String); undefinedSymbol.declarations = []; - const argumentsSymbol = createSymbol(SymbolFlags.Property, "arguments" as UnderscoreEscapedString); + const argumentsSymbol = createSymbol(SymbolFlags.Property, "arguments" as __String); /** This will be set during calls to `getResolvedSignature` where services determines an apparent number of arguments greater than what is actually provided. */ let apparentArgumentCount: number | undefined; @@ -236,8 +236,8 @@ namespace ts { const indexedAccessTypes = createMap(); const evolvingArrayTypes: EvolvingArrayType[] = []; - const unknownSymbol = createSymbol(SymbolFlags.Property, "unknown" as UnderscoreEscapedString); - const resolvingSymbol = createSymbol(0, "__resolving__"); + const unknownSymbol = createSymbol(SymbolFlags.Property, "unknown" as __String); + const resolvingSymbol = createSymbol(0, InternalSymbolName.Resolving); const anyType = createIntrinsicType(TypeFlags.Any, "any"); const autoType = createIntrinsicType(TypeFlags.Any, "any"); @@ -259,7 +259,7 @@ namespace ts { const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - const emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type"); + const emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type); emptyTypeLiteralSymbol.members = createSymbolTable(); const emptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, emptyArray, emptyArray, undefined, undefined); @@ -444,25 +444,25 @@ namespace ts { }); const typeofType = createTypeofType(); - let _jsxNamespace: UnderscoreEscapedString; + let _jsxNamespace: __String; let _jsxFactoryEntity: EntityName; - let _jsxElementPropertiesName: UnderscoreEscapedString; + let _jsxElementPropertiesName: __String; let _hasComputedJsxElementPropertiesName = false; - let _jsxElementChildrenPropertyName: UnderscoreEscapedString; + let _jsxElementChildrenPropertyName: __String; let _hasComputedJsxElementChildrenPropertyName = false; /** Things we lazy load from the JSX namespace */ const jsxTypes = createUnderscoreEscapedMap(); const JsxNames = { - JSX: "JSX" as UnderscoreEscapedString, - IntrinsicElements: "IntrinsicElements" as UnderscoreEscapedString, - ElementClass: "ElementClass" as UnderscoreEscapedString, - ElementAttributesPropertyNameContainer: "ElementAttributesProperty" as UnderscoreEscapedString, - ElementChildrenAttributeNameContainer: "ElementChildrenAttribute" as UnderscoreEscapedString, - Element: "Element" as UnderscoreEscapedString, - IntrinsicAttributes: "IntrinsicAttributes" as UnderscoreEscapedString, - IntrinsicClassAttributes: "IntrinsicClassAttributes" as UnderscoreEscapedString + JSX: "JSX" as __String, + IntrinsicElements: "IntrinsicElements" as __String, + ElementClass: "ElementClass" as __String, + ElementAttributesPropertyNameContainer: "ElementAttributesProperty" as __String, + ElementChildrenAttributeNameContainer: "ElementChildrenAttribute" as __String, + Element: "Element" as __String, + IntrinsicAttributes: "IntrinsicAttributes" as __String, + IntrinsicClassAttributes: "IntrinsicClassAttributes" as __String }; const subtypeRelation = createMap(); @@ -496,9 +496,9 @@ namespace ts { return checker; - function getJsxNamespace(): UnderscoreEscapedString { + function getJsxNamespace(): __String { if (!_jsxNamespace) { - _jsxNamespace = "React" as UnderscoreEscapedString; + _jsxNamespace = "React" as __String; if (compilerOptions.jsxFactory) { _jsxFactoryEntity = parseIsolatedEntityName(compilerOptions.jsxFactory, languageVersion); if (_jsxFactoryEntity) { @@ -526,7 +526,7 @@ namespace ts { diagnostics.add(diagnostic); } - function createSymbol(flags: SymbolFlags, name: UnderscoreEscapedString) { + function createSymbol(flags: SymbolFlags, name: __String) { symbolCount++; const symbol = (new Symbol(flags | SymbolFlags.Transient, name)); symbol.checkFlags = 0; @@ -706,7 +706,7 @@ namespace ts { return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(node); } - function getSymbol(symbols: SymbolTable, name: UnderscoreEscapedString, meaning: SymbolFlags): Symbol { + function getSymbol(symbols: SymbolTable, name: __String, meaning: SymbolFlags): Symbol { if (meaning) { const symbol = symbols.get(name); if (symbol) { @@ -732,7 +732,7 @@ namespace ts { * @param parameterName a name of the parameter to get the symbols for. * @return a tuple of two symbols */ - function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: UnderscoreEscapedString): [Symbol, Symbol] { + function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: __String): [Symbol, Symbol] { const constructorDeclaration = parameter.parent; const classDeclaration = parameter.parent.parent; @@ -855,20 +855,20 @@ namespace ts { // the given name can be found. function resolveName( location: Node | undefined, - name: UnderscoreEscapedString, + name: __String, meaning: SymbolFlags, nameNotFoundMessage: DiagnosticMessage | undefined, - nameArg: UnderscoreEscapedString | Identifier, + nameArg: __String | Identifier, suggestedNameNotFoundMessage?: DiagnosticMessage): Symbol { return resolveNameHelper(location, name, meaning, nameNotFoundMessage, nameArg, getSymbol, suggestedNameNotFoundMessage); } function resolveNameHelper( location: Node | undefined, - name: UnderscoreEscapedString, + name: __String, meaning: SymbolFlags, nameNotFoundMessage: DiagnosticMessage, - nameArg: UnderscoreEscapedString | Identifier, + nameArg: __String | Identifier, lookup: typeof getSymbol, suggestedNameNotFoundMessage?: DiagnosticMessage): Symbol { const originalLocation = location; // needed for did-you-mean error reporting, which gathers candidates starting from the original location @@ -933,7 +933,7 @@ namespace ts { // It's an external module. First see if the module has an export default and if the local // name of that export default matches. - if (result = moduleExports.get("default" as UnderscoreEscapedString)) { + if (result = moduleExports.get("default" as __String)) { const localSymbol = getLocalSymbolForExportDefault(result); if (localSymbol && (result.flags & meaning) && localSymbol.name === name) { break loop; @@ -1101,7 +1101,7 @@ namespace ts { !checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) && !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) && !checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation, name, meaning)) { - let suggestion: UnderscoreEscapedString | undefined; + let suggestion: __String | undefined; if (suggestedNameNotFoundMessage && suggestionCount < maximumSuggestionCount) { suggestion = getSuggestionForNonexistentSymbol(originalLocation, name, meaning); if (suggestion) { @@ -1159,8 +1159,8 @@ namespace ts { return result; } - function diagnosticName(nameArg: UnderscoreEscapedString | Identifier) { - return typeof nameArg === "string" ? unescapeLeadingUnderscores(nameArg as UnderscoreEscapedString) : declarationNameToString(nameArg as Identifier); + function diagnosticName(nameArg: __String | Identifier) { + return typeof nameArg === "string" ? unescapeLeadingUnderscores(nameArg as __String) : declarationNameToString(nameArg as Identifier); } function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) { @@ -1173,7 +1173,7 @@ namespace ts { return false; } - function checkAndReportErrorForMissingPrefix(errorLocation: Node, name: UnderscoreEscapedString, nameArg: UnderscoreEscapedString | Identifier): boolean { + function checkAndReportErrorForMissingPrefix(errorLocation: Node, name: __String, nameArg: __String | Identifier): boolean { if ((errorLocation.kind === SyntaxKind.Identifier && (isTypeReferenceIdentifier(errorLocation)) || isInTypeQuery(errorLocation))) { return false; } @@ -1236,7 +1236,7 @@ namespace ts { } } - function checkAndReportErrorForUsingTypeAsNamespace(errorLocation: Node, name: UnderscoreEscapedString, meaning: SymbolFlags): boolean { + function checkAndReportErrorForUsingTypeAsNamespace(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { if (meaning === SymbolFlags.Namespace) { const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined)); if (symbol) { @@ -1248,7 +1248,7 @@ namespace ts { return false; } - function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: UnderscoreEscapedString, meaning: SymbolFlags): boolean { + function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule)) { if (name === "any" || name === "string" || name === "number" || name === "boolean" || name === "never") { error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeLeadingUnderscores(name)); @@ -1263,7 +1263,7 @@ namespace ts { return false; } - function checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation: Node, name: UnderscoreEscapedString, meaning: SymbolFlags): boolean { + function checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule & ~SymbolFlags.Type)) { const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.NamespaceModule & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined)); if (symbol) { @@ -1339,10 +1339,10 @@ namespace ts { exportDefaultSymbol = moduleSymbol; } else { - const exportValue = moduleSymbol.exports.get("export=" as UnderscoreEscapedString); + const exportValue = moduleSymbol.exports.get("export=" as __String); exportDefaultSymbol = exportValue - ? getPropertyOfType(getTypeOfSymbol(exportValue), "default" as UnderscoreEscapedString) - : resolveSymbol(moduleSymbol.exports.get("default" as UnderscoreEscapedString), dontResolveAlias); + ? getPropertyOfType(getTypeOfSymbol(exportValue), "default" as __String) + : resolveSymbol(moduleSymbol.exports.get("default" as __String), dontResolveAlias); } if (!exportDefaultSymbol && !allowSyntheticDefaultImports) { @@ -1394,13 +1394,13 @@ namespace ts { return result; } - function getExportOfModule(symbol: Symbol, name: UnderscoreEscapedString, dontResolveAlias: boolean): Symbol { + function getExportOfModule(symbol: Symbol, name: __String, dontResolveAlias: boolean): Symbol { if (symbol.flags & SymbolFlags.Module) { return resolveSymbol(getExportsOfSymbol(symbol).get(name), dontResolveAlias); } } - function getPropertyOfVariable(symbol: Symbol, name: UnderscoreEscapedString): Symbol { + function getPropertyOfVariable(symbol: Symbol, name: __String): Symbol { if (symbol.flags & SymbolFlags.Variable) { const typeAnnotation = (symbol.valueDeclaration).type; if (typeAnnotation) { @@ -1421,7 +1421,7 @@ namespace ts { let symbolFromVariable: Symbol; // First check if module was specified with "export=". If so, get the member from the resolved type - if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get("export=" as UnderscoreEscapedString)) { + if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get("export=" as __String)) { symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name.text); } else { @@ -1738,7 +1738,7 @@ namespace ts { // An external module with an 'export =' declaration resolves to the target of the 'export =' declaration, // and an external module with no 'export =' declaration resolves to the module itself. function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol { - return moduleSymbol && getMergedSymbol(resolveSymbol(moduleSymbol.exports.get("export=" as UnderscoreEscapedString), dontResolveAlias)) || moduleSymbol; + return moduleSymbol && getMergedSymbol(resolveSymbol(moduleSymbol.exports.get("export=" as __String), dontResolveAlias)) || moduleSymbol; } // An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export =' @@ -1753,7 +1753,7 @@ namespace ts { } function hasExportAssignmentSymbol(moduleSymbol: Symbol): boolean { - return moduleSymbol.exports.get("export=" as UnderscoreEscapedString) !== undefined; + return moduleSymbol.exports.get("export=" as __String) !== undefined; } function getExportsOfModuleAsArray(moduleSymbol: Symbol): Symbol[] { @@ -1769,7 +1769,7 @@ namespace ts { return exports; } - function tryGetMemberInModuleExports(memberName: UnderscoreEscapedString, moduleSymbol: Symbol): Symbol | undefined { + function tryGetMemberInModuleExports(memberName: __String, moduleSymbol: Symbol): Symbol | undefined { const symbolTable = getExportsOfModule(moduleSymbol); if (symbolTable) { return symbolTable.get(memberName); @@ -1838,7 +1838,7 @@ namespace ts { visitedSymbols.push(symbol); const symbols = cloneMap(symbol.exports); // All export * declarations are collected in an __export symbol by the binder - const exportStars = symbol.exports.get("__export"); + const exportStars = symbol.exports.get(InternalSymbolName.ExportStar); if (exportStars) { const nestedSymbols = createSymbolTable(); const lookupTable = createMap() as ExportCollisionTrackerTable; @@ -1939,7 +1939,7 @@ namespace ts { // or the @ symbol. A third underscore indicates an escaped form of an identifer that started // with at least two underscores. The @ character indicates that the name is denoted by a well known ES // Symbol instance. - function isReservedMemberName(name: UnderscoreEscapedString) { + function isReservedMemberName(name: __String) { return (name as string).charCodeAt(0) === CharacterCodes._ && (name as string).charCodeAt(1) === CharacterCodes._ && (name as string).charCodeAt(2) !== CharacterCodes._ && @@ -4048,7 +4048,7 @@ namespace ts { } // Return the type of the given property in the given type, or undefined if no such property exists - function getTypeOfPropertyOfType(type: Type, name: UnderscoreEscapedString): Type { + function getTypeOfPropertyOfType(type: Type, name: __String): Type { const prop = getPropertyOfType(type, name); return prop ? getTypeOfSymbol(prop) : undefined; } @@ -4166,7 +4166,7 @@ namespace ts { // Use specific property type when parent is a tuple or numeric index type when parent is an array const propName = "" + indexOf(pattern.elements, declaration); type = isTupleLikeType(parentType) - ? getTypeOfPropertyOfType(parentType, propName as UnderscoreEscapedString) + ? getTypeOfPropertyOfType(parentType, propName as __String) : elementType; if (!type) { if (isTupleType(parentType)) { @@ -5333,8 +5333,8 @@ namespace ts { if (!(type).declaredProperties) { const symbol = type.symbol; (type).declaredProperties = getNamedMembers(symbol.members); - (type).declaredCallSignatures = getSignaturesOfSymbol(symbol.members.get("__call")); - (type).declaredConstructSignatures = getSignaturesOfSymbol(symbol.members.get("__new")); + (type).declaredCallSignatures = getSignaturesOfSymbol(symbol.members.get(InternalSymbolName.Call)); + (type).declaredConstructSignatures = getSignaturesOfSymbol(symbol.members.get(InternalSymbolName.New)); (type).declaredStringIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.String); (type).declaredNumberIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.Number); } @@ -5625,8 +5625,8 @@ namespace ts { } else if (symbol.flags & SymbolFlags.TypeLiteral) { const members = symbol.members; - const callSignatures = getSignaturesOfSymbol(members.get("__call")); - const constructSignatures = getSignaturesOfSymbol(members.get("__new")); + const callSignatures = getSignaturesOfSymbol(members.get(InternalSymbolName.Call)); + const constructSignatures = getSignaturesOfSymbol(members.get(InternalSymbolName.New)); const stringIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.String); const numberIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.Number); setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); @@ -5641,7 +5641,7 @@ namespace ts { } if (symbol.flags & SymbolFlags.Class) { const classType = getDeclaredTypeOfClassOrInterface(symbol); - constructSignatures = getSignaturesOfSymbol(symbol.members.get("__constructor")); + constructSignatures = getSignaturesOfSymbol(symbol.members.get(InternalSymbolName.Constructor)); if (!constructSignatures.length) { constructSignatures = getDefaultConstructSignatures(classType); } @@ -5811,7 +5811,7 @@ namespace ts { /** If the given type is an object type and that type has a property by the given name, * return the symbol for that property. Otherwise return undefined. */ - function getPropertyOfObjectType(type: Type, name: UnderscoreEscapedString): Symbol { + function getPropertyOfObjectType(type: Type, name: __String): Symbol { if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); const symbol = resolved.members.get(name); @@ -6006,7 +6006,7 @@ namespace ts { t; } - function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: UnderscoreEscapedString): Symbol { + function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: __String): Symbol { let props: Symbol[]; const types = containingType.types; const isUnion = containingType.flags & TypeFlags.Union; @@ -6077,7 +6077,7 @@ namespace ts { // constituents, in which case the isPartial flag is set when the containing type is union type. We need // these partial properties when identifying discriminant properties, but otherwise they are filtered out // and do not appear to be present in the union type. - function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: UnderscoreEscapedString): Symbol { + function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: __String): Symbol { const properties = type.propertyCache || (type.propertyCache = createSymbolTable()); let property = properties.get(name); if (!property) { @@ -6089,7 +6089,7 @@ namespace ts { return property; } - function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: UnderscoreEscapedString): Symbol { + function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: __String): Symbol { const property = getUnionOrIntersectionProperty(type, name); // We need to filter out partial properties in union types return property && !(getCheckFlags(property) & CheckFlags.Partial) ? property : undefined; @@ -6103,7 +6103,7 @@ namespace ts { * @param type a type to look up property from * @param name a name of property to look up in a given type */ - function getPropertyOfType(type: Type, name: UnderscoreEscapedString): Symbol | undefined { + function getPropertyOfType(type: Type, name: __String): Symbol | undefined { type = getApparentType(type); if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); @@ -6230,7 +6230,7 @@ namespace ts { if (isExternalModuleNameRelative(moduleName)) { return undefined; } - const symbol = getSymbol(globals, `"${moduleName}"` as UnderscoreEscapedString, SymbolFlags.ValueModule); + const symbol = getSymbol(globals, `"${moduleName}"` as __String, SymbolFlags.ValueModule); // merged symbol is module declaration symbol combined with all augmentations return symbol && withAugmentations ? getMergedSymbol(symbol) : symbol; } @@ -6394,7 +6394,7 @@ namespace ts { let hasRestLikeParameter = hasRestParameter(declaration); if (!hasRestLikeParameter && isInJavaScriptFile(declaration) && containsArgumentsReference(declaration)) { hasRestLikeParameter = true; - const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args" as UnderscoreEscapedString); + const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args" as __String); syntheticArgsSymbol.type = anyArrayType; syntheticArgsSymbol.isRestParameter = true; parameters.push(syntheticArgsSymbol); @@ -6599,7 +6599,7 @@ namespace ts { } function getIndexSymbol(symbol: Symbol): Symbol { - return symbol.members.get("__index"); + return symbol.members.get(InternalSymbolName.Index); } function getIndexDeclarationOfSymbol(symbol: Symbol, kind: IndexKind): SignatureDeclaration { @@ -6979,78 +6979,78 @@ namespace ts { return type; } - function getGlobalValueSymbol(name: UnderscoreEscapedString, reportErrors: boolean): Symbol { + function getGlobalValueSymbol(name: __String, reportErrors: boolean): Symbol { return getGlobalSymbol(name, SymbolFlags.Value, reportErrors ? Diagnostics.Cannot_find_global_value_0 : undefined); } - function getGlobalTypeSymbol(name: UnderscoreEscapedString, reportErrors: boolean): Symbol { + function getGlobalTypeSymbol(name: __String, reportErrors: boolean): Symbol { return getGlobalSymbol(name, SymbolFlags.Type, reportErrors ? Diagnostics.Cannot_find_global_type_0 : undefined); } - function getGlobalSymbol(name: UnderscoreEscapedString, meaning: SymbolFlags, diagnostic: DiagnosticMessage): Symbol { + function getGlobalSymbol(name: __String, meaning: SymbolFlags, diagnostic: DiagnosticMessage): Symbol { return resolveName(undefined, name, meaning, diagnostic, name); } - function getGlobalType(name: UnderscoreEscapedString, arity: 0, reportErrors: boolean): ObjectType; - function getGlobalType(name: UnderscoreEscapedString, arity: number, reportErrors: boolean): GenericType; - function getGlobalType(name: UnderscoreEscapedString, arity: number, reportErrors: boolean): ObjectType { + function getGlobalType(name: __String, arity: 0, reportErrors: boolean): ObjectType; + function getGlobalType(name: __String, arity: number, reportErrors: boolean): GenericType; + function getGlobalType(name: __String, arity: number, reportErrors: boolean): ObjectType { const symbol = getGlobalTypeSymbol(name, reportErrors); return symbol || reportErrors ? getTypeOfGlobalSymbol(symbol, arity) : undefined; } function getGlobalTypedPropertyDescriptorType() { - return deferredGlobalTypedPropertyDescriptorType || (deferredGlobalTypedPropertyDescriptorType = getGlobalType("TypedPropertyDescriptor" as UnderscoreEscapedString, /*arity*/ 1, /*reportErrors*/ true)) || emptyGenericType; + return deferredGlobalTypedPropertyDescriptorType || (deferredGlobalTypedPropertyDescriptorType = getGlobalType("TypedPropertyDescriptor" as __String, /*arity*/ 1, /*reportErrors*/ true)) || emptyGenericType; } function getGlobalTemplateStringsArrayType() { - return deferredGlobalTemplateStringsArrayType || (deferredGlobalTemplateStringsArrayType = getGlobalType("TemplateStringsArray" as UnderscoreEscapedString, /*arity*/ 0, /*reportErrors*/ true)) || emptyObjectType; + return deferredGlobalTemplateStringsArrayType || (deferredGlobalTemplateStringsArrayType = getGlobalType("TemplateStringsArray" as __String, /*arity*/ 0, /*reportErrors*/ true)) || emptyObjectType; } function getGlobalESSymbolConstructorSymbol(reportErrors: boolean) { - return deferredGlobalESSymbolConstructorSymbol || (deferredGlobalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol" as UnderscoreEscapedString, reportErrors)); + return deferredGlobalESSymbolConstructorSymbol || (deferredGlobalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol" as __String, reportErrors)); } function getGlobalESSymbolType(reportErrors: boolean) { - return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol" as UnderscoreEscapedString, /*arity*/ 0, reportErrors)) || emptyObjectType; + return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType; } function getGlobalPromiseType(reportErrors: boolean) { - return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise" as UnderscoreEscapedString, /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalPromiseConstructorSymbol(reportErrors: boolean): Symbol | undefined { - return deferredGlobalPromiseConstructorSymbol || (deferredGlobalPromiseConstructorSymbol = getGlobalValueSymbol("Promise" as UnderscoreEscapedString, reportErrors)); + return deferredGlobalPromiseConstructorSymbol || (deferredGlobalPromiseConstructorSymbol = getGlobalValueSymbol("Promise" as __String, reportErrors)); } function getGlobalPromiseConstructorLikeType(reportErrors: boolean) { - return deferredGlobalPromiseConstructorLikeType || (deferredGlobalPromiseConstructorLikeType = getGlobalType("PromiseConstructorLike" as UnderscoreEscapedString, /*arity*/ 0, reportErrors)) || emptyObjectType; + return deferredGlobalPromiseConstructorLikeType || (deferredGlobalPromiseConstructorLikeType = getGlobalType("PromiseConstructorLike" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType; } function getGlobalAsyncIterableType(reportErrors: boolean) { - return deferredGlobalAsyncIterableType || (deferredGlobalAsyncIterableType = getGlobalType("AsyncIterable" as UnderscoreEscapedString, /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIterableType || (deferredGlobalAsyncIterableType = getGlobalType("AsyncIterable" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalAsyncIteratorType(reportErrors: boolean) { - return deferredGlobalAsyncIteratorType || (deferredGlobalAsyncIteratorType = getGlobalType("AsyncIterator" as UnderscoreEscapedString, /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIteratorType || (deferredGlobalAsyncIteratorType = getGlobalType("AsyncIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalAsyncIterableIteratorType(reportErrors: boolean) { - return deferredGlobalAsyncIterableIteratorType || (deferredGlobalAsyncIterableIteratorType = getGlobalType("AsyncIterableIterator" as UnderscoreEscapedString, /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIterableIteratorType || (deferredGlobalAsyncIterableIteratorType = getGlobalType("AsyncIterableIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIterableType(reportErrors: boolean) { - return deferredGlobalIterableType || (deferredGlobalIterableType = getGlobalType("Iterable" as UnderscoreEscapedString, /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalIterableType || (deferredGlobalIterableType = getGlobalType("Iterable" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIteratorType(reportErrors: boolean) { - return deferredGlobalIteratorType || (deferredGlobalIteratorType = getGlobalType("Iterator" as UnderscoreEscapedString, /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalIteratorType || (deferredGlobalIteratorType = getGlobalType("Iterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIterableIteratorType(reportErrors: boolean) { - return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType("IterableIterator" as UnderscoreEscapedString, /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType("IterableIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } - function getGlobalTypeOrUndefined(name: UnderscoreEscapedString, arity = 0): ObjectType { + function getGlobalTypeOrUndefined(name: __String, arity = 0): ObjectType { const symbol = getGlobalSymbol(name, SymbolFlags.Type, /*diagnostic*/ undefined); return symbol && getTypeOfGlobalSymbol(symbol, arity); } @@ -7059,7 +7059,7 @@ namespace ts { * Returns a type that is inside a namespace at the global scope, e.g. * getExportedTypeFromNamespace('JSX', 'Element') returns the JSX.Element type */ - function getExportedTypeFromNamespace(namespace: UnderscoreEscapedString, name: UnderscoreEscapedString): Type { + function getExportedTypeFromNamespace(namespace: __String, name: __String): Type { const namespaceSymbol = getGlobalSymbol(namespace, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined); const typeSymbol = namespaceSymbol && getSymbol(namespaceSymbol.exports, name, SymbolFlags.Type); return typeSymbol && getDeclaredTypeOfSymbol(typeSymbol); @@ -7117,7 +7117,7 @@ namespace ts { for (let i = 0; i < arity; i++) { const typeParameter = createType(TypeFlags.TypeParameter); typeParameters.push(typeParameter); - const property = createSymbol(SymbolFlags.Property, "" + i as UnderscoreEscapedString); + const property = createSymbol(SymbolFlags.Property, "" + i as __String); property.type = typeParameter; properties.push(property); } @@ -9898,7 +9898,7 @@ namespace ts { } function isTupleLikeType(type: Type): boolean { - return !!getPropertyOfType(type, "0" as UnderscoreEscapedString); + return !!getPropertyOfType(type, "0" as __String); } function isUnitType(type: Type): boolean { @@ -10753,7 +10753,7 @@ namespace ts { return undefined; } - function isDiscriminantProperty(type: Type, name: UnderscoreEscapedString) { + function isDiscriminantProperty(type: Type, name: __String) { if (type && type.flags & TypeFlags.Union) { const prop = getUnionOrIntersectionProperty(type, name); if (prop && getCheckFlags(prop) & CheckFlags.SyntheticProperty) { @@ -10834,7 +10834,7 @@ namespace ts { // check. This gives us a quicker out in the common case where an object type is not a function. const resolved = resolveStructuredTypeMembers(type); return !!(resolved.callSignatures.length || resolved.constructSignatures.length || - resolved.members.get("bind" as UnderscoreEscapedString) && isTypeSubtypeOf(type, globalFunctionType)); + resolved.members.get("bind" as __String) && isTypeSubtypeOf(type, globalFunctionType)); } function getTypeFacts(type: Type): TypeFacts { @@ -10912,7 +10912,7 @@ namespace ts { } function getTypeOfDestructuredArrayElement(type: Type, index: number) { - return isTupleLikeType(type) && getTypeOfPropertyOfType(type, "" + index as UnderscoreEscapedString) || + return isTupleLikeType(type) && getTypeOfPropertyOfType(type, "" + index as __String) || checkIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || unknownType; } @@ -11745,7 +11745,7 @@ namespace ts { } let targetType: Type; - const prototypeProperty = getPropertyOfType(rightType, "prototype" as UnderscoreEscapedString); + const prototypeProperty = getPropertyOfType(rightType, "prototype" as __String); if (prototypeProperty) { // Target type is type of the prototype property const prototypePropertyType = getTypeOfSymbol(prototypeProperty); @@ -12836,7 +12836,7 @@ namespace ts { return undefined; } - function getTypeOfPropertyOfContextualType(type: Type, name: UnderscoreEscapedString) { + function getTypeOfPropertyOfContextualType(type: Type, name: __String) { return mapType(type, t => { const prop = t.flags & TypeFlags.StructuredType ? getPropertyOfType(t, name) : undefined; return prop ? getTypeOfSymbol(prop) : undefined; @@ -12896,7 +12896,7 @@ namespace ts { const type = getApparentTypeOfContextualType(arrayLiteral); if (type) { const index = indexOf(arrayLiteral.elements, node); - return getTypeOfPropertyOfContextualType(type, "" + index as UnderscoreEscapedString) + return getTypeOfPropertyOfContextualType(type, "" + index as __String) || getIndexTypeOfContextualType(type, IndexKind.Number) || getIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false, /*checkAssignability*/ false); } @@ -13228,11 +13228,11 @@ namespace ts { return isTypeAny(type) || isTypeOfKind(type, kind); } - function isInfinityOrNaNString(name: string | UnderscoreEscapedString): boolean { + function isInfinityOrNaNString(name: string | __String): boolean { return name === "Infinity" || name === "-Infinity" || name === "NaN"; } - function isNumericLiteralName(name: string | UnderscoreEscapedString) { + function isNumericLiteralName(name: string | __String) { // The intent of numeric names is that // - they are names with text in a numeric form, and that // - setting properties/indexing with them is always equivalent to doing so with the numeric literal 'numLit', @@ -13498,7 +13498,7 @@ namespace ts { /** * Returns true iff the JSX element name would be a valid JS identifier, ignoring restrictions about keywords not being identifiers */ - function isUnhyphenatedJsxName(name: string | UnderscoreEscapedString) { + function isUnhyphenatedJsxName(name: string | __String) { // - is the only character supported in JSX attribute names that isn't valid in JavaScript identifiers return (name as string).indexOf("-") < 0; } @@ -13657,7 +13657,7 @@ namespace ts { return createJsxAttributesTypeFromAttributesProperty(node.parent as JsxOpeningLikeElement, /*filter*/ undefined, checkMode); } - function getJsxType(name: UnderscoreEscapedString) { + function getJsxType(name: __String) { let jsxType = jsxTypes.get(name); if (jsxType === undefined) { jsxTypes.set(name, jsxType = getExportedTypeFromNamespace(JsxNames.JSX, name) || unknownType); @@ -13749,7 +13749,7 @@ namespace ts { * @param nameOfAttribPropContainer a string of value JsxNames.ElementAttributesPropertyNameContainer or JsxNames.ElementChildrenAttributeNameContainer * if other string is given or the container doesn't exist, return undefined. */ - function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: UnderscoreEscapedString): UnderscoreEscapedString { + function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: __String): __String { // JSX const jsxNamespace = getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined); // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [symbol] @@ -13761,7 +13761,7 @@ namespace ts { if (propertiesOfJsxElementAttribPropInterface) { // Element Attributes has zero properties, so the element attributes type will be the class instance type if (propertiesOfJsxElementAttribPropInterface.length === 0) { - return "" as UnderscoreEscapedString; + return "" as __String; } // Element Attributes has one property, so the element attributes type will be the type of the corresponding // property of the class instance type @@ -13790,7 +13790,7 @@ namespace ts { return _jsxElementPropertiesName; } - function getJsxElementChildrenPropertyname(): UnderscoreEscapedString { + function getJsxElementChildrenPropertyname(): __String { if (!_hasComputedJsxElementChildrenPropertyName) { _hasComputedJsxElementChildrenPropertyName = true; _jsxElementChildrenPropertyName = getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer); @@ -14190,7 +14190,7 @@ namespace ts { * @param name a property name to search * @param isComparingJsxAttributes a boolean flag indicating whether we are searching in JsxAttributesType */ - function isKnownProperty(targetType: Type, name: UnderscoreEscapedString, isComparingJsxAttributes: boolean): boolean { + function isKnownProperty(targetType: Type, name: __String, isComparingJsxAttributes: boolean): boolean { if (targetType.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(targetType); if (resolved.stringIndexInfo || @@ -14493,12 +14493,12 @@ namespace ts { diagnostics.add(createDiagnosticForNodeFromMessageChain(propNode, errorInfo)); } - function getSuggestionForNonexistentProperty(node: Identifier, containingType: Type): UnderscoreEscapedString | undefined { + function getSuggestionForNonexistentProperty(node: Identifier, containingType: Type): __String | undefined { const suggestion = getSpellingSuggestionForName(unescapeLeadingUnderscores(node.text), getPropertiesOfType(containingType), SymbolFlags.Value); return suggestion && suggestion.name; } - function getSuggestionForNonexistentSymbol(location: Node, name: UnderscoreEscapedString, meaning: SymbolFlags): UnderscoreEscapedString { + function getSuggestionForNonexistentSymbol(location: Node, name: __String, meaning: SymbolFlags): __String { const result = resolveNameHelper(location, name, meaning, /*nameNotFoundMessage*/ undefined, name, (symbols, name, meaning) => { const symbol = getSymbol(symbols, name, meaning); if (symbol) { @@ -14603,7 +14603,7 @@ namespace ts { return false; } - function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: UnderscoreEscapedString): boolean { + function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: __String): boolean { const left = node.kind === SyntaxKind.PropertyAccessExpression ? (node).expression : (node).left; @@ -14614,7 +14614,7 @@ namespace ts { function isValidPropertyAccessWithType( node: PropertyAccessExpression | QualifiedName, left: LeftHandSideExpression | QualifiedName, - propertyName: UnderscoreEscapedString, + propertyName: __String, type: Type): boolean { if (type !== unknownType && !isTypeAny(type)) { @@ -17068,7 +17068,7 @@ namespace ts { const element = elements[elementIndex]; if (element.kind !== SyntaxKind.OmittedExpression) { if (element.kind !== SyntaxKind.SpreadElement) { - const propName = "" + elementIndex as UnderscoreEscapedString; + const propName = "" + elementIndex as __String; const type = isTypeAny(sourceType) ? sourceType : isTupleLikeType(sourceType) @@ -18119,7 +18119,7 @@ namespace ts { } } - function addName(names: UnderscoreEscapedMap, location: Node, name: UnderscoreEscapedString, meaning: Declaration) { + function addName(names: UnderscoreEscapedMap, location: Node, name: __String, meaning: Declaration) { const prev = names.get(name); if (prev) { if (prev & Declaration.Method) { @@ -18893,7 +18893,7 @@ namespace ts { return typeAsPromise.promisedTypeOfPromise = (promise).typeArguments[0]; } - const thenFunction = getTypeOfPropertyOfType(promise, "then" as UnderscoreEscapedString); + const thenFunction = getTypeOfPropertyOfType(promise, "then" as __String); if (isTypeAny(thenFunction)) { return undefined; } @@ -19025,7 +19025,7 @@ namespace ts { // of a runtime problem. If the user wants to return this value from an async // function, they would need to wrap it in some other value. If they want it to // be treated as a promise, they can cast to . - const thenFunction = getTypeOfPropertyOfType(type, "then" as UnderscoreEscapedString); + const thenFunction = getTypeOfPropertyOfType(type, "then" as __String); if (thenFunction && getSignaturesOfType(thenFunction, SignatureKind.Call).length > 0) { if (errorNode) { Debug.assert(!!diagnosticMessage); @@ -20462,7 +20462,7 @@ namespace ts { } // Both async and non-async iterators must have a `next` method. - const nextMethod = getTypeOfPropertyOfType(type, "next" as UnderscoreEscapedString); + const nextMethod = getTypeOfPropertyOfType(type, "next" as __String); if (isTypeAny(nextMethod)) { return undefined; } @@ -20490,7 +20490,7 @@ namespace ts { } } - const nextValue = nextResult && getTypeOfPropertyOfType(nextResult, "value" as UnderscoreEscapedString); + const nextValue = nextResult && getTypeOfPropertyOfType(nextResult, "value" as __String); if (!nextValue) { if (errorNode) { error(errorNode, isAsyncIterator @@ -21370,7 +21370,7 @@ namespace ts { if (type.symbol && type.symbol.flags & SymbolFlags.Enum) { const name = expr.kind === SyntaxKind.PropertyAccessExpression ? (expr).name.text : - ((expr).argumentExpression).text as UnderscoreEscapedString; + ((expr).argumentExpression).text as __String; return evaluateEnumMember(expr, type.symbol, name); } } @@ -21379,7 +21379,7 @@ namespace ts { return undefined; } - function evaluateEnumMember(expr: Expression, enumSymbol: Symbol, name: UnderscoreEscapedString) { + function evaluateEnumMember(expr: Expression, enumSymbol: Symbol, name: __String) { const memberSymbol = enumSymbol.exports.get(name); if (memberSymbol) { const declaration = memberSymbol.valueDeclaration; @@ -21902,7 +21902,7 @@ namespace ts { const moduleSymbol = getSymbolOfNode(node); const links = getSymbolLinks(moduleSymbol); if (!links.exportsChecked) { - const exportEqualsSymbol = moduleSymbol.exports.get("export=" as UnderscoreEscapedString); + const exportEqualsSymbol = moduleSymbol.exports.get("export=" as __String); if (exportEqualsSymbol && hasExportedMembers(moduleSymbol)) { const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration; if (!isTopLevelInExternalModuleAugmentation(declaration)) { @@ -22615,7 +22615,7 @@ namespace ts { if (objectType === unknownType) return undefined; const apparentType = getApparentType(objectType); if (apparentType === unknownType) return undefined; - return getPropertyOfType(apparentType, (node).text as UnderscoreEscapedString); + return getPropertyOfType(apparentType, (node).text as __String); } break; } @@ -23452,23 +23452,23 @@ namespace ts { addToSymbolTable(globals, builtinGlobals, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0); getSymbolLinks(undefinedSymbol).type = undefinedWideningType; - getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments" as UnderscoreEscapedString, /*arity*/ 0, /*reportErrors*/ true); + getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments" as __String, /*arity*/ 0, /*reportErrors*/ true); getSymbolLinks(unknownSymbol).type = unknownType; // Initialize special types - globalArrayType = getGlobalType("Array" as UnderscoreEscapedString, /*arity*/ 1, /*reportErrors*/ true); - globalObjectType = getGlobalType("Object" as UnderscoreEscapedString, /*arity*/ 0, /*reportErrors*/ true); - globalFunctionType = getGlobalType("Function" as UnderscoreEscapedString, /*arity*/ 0, /*reportErrors*/ true); - globalStringType = getGlobalType("String" as UnderscoreEscapedString, /*arity*/ 0, /*reportErrors*/ true); - globalNumberType = getGlobalType("Number" as UnderscoreEscapedString, /*arity*/ 0, /*reportErrors*/ true); - globalBooleanType = getGlobalType("Boolean" as UnderscoreEscapedString, /*arity*/ 0, /*reportErrors*/ true); - globalRegExpType = getGlobalType("RegExp" as UnderscoreEscapedString, /*arity*/ 0, /*reportErrors*/ true); + globalArrayType = getGlobalType("Array" as __String, /*arity*/ 1, /*reportErrors*/ true); + globalObjectType = getGlobalType("Object" as __String, /*arity*/ 0, /*reportErrors*/ true); + globalFunctionType = getGlobalType("Function" as __String, /*arity*/ 0, /*reportErrors*/ true); + globalStringType = getGlobalType("String" as __String, /*arity*/ 0, /*reportErrors*/ true); + globalNumberType = getGlobalType("Number" as __String, /*arity*/ 0, /*reportErrors*/ true); + globalBooleanType = getGlobalType("Boolean" as __String, /*arity*/ 0, /*reportErrors*/ true); + globalRegExpType = getGlobalType("RegExp" as __String, /*arity*/ 0, /*reportErrors*/ true); anyArrayType = createArrayType(anyType); autoArrayType = createArrayType(autoType); - globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray" as UnderscoreEscapedString, /*arity*/ 1); + globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray" as __String, /*arity*/ 1); anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; - globalThisType = getGlobalTypeOrUndefined("ThisType" as UnderscoreEscapedString, /*arity*/ 1); + globalThisType = getGlobalTypeOrUndefined("ThisType" as __String, /*arity*/ 1); } function checkExternalEmitHelpers(location: Node, helpers: ExternalEmitHelpers) { diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 7e96d828b5a71..1520c162a836f 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1016,13 +1016,13 @@ namespace ts { * Calls `callback` for each entry in the map, returning the first truthy result. * Use `map.forEach` instead for normal iteration. */ - export function forEachEntry(map: UnderscoreEscapedMap, callback: (value: T, key: UnderscoreEscapedString) => U | undefined): U | undefined; + export function forEachEntry(map: UnderscoreEscapedMap, callback: (value: T, key: __String) => U | undefined): U | undefined; export function forEachEntry(map: Map, callback: (value: T, key: string) => U | undefined): U | undefined; - export function forEachEntry(map: UnderscoreEscapedMap | Map, callback: (value: T, key: (string & UnderscoreEscapedString)) => U | undefined): U | undefined { + export function forEachEntry(map: UnderscoreEscapedMap | Map, callback: (value: T, key: (string & __String)) => U | undefined): U | undefined { const iterator = map.entries(); for (let { value: pair, done } = iterator.next(); !done; { value: pair, done } = iterator.next()) { const [key, value] = pair; - const result = callback(value, key as (string & UnderscoreEscapedString)); + const result = callback(value, key as (string & __String)); if (result) { return result; } @@ -1031,12 +1031,12 @@ namespace ts { } /** `forEachEntry` for just keys. */ - export function forEachKey(map: UnderscoreEscapedMap<{}>, callback: (key: UnderscoreEscapedString) => T | undefined): T | undefined; + export function forEachKey(map: UnderscoreEscapedMap<{}>, callback: (key: __String) => T | undefined): T | undefined; export function forEachKey(map: Map<{}>, callback: (key: string) => T | undefined): T | undefined; - export function forEachKey(map: UnderscoreEscapedMap<{}> | Map<{}>, callback: (key: string & UnderscoreEscapedString) => T | undefined): T | undefined { + export function forEachKey(map: UnderscoreEscapedMap<{}> | Map<{}>, callback: (key: string & __String) => T | undefined): T | undefined { const iterator = map.keys(); for (let { value: key, done } = iterator.next(); !done; { value: key, done } = iterator.next()) { - const result = callback(key as string & UnderscoreEscapedString); + const result = callback(key as string & __String); if (result) { return result; } @@ -2296,13 +2296,13 @@ namespace ts { getTokenConstructor(): new (kind: TKind, pos?: number, end?: number) => Token; getIdentifierConstructor(): new (kind: SyntaxKind.Identifier, pos?: number, end?: number) => Identifier; getSourceFileConstructor(): new (kind: SyntaxKind.SourceFile, pos?: number, end?: number) => SourceFile; - getSymbolConstructor(): new (flags: SymbolFlags, name: UnderscoreEscapedString) => Symbol; + getSymbolConstructor(): new (flags: SymbolFlags, name: __String) => Symbol; getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type; getSignatureConstructor(): new (checker: TypeChecker) => Signature; getSourceMapSourceConstructor(): new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource; } - function Symbol(this: Symbol, flags: SymbolFlags, name: UnderscoreEscapedString) { + function Symbol(this: Symbol, flags: SymbolFlags, name: __String) { this.flags = flags; this.name = name; this.declarations = undefined; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 4e90570d1ec87..8e72a4bb08b8b 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1178,7 +1178,7 @@ namespace ts { } const result = createNode(kind, scanner.getStartPos()); - (result).text = "" as UnderscoreEscapedString; + (result).text = "" as __String; return finishNode(result); } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index b276a68ec5bbf..70bb2a4607d82 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -405,7 +405,7 @@ namespace ts { let commonSourceDirectory: string; let diagnosticsProducingTypeChecker: TypeChecker; let noDiagnosticsTypeChecker: TypeChecker; - let classifiableNames: UnderscoreEscapedMap; + let classifiableNames: UnderscoreEscapedMap<__String>; let modifiedFilePaths: Path[] | undefined; const cachedSemanticDiagnosticsForFile: DiagnosticCache = {}; @@ -580,7 +580,7 @@ namespace ts { if (!classifiableNames) { // Initialize a checker so that all our files are bound. getTypeChecker(); - classifiableNames = createUnderscoreEscapedMap(); + classifiableNames = createUnderscoreEscapedMap<__String>(); for (const sourceFile of files) { copyEntries(sourceFile.classifiableNames, classifiableNames); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a937398d9cfb2..829027c903948 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -589,7 +589,7 @@ namespace ts { * Text of identifier (with escapes converted to characters). * If the identifier begins with two underscores, this will begin with three. */ - text: UnderscoreEscapedString; + text: __String; originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later /*@internal*/ autoGenerateKind?: GeneratedIdentifierKind; // Specifies whether to auto-generate the text for an identifier. /*@internal*/ autoGenerateId?: number; // Ensures unique generated identifiers get unique names, but clones get the same name. @@ -2357,7 +2357,7 @@ namespace ts { // Stores a line map for the file. // This field should never be used directly to obtain line map, use getLineMap function instead. /* @internal */ lineMap: number[]; - /* @internal */ classifiableNames?: UnderscoreEscapedMap; + /* @internal */ classifiableNames?: UnderscoreEscapedMap<__String>; // Stores a mapping 'external module reference text' -> 'resolved file name' | undefined // It is used to resolve module names in the checker. // Content of this field should never be used directly - use getResolvedModuleFileName/setResolvedModuleFileName functions instead @@ -2463,7 +2463,7 @@ namespace ts { /* @internal */ getDiagnosticsProducingTypeChecker(): TypeChecker; /* @internal */ dropDiagnosticsProducingTypeChecker(): void; - /* @internal */ getClassifiableNames(): UnderscoreEscapedMap; + /* @internal */ getClassifiableNames(): UnderscoreEscapedMap<__String>; /* @internal */ getNodeCount(): number; /* @internal */ getIdentifierCount(): number; @@ -2937,7 +2937,7 @@ namespace ts { export interface Symbol { flags: SymbolFlags; // Symbol flags - name: UnderscoreEscapedString; // Name of symbol + name: __String; // Name of symbol declarations?: Declaration[]; // Declarations associated with this symbol valueDeclaration?: Declaration; // First value declaration of the symbol members?: SymbolTable; // Class, interface or literal instance members @@ -3006,22 +3006,22 @@ namespace ts { } export const enum InternalSymbolName { - "__call" = "__call", // Call signatures - "__constructor" = "__constructor", // Constructor implementations - "__new" = "__new", // Constructor signatures - "__index" = "__index", // Index signatures - "__export" = "__export", // Module export * declarations - "__global" = "__global", // Global self-reference - "__missing" = "__missing", // Indicates missing symbol - "__type" = "__type", // Anonymous type literal symbol - "__object" = "__object", // Anonymous object literal declaration - "__jsxAttributes" = "__jsxAttributes", // Anonymous JSX attributes object literal declaration - "__class" = "__class", // Unnamed class expression - "__function" = "__function", // Unnamed function expression - "__computed" = "__computed", // Computed property name declaration with dynamic name - "__resolving__" = "__resolving__", // Indicator symbol used to mark partially resolved type aliases - "export=" = "export=", // Export assignment symbol - "default" = "default", // Default export symbol (technically not wholly internal, but included here for usability) + Call = "__call", // Call signatures + Constructor = "__constructor", // Constructor implementations + New = "__new", // Constructor signatures + Index = "__index", // Index signatures + ExportStar = "__export", // Module export * declarations + Global = "__global", // Global self-reference + Missing = "__missing", // Indicates missing symbol + Type = "__type", // Anonymous type literal symbol + Object = "__object", // Anonymous object literal declaration + JSXAttributes = "__jsxAttributes", // Anonymous JSX attributes object literal declaration + Class = "__class", // Unnamed class expression + Function = "__function", // Unnamed function expression + Computed = "__computed", // Computed property name declaration with dynamic name + Resolving = "__resolving__", // Indicator symbol used to mark partially resolved type aliases + ExportEquals = "export=", // Export assignment symbol + Default = "default", // Default export symbol (technically not wholly internal, but included here for usability) } /** @@ -3032,20 +3032,20 @@ namespace ts { * with a normal string (which is good, it cannot be misused on assignment or on usage), * while still being comparable with a normal string via === (also good) and castable from a string. */ - export type UnderscoreEscapedString = (string & { __escapedIdentifier: void }) | (void & { __escapedIdentifier: void }) | InternalSymbolName; + export type __String = (string & { __escapedIdentifier: void }) | (void & { __escapedIdentifier: void }) | InternalSymbolName; /** EscapedStringMap based on ES6 Map interface. */ export interface UnderscoreEscapedMap { - get(key: UnderscoreEscapedString): T | undefined; - has(key: UnderscoreEscapedString): boolean; - set(key: UnderscoreEscapedString, value: T): this; - delete(key: UnderscoreEscapedString): boolean; + get(key: __String): T | undefined; + has(key: __String): boolean; + set(key: __String, value: T): this; + delete(key: __String): boolean; clear(): void; - forEach(action: (value: T, key: UnderscoreEscapedString) => void): void; + forEach(action: (value: T, key: __String) => void): void; readonly size: number; - keys(): Iterator; + keys(): Iterator<__String>; values(): Iterator; - entries(): Iterator<[UnderscoreEscapedString, T]>; + entries(): Iterator<[__String, T]>; } /** SymbolTable based on ES6 Map interface. */ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 5a9e07bfeb517..006df07d22d13 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -351,8 +351,8 @@ namespace ts { } // Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__' - export function escapeLeadingUnderscores(identifier: string): UnderscoreEscapedString { - return (identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier) as UnderscoreEscapedString; + export function escapeLeadingUnderscores(identifier: string): __String { + return (identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier) as __String; } /** @@ -475,7 +475,7 @@ namespace ts { return info.declaration ? declarationNameToString(info.declaration.parameters[0].name) : undefined; } - export function getTextOfPropertyName(name: PropertyName): UnderscoreEscapedString { + export function getTextOfPropertyName(name: PropertyName): __String { switch (name.kind) { case SyntaxKind.Identifier: return (name).text; @@ -1967,7 +1967,7 @@ namespace ts { return isPropertyAccessExpression(node) && isESSymbolIdentifier(node.expression); } - export function getPropertyNameForPropertyNameNode(name: DeclarationName): UnderscoreEscapedString { + export function getPropertyNameForPropertyNameNode(name: DeclarationName): __String { if (name.kind === SyntaxKind.Identifier) { return name.text; } @@ -2018,8 +2018,8 @@ namespace ts { return undefined; } - export function getPropertyNameForKnownSymbolName(symbolName: string): UnderscoreEscapedString { - return "__@" + symbolName as UnderscoreEscapedString; + export function getPropertyNameForKnownSymbolName(symbolName: string): __String { + return "__@" + symbolName as __String; } /** @@ -2385,7 +2385,7 @@ namespace ts { return escapedCharsMap.get(c) || get16BitUnicodeEscapeSequence(c.charCodeAt(0)); } - export function isIntrinsicJsxName(name: UnderscoreEscapedString | string) { + export function isIntrinsicJsxName(name: __String | string) { // An escaped identifier had a leading underscore prior to being escaped, which would return true // The escape adds an extra underscore which does not change the result const ch = (name as string).substr(0, 1); @@ -4017,7 +4017,7 @@ namespace ts { * @param identifier The escaped identifier text. * @returns The unescaped identifier text. */ - export function unescapeLeadingUnderscores(identifier: UnderscoreEscapedString): string { + export function unescapeLeadingUnderscores(identifier: __String): string { const id = identifier as string; return id.length >= 3 && id.charCodeAt(0) === CharacterCodes._ && id.charCodeAt(1) === CharacterCodes._ && id.charCodeAt(2) === CharacterCodes._ ? id.substr(1) : id; } @@ -4029,7 +4029,7 @@ namespace ts { * @returns The unescaped identifier text. */ export function unescapeIdentifier(id: string): string { - return unescapeLeadingUnderscores(id as UnderscoreEscapedString); + return unescapeLeadingUnderscores(id as __String); } export function getNameOfDeclaration(declaration: Declaration): DeclarationName | undefined { diff --git a/src/services/classifier.ts b/src/services/classifier.ts index 0309c1d309236..793d59616f631 100644 --- a/src/services/classifier.ts +++ b/src/services/classifier.ts @@ -462,7 +462,7 @@ namespace ts { } /* @internal */ - export function getSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: UnderscoreEscapedMap, span: TextSpan): ClassifiedSpan[] { + export function getSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: UnderscoreEscapedMap<__String>, span: TextSpan): ClassifiedSpan[] { return convertClassifications(getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span)); } @@ -487,7 +487,7 @@ namespace ts { } /* @internal */ - export function getEncodedSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: UnderscoreEscapedMap, span: TextSpan): Classifications { + export function getEncodedSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: UnderscoreEscapedMap<__String>, span: TextSpan): Classifications { const result: number[] = []; processNode(sourceFile); diff --git a/src/services/completions.ts b/src/services/completions.ts index ff4061b02aea1..7c29d67fd7549 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1494,7 +1494,7 @@ namespace ts.Completions { continue; } - let existingName: UnderscoreEscapedString; + let existingName: __String; if (m.kind === SyntaxKind.BindingElement && (m).propertyName) { // include only identifiers in completion list diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index ffc794070caee..8c6cfc3185a29 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -432,7 +432,7 @@ namespace ts.FindAllReferences.Core { readonly location: Node; readonly symbol: Symbol; readonly text: string; - readonly escapedText: UnderscoreEscapedString; + readonly escapedText: __String; /** Only set if `options.implementations` is true. These are the symbols checked to get the implementations of a property access. */ readonly parents: Symbol[] | undefined; @@ -977,7 +977,7 @@ namespace ts.FindAllReferences.Core { * Reference the constructor and all calls to `new this()`. */ function findOwnConstructorReferences(classSymbol: Symbol, sourceFile: SourceFile, addNode: (node: Node) => void): void { - for (const decl of classSymbol.members.get("__constructor").declarations) { + for (const decl of classSymbol.members.get(InternalSymbolName.Constructor).declarations) { const ctrKeyword = ts.findChildOfKind(decl, ts.SyntaxKind.ConstructorKeyword, sourceFile)!; Debug.assert(decl.kind === SyntaxKind.Constructor && !!ctrKeyword); addNode(ctrKeyword); @@ -1001,7 +1001,7 @@ namespace ts.FindAllReferences.Core { /** Find references to `super` in the constructor of an extending class. */ function findSuperConstructorAccesses(cls: ClassLikeDeclaration, addNode: (node: Node) => void): void { const symbol = cls.symbol; - const ctr = symbol.members.get("__constructor"); + const ctr = symbol.members.get(InternalSymbolName.Constructor); if (!ctr) { return; } diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index deaec5a505942..ecd52baa7ddb6 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -595,7 +595,7 @@ namespace ts.FindAllReferences { return isExternalModuleSymbol(exportingModuleSymbol) ? { exportingModuleSymbol, exportKind } : undefined; } - function symbolName(symbol: Symbol): UnderscoreEscapedString | undefined { + function symbolName(symbol: Symbol): __String | undefined { if (symbol.name !== "default") { return symbol.getName(); } diff --git a/src/services/services.ts b/src/services/services.ts index f82b82be48fb8..d438948fa11e6 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -304,7 +304,7 @@ namespace ts { class SymbolObject implements Symbol { flags: SymbolFlags; - name: UnderscoreEscapedString; + name: __String; declarations?: Declaration[]; // Undefined is used to indicate the value has not been computed. If, after computing, the @@ -315,7 +315,7 @@ namespace ts { // symbol has no JSDoc tags, then the empty array will be returned. tags?: JSDocTagInfo[]; - constructor(flags: SymbolFlags, name: UnderscoreEscapedString) { + constructor(flags: SymbolFlags, name: __String) { this.flags = flags; this.name = name; } @@ -324,7 +324,7 @@ namespace ts { return this.flags; } - getName(): UnderscoreEscapedString { + getName(): __String { return this.name; } @@ -364,7 +364,7 @@ namespace ts { class IdentifierObject extends TokenOrIdentifierObject implements Identifier { public kind: SyntaxKind.Identifier; - public text: UnderscoreEscapedString; + public text: __String; _primaryExpressionBrand: any; _memberExpressionBrand: any; _leftHandSideExpressionBrand: any; @@ -2115,7 +2115,7 @@ namespace ts { } } - function setNameTable(text: UnderscoreEscapedString, node: ts.Node): void { + function setNameTable(text: __String, node: ts.Node): void { nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1); } } diff --git a/src/services/types.ts b/src/services/types.ts index b4a0402536423..d440ecab28ece 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -24,7 +24,7 @@ namespace ts { export interface Symbol { getFlags(): SymbolFlags; - getName(): UnderscoreEscapedString; + getName(): __String; getUnescapedName(): string; getDeclarations(): Declaration[] | undefined; getDocumentationComment(): SymbolDisplayPart[]; From 23032d42c9464bfe2fec45eb99350102c3187c50 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 6 Jul 2017 13:54:40 -0700 Subject: [PATCH 23/25] Reorganize double underscore tests --- .../reference/doubleUnderscoreEnumEmit.js | 44 +++++++ .../doubleUnderscoreEnumEmit.symbols | 33 ++++++ .../reference/doubleUnderscoreEnumEmit.types | 43 +++++++ ...bleUnderscoreExportStarConflict.errors.txt | 15 +++ .../doubleUnderscoreExportStarConflict.js | 31 +++++ .../reference/doubleUnderscoreLabels.js | 29 +++++ .../reference/doubleUnderscoreLabels.symbols | 26 ++++ .../reference/doubleUnderscoreLabels.types | 41 +++++++ .../doubleUnderscoreReactNamespace.js | 19 +++ .../doubleUnderscoreReactNamespace.symbols | 26 ++++ .../doubleUnderscoreReactNamespace.types | 27 +++++ .../doubleUnderscoreSymbolsAndEmit.errors.txt | 60 ---------- .../doubleUnderscoreSymbolsAndEmit.js | 112 ------------------ .../compiler/doubleUnderscoreEnumEmit.ts | 19 +++ .../doubleUnderscoreExportStarConflict.ts | 11 ++ .../cases/compiler/doubleUnderscoreLabels.ts | 13 ++ .../doubleUnderscoreReactNamespace.ts | 18 +++ .../doubleUnderscoreSymbolsAndEmit.ts | 58 --------- 18 files changed, 395 insertions(+), 230 deletions(-) create mode 100644 tests/baselines/reference/doubleUnderscoreEnumEmit.js create mode 100644 tests/baselines/reference/doubleUnderscoreEnumEmit.symbols create mode 100644 tests/baselines/reference/doubleUnderscoreEnumEmit.types create mode 100644 tests/baselines/reference/doubleUnderscoreExportStarConflict.errors.txt create mode 100644 tests/baselines/reference/doubleUnderscoreExportStarConflict.js create mode 100644 tests/baselines/reference/doubleUnderscoreLabels.js create mode 100644 tests/baselines/reference/doubleUnderscoreLabels.symbols create mode 100644 tests/baselines/reference/doubleUnderscoreLabels.types create mode 100644 tests/baselines/reference/doubleUnderscoreReactNamespace.js create mode 100644 tests/baselines/reference/doubleUnderscoreReactNamespace.symbols create mode 100644 tests/baselines/reference/doubleUnderscoreReactNamespace.types delete mode 100644 tests/baselines/reference/doubleUnderscoreSymbolsAndEmit.errors.txt delete mode 100644 tests/baselines/reference/doubleUnderscoreSymbolsAndEmit.js create mode 100644 tests/cases/compiler/doubleUnderscoreEnumEmit.ts create mode 100644 tests/cases/compiler/doubleUnderscoreExportStarConflict.ts create mode 100644 tests/cases/compiler/doubleUnderscoreLabels.ts create mode 100644 tests/cases/compiler/doubleUnderscoreReactNamespace.ts delete mode 100644 tests/cases/compiler/doubleUnderscoreSymbolsAndEmit.ts diff --git a/tests/baselines/reference/doubleUnderscoreEnumEmit.js b/tests/baselines/reference/doubleUnderscoreEnumEmit.js new file mode 100644 index 0000000000000..933ed55433081 --- /dev/null +++ b/tests/baselines/reference/doubleUnderscoreEnumEmit.js @@ -0,0 +1,44 @@ +//// [doubleUnderscoreEnumEmit.ts] +enum Foo { + "__a" = 1, + "(Anonymous function)" = 2, + "(Anonymous class)" = 4, + "__call" = 10 +} +namespace Foo { + export function ___call(): number { + return 5; + } +} +function Bar() { + return "no"; +} +namespace Bar { + export function __call(x: number): number { + return 5; + } +} + +//// [doubleUnderscoreEnumEmit.js] +var Foo; +(function (Foo) { + Foo[Foo["__a"] = 1] = "__a"; + Foo[Foo["(Anonymous function)"] = 2] = "(Anonymous function)"; + Foo[Foo["(Anonymous class)"] = 4] = "(Anonymous class)"; + Foo[Foo["__call"] = 10] = "__call"; +})(Foo || (Foo = {})); +(function (Foo) { + function ___call() { + return 5; + } + Foo.___call = ___call; +})(Foo || (Foo = {})); +function Bar() { + return "no"; +} +(function (Bar) { + function __call(x) { + return 5; + } + Bar.__call = __call; +})(Bar || (Bar = {})); diff --git a/tests/baselines/reference/doubleUnderscoreEnumEmit.symbols b/tests/baselines/reference/doubleUnderscoreEnumEmit.symbols new file mode 100644 index 0000000000000..4e430a29b3fd0 --- /dev/null +++ b/tests/baselines/reference/doubleUnderscoreEnumEmit.symbols @@ -0,0 +1,33 @@ +=== tests/cases/compiler/doubleUnderscoreEnumEmit.ts === +enum Foo { +>Foo : Symbol(Foo, Decl(doubleUnderscoreEnumEmit.ts, 0, 0), Decl(doubleUnderscoreEnumEmit.ts, 5, 1)) + + "__a" = 1, + "(Anonymous function)" = 2, + "(Anonymous class)" = 4, + "__call" = 10 +} +namespace Foo { +>Foo : Symbol(Foo, Decl(doubleUnderscoreEnumEmit.ts, 0, 0), Decl(doubleUnderscoreEnumEmit.ts, 5, 1)) + + export function ___call(): number { +>___call : Symbol(___call, Decl(doubleUnderscoreEnumEmit.ts, 6, 15)) + + return 5; + } +} +function Bar() { +>Bar : Symbol(Bar, Decl(doubleUnderscoreEnumEmit.ts, 10, 1), Decl(doubleUnderscoreEnumEmit.ts, 13, 1)) + + return "no"; +} +namespace Bar { +>Bar : Symbol(Bar, Decl(doubleUnderscoreEnumEmit.ts, 10, 1), Decl(doubleUnderscoreEnumEmit.ts, 13, 1)) + + export function __call(x: number): number { +>__call : Symbol(__call, Decl(doubleUnderscoreEnumEmit.ts, 14, 15)) +>x : Symbol(x, Decl(doubleUnderscoreEnumEmit.ts, 15, 27)) + + return 5; + } +} diff --git a/tests/baselines/reference/doubleUnderscoreEnumEmit.types b/tests/baselines/reference/doubleUnderscoreEnumEmit.types new file mode 100644 index 0000000000000..550b520c6bbc7 --- /dev/null +++ b/tests/baselines/reference/doubleUnderscoreEnumEmit.types @@ -0,0 +1,43 @@ +=== tests/cases/compiler/doubleUnderscoreEnumEmit.ts === +enum Foo { +>Foo : Foo + + "__a" = 1, +>1 : 1 + + "(Anonymous function)" = 2, +>2 : 2 + + "(Anonymous class)" = 4, +>4 : 4 + + "__call" = 10 +>10 : 10 +} +namespace Foo { +>Foo : typeof Foo + + export function ___call(): number { +>___call : () => number + + return 5; +>5 : 5 + } +} +function Bar() { +>Bar : typeof Bar + + return "no"; +>"no" : "no" +} +namespace Bar { +>Bar : typeof Bar + + export function __call(x: number): number { +>__call : (x: number) => number +>x : number + + return 5; +>5 : 5 + } +} diff --git a/tests/baselines/reference/doubleUnderscoreExportStarConflict.errors.txt b/tests/baselines/reference/doubleUnderscoreExportStarConflict.errors.txt new file mode 100644 index 0000000000000..cb96df30ca90f --- /dev/null +++ b/tests/baselines/reference/doubleUnderscoreExportStarConflict.errors.txt @@ -0,0 +1,15 @@ +tests/cases/compiler/index.tsx(2,1): error TS2308: Module "./b" has already exported a member named '__foo'. Consider explicitly re-exporting to resolve the ambiguity. + + +==== tests/cases/compiler/index.tsx (1 errors) ==== + export * from "./b"; + export * from "./c"; + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2308: Module "./b" has already exported a member named '__foo'. Consider explicitly re-exporting to resolve the ambiguity. + +==== tests/cases/compiler/b.ts (0 errors) ==== + export function __foo(): number | void {} + +==== tests/cases/compiler/c.ts (0 errors) ==== + export function __foo(): string | void {} + \ No newline at end of file diff --git a/tests/baselines/reference/doubleUnderscoreExportStarConflict.js b/tests/baselines/reference/doubleUnderscoreExportStarConflict.js new file mode 100644 index 0000000000000..e73c586852575 --- /dev/null +++ b/tests/baselines/reference/doubleUnderscoreExportStarConflict.js @@ -0,0 +1,31 @@ +//// [tests/cases/compiler/doubleUnderscoreExportStarConflict.ts] //// + +//// [index.tsx] +export * from "./b"; +export * from "./c"; + +//// [b.ts] +export function __foo(): number | void {} + +//// [c.ts] +export function __foo(): string | void {} + + +//// [b.js] +"use strict"; +exports.__esModule = true; +function __foo() { } +exports.__foo = __foo; +//// [c.js] +"use strict"; +exports.__esModule = true; +function __foo() { } +exports.__foo = __foo; +//// [index.js] +"use strict"; +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +exports.__esModule = true; +__export(require("./b")); +__export(require("./c")); diff --git a/tests/baselines/reference/doubleUnderscoreLabels.js b/tests/baselines/reference/doubleUnderscoreLabels.js new file mode 100644 index 0000000000000..e8c3c8506014e --- /dev/null +++ b/tests/baselines/reference/doubleUnderscoreLabels.js @@ -0,0 +1,29 @@ +//// [doubleUnderscoreLabels.ts] +function doThing() { + __call: while (true) { + aLabel: for (let i = 0; i < 10; i++) { + if (i === 3) { + break __call; + } + if (i === 5) { + break aLabel; + } + } + } +} +doThing(); + +//// [doubleUnderscoreLabels.js] +function doThing() { + __call: while (true) { + aLabel: for (var i = 0; i < 10; i++) { + if (i === 3) { + break __call; + } + if (i === 5) { + break aLabel; + } + } + } +} +doThing(); diff --git a/tests/baselines/reference/doubleUnderscoreLabels.symbols b/tests/baselines/reference/doubleUnderscoreLabels.symbols new file mode 100644 index 0000000000000..e3fd879d330fb --- /dev/null +++ b/tests/baselines/reference/doubleUnderscoreLabels.symbols @@ -0,0 +1,26 @@ +=== tests/cases/compiler/doubleUnderscoreLabels.ts === +function doThing() { +>doThing : Symbol(doThing, Decl(doubleUnderscoreLabels.ts, 0, 0)) + + __call: while (true) { + aLabel: for (let i = 0; i < 10; i++) { +>i : Symbol(i, Decl(doubleUnderscoreLabels.ts, 2, 24)) +>i : Symbol(i, Decl(doubleUnderscoreLabels.ts, 2, 24)) +>i : Symbol(i, Decl(doubleUnderscoreLabels.ts, 2, 24)) + + if (i === 3) { +>i : Symbol(i, Decl(doubleUnderscoreLabels.ts, 2, 24)) + + break __call; + } + if (i === 5) { +>i : Symbol(i, Decl(doubleUnderscoreLabels.ts, 2, 24)) + + break aLabel; + } + } + } +} +doThing(); +>doThing : Symbol(doThing, Decl(doubleUnderscoreLabels.ts, 0, 0)) + diff --git a/tests/baselines/reference/doubleUnderscoreLabels.types b/tests/baselines/reference/doubleUnderscoreLabels.types new file mode 100644 index 0000000000000..eff425c0eed9e --- /dev/null +++ b/tests/baselines/reference/doubleUnderscoreLabels.types @@ -0,0 +1,41 @@ +=== tests/cases/compiler/doubleUnderscoreLabels.ts === +function doThing() { +>doThing : () => void + + __call: while (true) { +>__call : any +>true : true + + aLabel: for (let i = 0; i < 10; i++) { +>aLabel : any +>i : number +>0 : 0 +>i < 10 : boolean +>i : number +>10 : 10 +>i++ : number +>i : number + + if (i === 3) { +>i === 3 : boolean +>i : number +>3 : 3 + + break __call; +>__call : any + } + if (i === 5) { +>i === 5 : boolean +>i : number +>5 : 5 + + break aLabel; +>aLabel : any + } + } + } +} +doThing(); +>doThing() : void +>doThing : () => void + diff --git a/tests/baselines/reference/doubleUnderscoreReactNamespace.js b/tests/baselines/reference/doubleUnderscoreReactNamespace.js new file mode 100644 index 0000000000000..de2997d53a614 --- /dev/null +++ b/tests/baselines/reference/doubleUnderscoreReactNamespace.js @@ -0,0 +1,19 @@ +//// [index.tsx] +declare global { + namespace JSX { + interface IntrinsicElements { + __foot: any; + } + } + function __make (params: object): any; +} + + +const thing = <__foot>; + +export {} + +//// [index.js] +"use strict"; +exports.__esModule = true; +var thing = __make("__foot", null); diff --git a/tests/baselines/reference/doubleUnderscoreReactNamespace.symbols b/tests/baselines/reference/doubleUnderscoreReactNamespace.symbols new file mode 100644 index 0000000000000..3f942c5f69d66 --- /dev/null +++ b/tests/baselines/reference/doubleUnderscoreReactNamespace.symbols @@ -0,0 +1,26 @@ +=== tests/cases/compiler/index.tsx === +declare global { +>global : Symbol(global, Decl(index.tsx, 0, 0)) + + namespace JSX { +>JSX : Symbol(JSX, Decl(index.tsx, 0, 16)) + + interface IntrinsicElements { +>IntrinsicElements : Symbol(IntrinsicElements, Decl(index.tsx, 1, 19)) + + __foot: any; +>__foot : Symbol(IntrinsicElements.__foot, Decl(index.tsx, 2, 37)) + } + } + function __make (params: object): any; +>__make : Symbol(__make, Decl(index.tsx, 5, 5)) +>params : Symbol(params, Decl(index.tsx, 6, 21)) +} + + +const thing = <__foot>; +>thing : Symbol(thing, Decl(index.tsx, 10, 5)) +>__foot : Symbol(JSX.IntrinsicElements.__foot, Decl(index.tsx, 2, 37)) +>__foot : Symbol(JSX.IntrinsicElements.__foot, Decl(index.tsx, 2, 37)) + +export {} diff --git a/tests/baselines/reference/doubleUnderscoreReactNamespace.types b/tests/baselines/reference/doubleUnderscoreReactNamespace.types new file mode 100644 index 0000000000000..6a9b6d4c984c2 --- /dev/null +++ b/tests/baselines/reference/doubleUnderscoreReactNamespace.types @@ -0,0 +1,27 @@ +=== tests/cases/compiler/index.tsx === +declare global { +>global : typeof global + + namespace JSX { +>JSX : any + + interface IntrinsicElements { +>IntrinsicElements : IntrinsicElements + + __foot: any; +>__foot : any + } + } + function __make (params: object): any; +>__make : (params: object) => any +>params : object +} + + +const thing = <__foot>; +>thing : any +><__foot> : any +>__foot : any +>__foot : any + +export {} diff --git a/tests/baselines/reference/doubleUnderscoreSymbolsAndEmit.errors.txt b/tests/baselines/reference/doubleUnderscoreSymbolsAndEmit.errors.txt deleted file mode 100644 index b35e68749b840..0000000000000 --- a/tests/baselines/reference/doubleUnderscoreSymbolsAndEmit.errors.txt +++ /dev/null @@ -1,60 +0,0 @@ -tests/cases/compiler/index.tsx(33,1): error TS2308: Module "./b" has already exported a member named '__foo'. Consider explicitly re-exporting to resolve the ambiguity. - - -==== tests/cases/compiler/index.tsx (1 errors) ==== - declare global { - namespace JSX { - interface IntrinsicElements { - __foot: any; - } - } - function __make (params: object): any; - } - - enum Foo { - "__a" = 1, - "(Anonymous function)" = 2, - "(Anonymous class)" = 4, - "__call" = 10 - } - namespace Foo { - export function ___call(): number { - return 5; - } - } - function Bar() { - return "no"; - } - namespace Bar { - export function __call(x: number): number { - return 5; - } - } - - const thing = <__foot>; - - export * from "./b"; - export * from "./c"; - ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2308: Module "./b" has already exported a member named '__foo'. Consider explicitly re-exporting to resolve the ambiguity. - - function doThing() { - __call: while (true) { - aLabel: for (let i = 0; i < 10; i++) { - if (i === 3) { - break __call; - } - if (i === 5) { - break aLabel; - } - } - } - } - doThing(); - -==== tests/cases/compiler/b.ts (0 errors) ==== - export function __foo(): number | void {} - -==== tests/cases/compiler/c.ts (0 errors) ==== - export function __foo(): string | void {} - \ No newline at end of file diff --git a/tests/baselines/reference/doubleUnderscoreSymbolsAndEmit.js b/tests/baselines/reference/doubleUnderscoreSymbolsAndEmit.js deleted file mode 100644 index bee117f7d3283..0000000000000 --- a/tests/baselines/reference/doubleUnderscoreSymbolsAndEmit.js +++ /dev/null @@ -1,112 +0,0 @@ -//// [tests/cases/compiler/doubleUnderscoreSymbolsAndEmit.ts] //// - -//// [index.tsx] -declare global { - namespace JSX { - interface IntrinsicElements { - __foot: any; - } - } - function __make (params: object): any; -} - -enum Foo { - "__a" = 1, - "(Anonymous function)" = 2, - "(Anonymous class)" = 4, - "__call" = 10 -} -namespace Foo { - export function ___call(): number { - return 5; - } -} -function Bar() { - return "no"; -} -namespace Bar { - export function __call(x: number): number { - return 5; - } -} - -const thing = <__foot>; - -export * from "./b"; -export * from "./c"; - -function doThing() { - __call: while (true) { - aLabel: for (let i = 0; i < 10; i++) { - if (i === 3) { - break __call; - } - if (i === 5) { - break aLabel; - } - } - } -} -doThing(); - -//// [b.ts] -export function __foo(): number | void {} - -//// [c.ts] -export function __foo(): string | void {} - - -//// [b.js] -"use strict"; -exports.__esModule = true; -function __foo() { } -exports.__foo = __foo; -//// [c.js] -"use strict"; -exports.__esModule = true; -function __foo() { } -exports.__foo = __foo; -//// [index.js] -"use strict"; -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -exports.__esModule = true; -var Foo; -(function (Foo) { - Foo[Foo["__a"] = 1] = "__a"; - Foo[Foo["(Anonymous function)"] = 2] = "(Anonymous function)"; - Foo[Foo["(Anonymous class)"] = 4] = "(Anonymous class)"; - Foo[Foo["__call"] = 10] = "__call"; -})(Foo || (Foo = {})); -(function (Foo) { - function ___call() { - return 5; - } - Foo.___call = ___call; -})(Foo || (Foo = {})); -function Bar() { - return "no"; -} -(function (Bar) { - function __call(x) { - return 5; - } - Bar.__call = __call; -})(Bar || (Bar = {})); -var thing = __make("__foot", null); -__export(require("./b")); -__export(require("./c")); -function doThing() { - __call: while (true) { - aLabel: for (var i = 0; i < 10; i++) { - if (i === 3) { - break __call; - } - if (i === 5) { - break aLabel; - } - } - } -} -doThing(); diff --git a/tests/cases/compiler/doubleUnderscoreEnumEmit.ts b/tests/cases/compiler/doubleUnderscoreEnumEmit.ts new file mode 100644 index 0000000000000..2bea04c8a9cfa --- /dev/null +++ b/tests/cases/compiler/doubleUnderscoreEnumEmit.ts @@ -0,0 +1,19 @@ +enum Foo { + "__a" = 1, + "(Anonymous function)" = 2, + "(Anonymous class)" = 4, + "__call" = 10 +} +namespace Foo { + export function ___call(): number { + return 5; + } +} +function Bar() { + return "no"; +} +namespace Bar { + export function __call(x: number): number { + return 5; + } +} \ No newline at end of file diff --git a/tests/cases/compiler/doubleUnderscoreExportStarConflict.ts b/tests/cases/compiler/doubleUnderscoreExportStarConflict.ts new file mode 100644 index 0000000000000..cf216361f4819 --- /dev/null +++ b/tests/cases/compiler/doubleUnderscoreExportStarConflict.ts @@ -0,0 +1,11 @@ +// @module: commonjs +// @filename: index.tsx + +export * from "./b"; +export * from "./c"; + +// @filename: b.ts +export function __foo(): number | void {} + +// @filename: c.ts +export function __foo(): string | void {} diff --git a/tests/cases/compiler/doubleUnderscoreLabels.ts b/tests/cases/compiler/doubleUnderscoreLabels.ts new file mode 100644 index 0000000000000..c94b277a34998 --- /dev/null +++ b/tests/cases/compiler/doubleUnderscoreLabels.ts @@ -0,0 +1,13 @@ +function doThing() { + __call: while (true) { + aLabel: for (let i = 0; i < 10; i++) { + if (i === 3) { + break __call; + } + if (i === 5) { + break aLabel; + } + } + } +} +doThing(); \ No newline at end of file diff --git a/tests/cases/compiler/doubleUnderscoreReactNamespace.ts b/tests/cases/compiler/doubleUnderscoreReactNamespace.ts new file mode 100644 index 0000000000000..bd7789ab1d9ca --- /dev/null +++ b/tests/cases/compiler/doubleUnderscoreReactNamespace.ts @@ -0,0 +1,18 @@ +// @jsx: react +// @jsxFactory: __make +// @module: commonjs +// @filename: index.tsx + +declare global { + namespace JSX { + interface IntrinsicElements { + __foot: any; + } + } + function __make (params: object): any; +} + + +const thing = <__foot>; + +export {} \ No newline at end of file diff --git a/tests/cases/compiler/doubleUnderscoreSymbolsAndEmit.ts b/tests/cases/compiler/doubleUnderscoreSymbolsAndEmit.ts deleted file mode 100644 index 91bd8a38dc74e..0000000000000 --- a/tests/cases/compiler/doubleUnderscoreSymbolsAndEmit.ts +++ /dev/null @@ -1,58 +0,0 @@ -// @jsx: react -// @jsxFactory: __make -// @module: commonjs -// @filename: index.tsx - -declare global { - namespace JSX { - interface IntrinsicElements { - __foot: any; - } - } - function __make (params: object): any; -} - -enum Foo { - "__a" = 1, - "(Anonymous function)" = 2, - "(Anonymous class)" = 4, - "__call" = 10 -} -namespace Foo { - export function ___call(): number { - return 5; - } -} -function Bar() { - return "no"; -} -namespace Bar { - export function __call(x: number): number { - return 5; - } -} - -const thing = <__foot>; - -export * from "./b"; -export * from "./c"; - -function doThing() { - __call: while (true) { - aLabel: for (let i = 0; i < 10; i++) { - if (i === 3) { - break __call; - } - if (i === 5) { - break aLabel; - } - } - } -} -doThing(); - -// @filename: b.ts -export function __foo(): number | void {} - -// @filename: c.ts -export function __foo(): string | void {} From 008532d4425c47636dd062872916f740bbe93b71 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 6 Jul 2017 13:57:56 -0700 Subject: [PATCH 24/25] Remove jfreeman from TODO --- src/services/completions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index 7c29d67fd7549..53142b7b2da0c 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1503,11 +1503,11 @@ namespace ts.Completions { } } else { - // TODO(jfreeman): Account for computed property name + // TODO: Account for computed property name // NOTE: if one only performs this step when m.name is an identifier, // things like '__proto__' are not filtered out. const name = getNameOfDeclaration(m); - existingName = getEscapedTextOfIdentifierOrLiteral(name as (Identifier | LiteralExpression)); + existingName = getEscapedTextOfIdentifierOrLiteral(name as (Identifier | LiteralExpression)); } existingMemberNames.set(existingName, true); From 5e6b69a6d8c6ebf8f78ccd7e700ef9e8daaa9412 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 6 Jul 2017 14:26:11 -0700 Subject: [PATCH 25/25] Remove unneeded parenthesis --- src/compiler/binder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 7d170cf291714..3feba26369f63 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -259,7 +259,7 @@ namespace ts { case SyntaxKind.ExportDeclaration: return InternalSymbolName.ExportStar; case SyntaxKind.ExportAssignment: - return ((node).isExportEquals ? InternalSymbolName.ExportEquals : InternalSymbolName.Default); + return (node).isExportEquals ? InternalSymbolName.ExportEquals : InternalSymbolName.Default; case SyntaxKind.BinaryExpression: if (getSpecialPropertyAssignmentKind(node as BinaryExpression) === SpecialPropertyAssignmentKind.ModuleExports) { // module.exports = ...