diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 6975d431a112e..3feba26369f63 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -10,7 +10,7 @@ namespace ts { } interface ActiveLabel { - name: string; + 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: string): Symbol }; - let classifiableNames: Map; + 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 = createMap(); + classifiableNames = createUnderscoreEscapedMap<__String>(); symbolCount = 0; skipTransformFlagAggregation = file.isDeclarationFile; @@ -191,7 +191,7 @@ namespace ts { } } - function createSymbol(flags: SymbolFlags, name: string): Symbol { + function createSymbol(flags: SymbolFlags, name: __String): 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): __String { const name = getNameOfDeclaration(node); if (name) { if (isAmbientModule(node)) { - return isGlobalScopeAugmentation(node) ? "__global" : `"${(name).text}"`; + const moduleName = getTextOfIdentifierOrLiteral(name); + return (isGlobalScopeAugmentation(node) ? "__global" : `"${moduleName}"`) as __String; } 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 escapeLeadingUnderscores(nameExpression.text); } Debug.assert(isWellKnownSymbolSyntactically(nameExpression)); - return getPropertyNameForKnownSymbolName((nameExpression).name.text); + return getPropertyNameForKnownSymbolName(unescapeLeadingUnderscores((nameExpression).name.text)); } - return (name).text; + return getEscapedTextOfIdentifierOrLiteral(name); } 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; + return "arg" + index as __String; case SyntaxKind.JSDocTypedefTag: const parentNode = node.parent && node.parent.parent; - let nameFromParentNode: string; + let nameFromParentNode: __String; 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) : unescapeLeadingUnderscores(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 ? 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, @@ -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); } @@ -1006,7 +1007,7 @@ namespace ts { currentFlow = unreachableFlow; } - function findActiveLabel(name: string) { + function findActiveLabel(name: __String) { if (activeLabels) { for (const label of activeLabels) { if (label.name === name) { @@ -1169,7 +1170,7 @@ namespace ts { bindEach(node.statements); } - function pushActiveLabel(name: string, breakTarget: FlowLabel, continueTarget: FlowLabel): ActiveLabel { + function pushActiveLabel(name: __String, breakTarget: FlowLabel, continueTarget: FlowLabel): ActiveLabel { const activeLabel = { name, breakTarget, @@ -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, InternalSymbolName.Type); addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral); - typeLiteralSymbol.members = createMap(); + typeLiteralSymbol.members = createSymbolTable(); typeLiteralSymbol.members.set(symbol.name, symbol); } @@ -1658,14 +1659,14 @@ namespace ts { } if (inStrictMode) { - const seen = createMap(); + const seen = createUnderscoreEscapedMap(); for (const prop of node.properties) { if (prop.kind === SyntaxKind.SpreadAssignment || prop.name.kind !== SyntaxKind.Identifier) { 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 @@ -1693,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: string) { + function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: __String) { 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), unescapeLeadingUnderscores(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): __String { + return "__" + indexOf((node.parent).parameters, node) as __String; } 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, InternalSymbolName.Type); } 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 __String); } 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: __String) { 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: __String, 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 : InternalSymbolName.Class; 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 __String); 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, unescapeLeadingUnderscores(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 : InternalSymbolName.Function; return bindAnonymousDeclaration(node, SymbolFlags.Function, bindingName); } @@ -2567,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 3ac4e8e512d74..32ef2ba57942e 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 __String); undefinedSymbol.declarations = []; - const argumentsSymbol = createSymbol(SymbolFlags.Property, "arguments"); + 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; @@ -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, escapeLeadingUnderscores(parameterName)); }, getDeclaredTypeOfSymbol, getPropertiesOfType, - getPropertyOfType, + 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, 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, + 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, - getSuggestionForNonexistentSymbol, + getSuggestionForNonexistentProperty: (node, type) => unescapeLeadingUnderscores(getSuggestionForNonexistentProperty(node, type)), + getSuggestionForNonexistentSymbol: (location, name, meaning) => unescapeLeadingUnderscores(getSuggestionForNonexistentSymbol(location, escapeLeadingUnderscores(name), meaning)), getBaseConstraintOfType, - getJsxNamespace, + getJsxNamespace: () => unescapeLeadingUnderscores(getJsxNamespace()), resolveNameAtLocation(location: Node, name: string, meaning: SymbolFlags): Symbol | undefined { location = getParseTreeNode(location); - return resolveName(location, name, meaning, /*nameNotFoundMessage*/ undefined, 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"); - 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,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, InternalSymbolName.Type); + 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: __String; let _jsxFactoryEntity: EntityName; - let _jsxElementPropertiesName: string; + let _jsxElementPropertiesName: __String; let _hasComputedJsxElementPropertiesName = false; - let _jsxElementChildrenPropertyName: string; + let _jsxElementChildrenPropertyName: __String; let _hasComputedJsxElementChildrenPropertyName = false; /** Things we lazy load from the JSX namespace */ - const jsxTypes = createMap(); + const jsxTypes = createUnderscoreEscapedMap(); const JsxNames = { - JSX: "JSX", - IntrinsicElements: "IntrinsicElements", - ElementClass: "ElementClass", - ElementAttributesPropertyNameContainer: "ElementAttributesProperty", - ElementChildrenAttributeNameContainer: "ElementChildrenAttribute", - Element: "Element", - IntrinsicAttributes: "IntrinsicAttributes", - IntrinsicClassAttributes: "IntrinsicClassAttributes" + 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(); @@ -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(): __String { if (!_jsxNamespace) { - _jsxNamespace = "React"; + _jsxNamespace = "React" as __String; if (compilerOptions.jsxFactory) { _jsxFactoryEntity = parseIsolatedEntityName(compilerOptions.jsxFactory, languageVersion); if (_jsxFactoryEntity) { @@ -506,7 +506,7 @@ namespace ts { } } else if (compilerOptions.reactNamespace) { - _jsxNamespace = compilerOptions.reactNamespace; + _jsxNamespace = escapeLeadingUnderscores(compilerOptions.reactNamespace); } } return _jsxNamespace; @@ -526,7 +526,7 @@ namespace ts { diagnostics.add(diagnostic); } - function createSymbol(flags: SymbolFlags, name: string) { + function createSymbol(flags: SymbolFlags, name: __String) { 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(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: string, 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: string): [Symbol, Symbol] { + function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: __String): [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: __String, meaning: SymbolFlags, nameNotFoundMessage: DiagnosticMessage | undefined, - nameArg: string | Identifier, + nameArg: __String | Identifier, suggestedNameNotFoundMessage?: DiagnosticMessage): Symbol { return resolveNameHelper(location, name, meaning, nameNotFoundMessage, nameArg, getSymbol, suggestedNameNotFoundMessage); } function resolveNameHelper( location: Node | undefined, - name: string, + name: __String, meaning: SymbolFlags, nameNotFoundMessage: DiagnosticMessage, - nameArg: string | Identifier, - lookup: (symbols: SymbolTable, name: string, meaning: SymbolFlags) => Symbol, + 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 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 __String)) { 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: __String | 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, diagnosticName(nameArg), unescapeLeadingUnderscores(suggestion)); } } if (!suggestion) { - error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); + 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)); + declarationNameToString(propertyName), diagnosticName(nameArg)); return undefined; } @@ -1152,13 +1152,17 @@ 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, unescapeLeadingUnderscores(name)); } } } return result; } + function diagnosticName(nameArg: __String | Identifier) { + return typeof nameArg === "string" ? unescapeLeadingUnderscores(nameArg as __String) : declarationNameToString(nameArg as Identifier); + } + function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) { for (const decl of symbol.declarations) { if (decl.kind === SyntaxKind.TypeParameter && decl.parent === container) { @@ -1169,7 +1173,7 @@ namespace ts { return false; } - function checkAndReportErrorForMissingPrefix(errorLocation: Node, name: string, nameArg: string | Identifier): boolean { + function checkAndReportErrorForMissingPrefix(errorLocation: Node, name: __String, nameArg: __String | Identifier): boolean { if ((errorLocation.kind === SyntaxKind.Identifier && (isTypeReferenceIdentifier(errorLocation)) || isInTypeQuery(errorLocation))) { return false; } @@ -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), 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)); + error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, diagnosticName(nameArg)); return true; } } @@ -1232,11 +1236,11 @@ namespace ts { } } - function checkAndReportErrorForUsingTypeAsNamespace(errorLocation: Node, name: string, 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) { - 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, unescapeLeadingUnderscores(name)); return true; } } @@ -1244,33 +1248,33 @@ namespace ts { return false; } - function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: string, 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, 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, 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: string, 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) { - error(errorLocation, Diagnostics.Cannot_use_namespace_0_as_a_value, 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, name); + error(errorLocation, Diagnostics.Cannot_use_namespace_0_as_a_type, unescapeLeadingUnderscores(name)); return true; } } @@ -1335,10 +1339,10 @@ namespace ts { exportDefaultSymbol = moduleSymbol; } else { - const exportValue = moduleSymbol.exports.get("export="); + const exportValue = moduleSymbol.exports.get("export=" as __String); exportDefaultSymbol = exportValue - ? getPropertyOfType(getTypeOfSymbol(exportValue), "default") - : resolveSymbol(moduleSymbol.exports.get("default"), dontResolveAlias); + ? getPropertyOfType(getTypeOfSymbol(exportValue), "default" as __String) + : resolveSymbol(moduleSymbol.exports.get("default" as __String), dontResolveAlias); } if (!exportDefaultSymbol && !allowSyntheticDefaultImports) { @@ -1390,13 +1394,13 @@ namespace ts { return result; } - function getExportOfModule(symbol: Symbol, name: string, 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: string): Symbol { + function getPropertyOfVariable(symbol: Symbol, name: __String): Symbol { if (symbol.flags & SymbolFlags.Variable) { const typeAnnotation = (symbol.valueDeclaration).type; if (typeAnnotation) { @@ -1417,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=")) { + if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get("export=" as __String)) { symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name.text); } else { @@ -1655,11 +1659,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 +1669,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 +1690,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 +1719,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 +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="), 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=") !== 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: string, moduleSymbol: Symbol): Symbol | undefined { + function tryGetMemberInModuleExports(memberName: __String, moduleSymbol: Symbol): Symbol | undefined { const symbolTable = getExportsOfModule(moduleSymbol); if (symbolTable) { return symbolTable.get(memberName); @@ -1790,11 +1790,13 @@ namespace ts { exportsWithDuplicate: ExportDeclaration[]; } + type ExportCollisionTrackerTable = UnderscoreEscapedMap; + /** * 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 +1838,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(InternalSymbolName.ExportStar); 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 +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, - id + unescapeLeadingUnderscores(id) )); } }); @@ -1937,11 +1939,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: __String) { + 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 +2856,7 @@ namespace ts { parameterDeclaration.name.kind === SyntaxKind.Identifier ? setEmitFlags(getSynthesizedClone(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) : cloneBindingName(parameterDeclaration.name) : - parameterSymbol.name; + unescapeLeadingUnderscores(parameterSymbol.name); const questionToken = isOptionalParameter(parameterDeclaration) ? createToken(SyntaxKind.QuestionToken) : undefined; let parameterType = getTypeOfSymbol(parameterSymbol); @@ -2990,7 +2992,7 @@ namespace ts { return "(Anonymous function)"; } } - return symbol.name; + return unescapeLeadingUnderscores(symbol.name); } } @@ -3077,7 +3079,7 @@ namespace ts { return "(Anonymous function)"; } } - return symbol.name; + return unescapeLeadingUnderscores(symbol.name); } function getSymbolDisplayBuilder(): SymbolDisplayBuilder { @@ -3534,7 +3536,7 @@ namespace ts { continue; } if (getDeclarationModifierFlagsFromSymbol(p) & (ModifierFlags.Private | ModifierFlags.Protected)) { - writer.reportPrivateInBaseOfClassExpression(p.name); + writer.reportPrivateInBaseOfClassExpression(unescapeLeadingUnderscores(p.name)); } } const t = getTypeOfSymbol(p); @@ -4046,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: string): Type { + function getTypeOfPropertyOfType(type: Type, name: __String): Type { const prop = getPropertyOfType(type, name); return prop ? getTypeOfSymbol(prop) : undefined; } @@ -4076,8 +4078,8 @@ namespace ts { return mapType(source, t => getRestType(t, properties, symbol)); } - const members = createMap(); - const names = createMap(); + const members = createSymbolTable(); + const names = createUnderscoreEscapedMap(); for (const name of properties) { names.set(getTextOfPropertyName(name), true); } @@ -4164,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) + ? getTypeOfPropertyOfType(parentType, propName as __String) : elementType; if (!type) { if (isTupleType(parentType)) { @@ -4372,7 +4374,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 +5311,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 +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); } @@ -5631,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); @@ -5647,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); } @@ -5674,7 +5668,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 +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 = (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); @@ -5817,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: string): Symbol { + function getPropertyOfObjectType(type: Type, name: __String): Symbol { if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); const symbol = resolved.members.get(name); @@ -5829,7 +5823,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 +5853,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 +6006,7 @@ namespace ts { t; } - function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: string): Symbol { + function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: __String): Symbol { let props: Symbol[]; const types = containingType.types; const isUnion = containingType.flags & TypeFlags.Union; @@ -6083,8 +6077,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: __String): Symbol { + const properties = type.propertyCache || (type.propertyCache = createSymbolTable()); let property = properties.get(name); if (!property) { property = createUnionOrIntersectionProperty(type, name); @@ -6095,7 +6089,7 @@ namespace ts { return property; } - function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: string): 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; @@ -6109,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: string): Symbol | undefined { + function getPropertyOfType(type: Type, name: __String): Symbol | undefined { type = getApparentType(type); if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); @@ -6236,7 +6230,7 @@ namespace ts { if (isExternalModuleNameRelative(moduleName)) { return undefined; } - const symbol = getSymbol(globals, `"${moduleName}"`, 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; } @@ -6400,7 +6394,7 @@ namespace ts { let hasRestLikeParameter = hasRestParameter(declaration); if (!hasRestLikeParameter && isInJavaScriptFile(declaration) && containsArgumentsReference(declaration)) { hasRestLikeParameter = true; - const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args"); + const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args" as __String); syntheticArgsSymbol.type = anyArrayType; syntheticArgsSymbol.isRestParameter = true; parameters.push(syntheticArgsSymbol); @@ -6605,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 { @@ -6975,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, 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, 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: string, 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: string, 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: string, meaning: SymbolFlags, diagnostic: DiagnosticMessage): Symbol { + function getGlobalSymbol(name: __String, 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: __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", /*arity*/ 1, /*reportErrors*/ true)) || emptyGenericType; + return deferredGlobalTypedPropertyDescriptorType || (deferredGlobalTypedPropertyDescriptorType = getGlobalType("TypedPropertyDescriptor" as __String, /*arity*/ 1, /*reportErrors*/ true)) || emptyGenericType; } function getGlobalTemplateStringsArrayType() { - return deferredGlobalTemplateStringsArrayType || (deferredGlobalTemplateStringsArrayType = getGlobalType("TemplateStringsArray", /*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", reportErrors)); + return deferredGlobalESSymbolConstructorSymbol || (deferredGlobalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol" as __String, reportErrors)); } function getGlobalESSymbolType(reportErrors: boolean) { - return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol", /*arity*/ 0, reportErrors)) || emptyObjectType; + return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType; } function getGlobalPromiseType(reportErrors: boolean) { - return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise", /*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", reportErrors)); + return deferredGlobalPromiseConstructorSymbol || (deferredGlobalPromiseConstructorSymbol = getGlobalValueSymbol("Promise" as __String, reportErrors)); } function getGlobalPromiseConstructorLikeType(reportErrors: boolean) { - return deferredGlobalPromiseConstructorLikeType || (deferredGlobalPromiseConstructorLikeType = getGlobalType("PromiseConstructorLike", /*arity*/ 0, reportErrors)) || emptyObjectType; + return deferredGlobalPromiseConstructorLikeType || (deferredGlobalPromiseConstructorLikeType = getGlobalType("PromiseConstructorLike" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType; } function getGlobalAsyncIterableType(reportErrors: boolean) { - return deferredGlobalAsyncIterableType || (deferredGlobalAsyncIterableType = getGlobalType("AsyncIterable", /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIterableType || (deferredGlobalAsyncIterableType = getGlobalType("AsyncIterable" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalAsyncIteratorType(reportErrors: boolean) { - return deferredGlobalAsyncIteratorType || (deferredGlobalAsyncIteratorType = getGlobalType("AsyncIterator", /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIteratorType || (deferredGlobalAsyncIteratorType = getGlobalType("AsyncIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalAsyncIterableIteratorType(reportErrors: boolean) { - return deferredGlobalAsyncIterableIteratorType || (deferredGlobalAsyncIterableIteratorType = getGlobalType("AsyncIterableIterator", /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIterableIteratorType || (deferredGlobalAsyncIterableIteratorType = getGlobalType("AsyncIterableIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIterableType(reportErrors: boolean) { - return deferredGlobalIterableType || (deferredGlobalIterableType = getGlobalType("Iterable", /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalIterableType || (deferredGlobalIterableType = getGlobalType("Iterable" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIteratorType(reportErrors: boolean) { - return deferredGlobalIteratorType || (deferredGlobalIteratorType = getGlobalType("Iterator", /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalIteratorType || (deferredGlobalIteratorType = getGlobalType("Iterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIterableIteratorType(reportErrors: boolean) { - return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType("IterableIterator", /*arity*/ 1, reportErrors)) || emptyGenericType; + return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType("IterableIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } - function getGlobalTypeOrUndefined(name: string, arity = 0): ObjectType { + function getGlobalTypeOrUndefined(name: __String, arity = 0): ObjectType { const symbol = getGlobalSymbol(name, SymbolFlags.Type, /*diagnostic*/ undefined); return symbol && getTypeOfGlobalSymbol(symbol, arity); } @@ -7065,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: string, name: string): 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); @@ -7123,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); + const property = createSymbol(SymbolFlags.Property, "" + i as __String); property.type = typeParameter; properties.push(property); } @@ -7463,9 +7457,9 @@ 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)); + getLiteralType(unescapeLeadingUnderscores(prop.name)); } function getLiteralTypeFromPropertyNames(type: Type) { @@ -7502,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 ? - "" + (indexType).value : + escapeLeadingUnderscores("" + (indexType).value) : accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false) ? - getPropertyNameForKnownSymbolName(((accessExpression.argumentExpression).name).text) : + getPropertyNameForKnownSymbolName(unescapeLeadingUnderscores(((accessExpression.argumentExpression).name).text)) : undefined; if (propName !== undefined) { const prop = getPropertyOfType(objectType, propName); @@ -7692,8 +7686,8 @@ namespace ts { return emptyObjectType; } - const members = createMap(); - const skippedPrivateMembers = createMap(); + const members = createSymbolTable(); + const skippedPrivateMembers = createUnderscoreEscapedMap(); let stringIndexInfo: IndexInfo; let numberIndexInfo: IndexInfo; if (left === emptyObjectType) { @@ -8502,8 +8496,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); + unescapeLeadingUnderscores(sourceParams[i < sourceMax ? i : sourceMax].name), + unescapeLeadingUnderscores(targetParams[i < targetMax ? i : targetMax].name)); } return Ternary.False; } @@ -8652,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, 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); @@ -9904,7 +9898,7 @@ namespace ts { } function isTupleLikeType(type: Type): boolean { - return !!getPropertyOfType(type, "0"); + return !!getPropertyOfType(type, "0" as __String); } function isUnitType(type: Type): boolean { @@ -10017,7 +10011,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 +10055,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 +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, 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; } @@ -10283,7 +10277,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 +10753,7 @@ namespace ts { return undefined; } - function isDiscriminantProperty(type: Type, name: string) { + function isDiscriminantProperty(type: Type, name: __String) { if (type && type.flags & TypeFlags.Union) { const prop = getUnionOrIntersectionProperty(type, name); if (prop && getCheckFlags(prop) & CheckFlags.SyntheticProperty) { @@ -10840,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") && isTypeSubtypeOf(type, globalFunctionType)); + resolved.members.get("bind" as __String) && isTypeSubtypeOf(type, globalFunctionType)); } function getTypeFacts(type: Type): TypeFacts { @@ -10918,7 +10912,7 @@ namespace ts { } function getTypeOfDestructuredArrayElement(type: Type, index: number) { - return isTupleLikeType(type) && getTypeOfPropertyOfType(type, "" + index) || + return isTupleLikeType(type) && getTypeOfPropertyOfType(type, "" + index as __String) || checkIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || unknownType; } @@ -11751,7 +11745,7 @@ namespace ts { } let targetType: Type; - const prototypeProperty = getPropertyOfType(rightType, "prototype"); + const prototypeProperty = getPropertyOfType(rightType, "prototype" as __String); if (prototypeProperty) { // Target type is type of the prototype property const prototypePropertyType = getTypeOfSymbol(prototypeProperty); @@ -12842,7 +12836,7 @@ namespace ts { return undefined; } - function getTypeOfPropertyOfContextualType(type: Type, name: string) { + 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; @@ -12902,7 +12896,7 @@ namespace ts { const type = getApparentTypeOfContextualType(arrayLiteral); if (type) { const index = indexOf(arrayLiteral.elements, node); - return getTypeOfPropertyOfContextualType(type, "" + index) + return getTypeOfPropertyOfContextualType(type, "" + index as __String) || getIndexTypeOfContextualType(type, IndexKind.Number) || getIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false, /*checkAssignability*/ false); } @@ -13234,11 +13228,11 @@ namespace ts { return isTypeAny(type) || isTypeOfKind(type, kind); } - function isInfinityOrNaNString(name: string): boolean { + function isInfinityOrNaNString(name: string | __String): boolean { return name === "Infinity" || name === "-Infinity" || name === "NaN"; } - function isNumericLiteralName(name: string) { + 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', @@ -13297,7 +13291,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 +13380,7 @@ namespace ts { if (propertiesArray.length > 0) { spread = getSpreadType(spread, createObjectLiteralType()); propertiesArray = []; - propertiesTable = createMap(); + propertiesTable = createSymbolTable(); hasComputedStringProperty = false; hasComputedNumberProperty = false; typeFlags = 0; @@ -13504,9 +13498,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 | __String) { // - 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 +13527,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 +13561,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 +13584,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 +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, 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 @@ -13646,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: Map) { + 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; @@ -13663,7 +13657,7 @@ namespace ts { return createJsxAttributesTypeFromAttributesProperty(node.parent as JsxOpeningLikeElement, /*filter*/ undefined, checkMode); } - function getJsxType(name: string) { + function getJsxType(name: __String) { let jsxType = jsxTypes.get(name); if (jsxType === undefined) { jsxTypes.set(name, jsxType = getExportedTypeFromNamespace(JsxNames.JSX, name) || unknownType); @@ -13697,12 +13691,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, 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, JsxNames.IntrinsicElements); + error(node, Diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, unescapeLeadingUnderscores(JsxNames.IntrinsicElements)); } return links.resolvedSymbol = unknownSymbol; } @@ -13755,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: string): string { + function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: __String): __String { // JSX const jsxNamespace = getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined); // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [symbol] @@ -13767,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 ""; + 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 @@ -13776,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, nameOfAttribPropContainer); + error(jsxElementAttribPropInterfaceSym.declarations[0], Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, unescapeLeadingUnderscores(nameOfAttribPropContainer)); } } return undefined; @@ -13796,7 +13790,7 @@ namespace ts { return _jsxElementPropertiesName; } - function getJsxElementChildrenPropertyname(): string { + function getJsxElementChildrenPropertyname(): __String { if (!_hasComputedJsxElementChildrenPropertyName) { _hasComputedJsxElementChildrenPropertyName = true; _jsxElementChildrenPropertyName = getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer); @@ -13954,7 +13948,7 @@ namespace ts { // Hello World const intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements); if (intrinsicElementsType !== unknownType) { - const stringLiteralTypeName = (elementType).value; + const stringLiteralTypeName = escapeLeadingUnderscores((elementType).value); const intrinsicProp = getPropertyOfType(intrinsicElementsType, stringLiteralTypeName); if (intrinsicProp) { return getTypeOfSymbol(intrinsicProp); @@ -13963,7 +13957,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, 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; @@ -14196,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: string, isComparingJsxAttributes: boolean): boolean { + function isKnownProperty(targetType: Type, name: __String, isComparingJsxAttributes: boolean): boolean { if (targetType.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(targetType); if (resolved.stringIndexInfo || @@ -14246,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, 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 @@ -14256,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, 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; } @@ -14441,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, 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, right.text); + error(right, Diagnostics.Class_0_used_before_its_declaration, unescapeLeadingUnderscores(right.text)); } } @@ -14462,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, right.text); + error(right, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, unescapeLeadingUnderscores(right.text)); return unknownType; } } @@ -14499,12 +14493,12 @@ namespace ts { diagnostics.add(createDiagnosticForNodeFromMessageChain(propNode, errorInfo)); } - function getSuggestionForNonexistentProperty(node: Identifier, containingType: Type): string | undefined { - const suggestion = getSpellingSuggestionForName(node.text, getPropertiesOfType(containingType), SymbolFlags.Value); + 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: string, meaning: SymbolFlags): string { + 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) { @@ -14513,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(name, arrayFrom(symbols.values()), meaning); + return getSpellingSuggestionForName(unescapeLeadingUnderscores(name), arrayFrom(symbols.values()), meaning); }); if (result) { return result.name; @@ -14547,10 +14541,11 @@ namespace ts { } name = name.toLowerCase(); for (const candidate of symbols) { + let candidateName = unescapeLeadingUnderscores(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 +14603,7 @@ namespace ts { return false; } - function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean { + function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: __String): boolean { const left = node.kind === SyntaxKind.PropertyAccessExpression ? (node).expression : (node).left; @@ -14619,7 +14614,7 @@ namespace ts { function isValidPropertyAccessWithType( node: PropertyAccessExpression | QualifiedName, left: LeftHandSideExpression | QualifiedName, - propertyName: string, + propertyName: __String, type: Type): boolean { if (type !== unknownType && !isTypeAny(type)) { @@ -15361,9 +15356,10 @@ namespace ts { const element = node; switch (element.name.kind) { case SyntaxKind.Identifier: + return getLiteralType(unescapeLeadingUnderscores((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 +17068,7 @@ namespace ts { const element = elements[elementIndex]; if (element.kind !== SyntaxKind.OmittedExpression) { if (element.kind !== SyntaxKind.SpreadElement) { - const propName = "" + elementIndex; + const propName = "" + elementIndex as __String; const type = isTypeAny(sourceType) ? sourceType : isTupleLikeType(sourceType) @@ -17089,7 +17085,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 +18082,8 @@ namespace ts { Property = Getter | Setter } - const instanceNames = createMap(); - const staticNames = createMap(); + 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) { @@ -18123,7 +18119,7 @@ namespace ts { } } - function addName(names: Map, location: Node, name: string, meaning: Declaration) { + function addName(names: UnderscoreEscapedMap, location: Node, name: __String, meaning: Declaration) { const prev = names.get(name); if (prev) { if (prev & Declaration.Method) { @@ -18184,8 +18180,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 = unescapeLeadingUnderscores(member.name.text); break; default: continue; @@ -18895,7 +18893,7 @@ namespace ts { return typeAsPromise.promisedTypeOfPromise = (promise).typeArguments[0]; } - const thenFunction = getTypeOfPropertyOfType(promise, "then"); + const thenFunction = getTypeOfPropertyOfType(promise, "then" as __String); if (isTypeAny(thenFunction)) { return undefined; } @@ -19027,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"); + const thenFunction = getTypeOfPropertyOfType(type, "then" as __String); if (thenFunction && getSignaturesOfType(thenFunction, SignatureKind.Call).length > 0) { if (errorNode) { Debug.assert(!!diagnosticMessage); @@ -19136,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, - rootName.text, + unescapeLeadingUnderscores(rootName.text), entityNameToString(promiseConstructorName)); return unknownType; } @@ -19485,11 +19483,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, unescapeLeadingUnderscores(local.name)); } } else if (compilerOptions.noUnusedLocals) { - forEach(local.declarations, d => errorUnusedLocal(getNameOfDeclaration(d) || d, local.name)); + forEach(local.declarations, d => errorUnusedLocal(getNameOfDeclaration(d) || d, unescapeLeadingUnderscores(local.name))); } } }); @@ -19522,7 +19520,7 @@ namespace ts { } function isIdentifierThatStartsWithUnderScore(node: Node) { - return node.kind === SyntaxKind.Identifier && (node).text.charCodeAt(0) === CharacterCodes._; + return node.kind === SyntaxKind.Identifier && unescapeLeadingUnderscores((node).text).charCodeAt(0) === CharacterCodes._; } function checkUnusedClassMembers(node: ClassDeclaration | ClassExpression): void { @@ -19531,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, 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, parameter.symbol.name); + error(parameter.name, Diagnostics.Property_0_is_declared_but_never_used, unescapeLeadingUnderscores(parameter.symbol.name)); } } } @@ -19558,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, typeParameter.symbol.name); + error(typeParameter.name, Diagnostics._0_is_declared_but_never_used, unescapeLeadingUnderscores(typeParameter.symbol.name)); } } } @@ -19571,7 +19569,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), unescapeLeadingUnderscores(local.name)); } } } @@ -20464,7 +20462,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 __String); if (isTypeAny(nextMethod)) { return undefined; } @@ -20492,7 +20490,7 @@ namespace ts { } } - const nextValue = nextResult && getTypeOfPropertyOfType(nextResult, "value"); + const nextValue = nextResult && getTypeOfPropertyOfType(nextResult, "value" as __String); if (!nextValue) { if (errorNode) { error(errorNode, isAsyncIterator @@ -20837,7 +20835,7 @@ namespace ts { case "symbol": case "void": case "object": - error(name, message, (name).text); + error(name, message, (name).text as string); } } @@ -21172,7 +21170,8 @@ namespace ts { return true; } - const seen = createMap<{ prop: Symbol; containingType: Type }>(); + type InheritanceInfoMap = { prop: Symbol; containingType: Type }; + const seen = createUnderscoreEscapedMap(); forEach(resolveDeclaredMembers(type).declaredProperties, p => { seen.set(p.name, { prop: p, containingType: type }); }); let ok = true; @@ -21371,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; + ((expr).argumentExpression).text as __String; return evaluateEnumMember(expr, type.symbol, name); } } @@ -21380,7 +21379,7 @@ namespace ts { return undefined; } - function evaluateEnumMember(expr: Expression, enumSymbol: Symbol, name: string) { + function evaluateEnumMember(expr: Expression, enumSymbol: Symbol, name: __String) { const memberSymbol = enumSymbol.exports.get(name); if (memberSymbol) { const declaration = memberSymbol.valueDeclaration; @@ -21570,7 +21569,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(getTextOfIdentifierOrLiteral(node.name))) { error(node.name, Diagnostics.Ambient_module_declaration_cannot_specify_relative_module_name); } } @@ -21845,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, exportedName.text); + error(exportedName, Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, unescapeLeadingUnderscores(exportedName.text)); } else { markExportAsReferenced(node); @@ -21903,7 +21902,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 __String); if (exportEqualsSymbol && hasExportedMembers(moduleSymbol)) { const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration; if (!isTopLevelInExternalModuleAugmentation(declaration)) { @@ -21930,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, id)); + diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, unescapeLeadingUnderscores(id))); } } } @@ -22250,7 +22249,7 @@ namespace ts { return []; } - const symbols = createMap(); + const symbols = createSymbolTable(); let memberFlags: ModifierFlags = ModifierFlags.None; populateSymbols(); @@ -22616,7 +22615,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 __String); } break; } @@ -23209,7 +23208,7 @@ namespace ts { } function hasGlobalName(name: string): boolean { - return globals.has(name); + return globals.has(escapeLeadingUnderscores(name)); } function getReferencedValueSymbol(reference: Identifier, startInDeclarationContainer?: boolean): Symbol { @@ -23453,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", /*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", /*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 __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", /*arity*/ 1); + globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray" as __String, /*arity*/ 1); anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; - globalThisType = getGlobalTypeOrUndefined("ThisType", /*arity*/ 1); + globalThisType = getGlobalTypeOrUndefined("ThisType" as __String, /*arity*/ 1); } function checkExternalEmitHelpers(location: Node, helpers: ExternalEmitHelpers) { @@ -23482,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); } @@ -24086,7 +24085,7 @@ namespace ts { } function checkGrammarObjectLiteralExpression(node: ObjectLiteralExpression, inDestructuring: boolean) { - const seen = createMap(); + const seen = createUnderscoreEscapedMap(); const Property = 1; const GetAccessor = 2; const SetAccessor = 4; @@ -24176,7 +24175,7 @@ namespace ts { } function checkGrammarJsxElement(node: JsxOpeningLikeElement) { - const seen = createMap(); + const seen = createUnderscoreEscapedMap(); for (const attr of node.attributes.properties) { if (attr.kind === SyntaxKind.JsxSpreadAttribute) { @@ -24481,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); } } @@ -24733,7 +24732,7 @@ namespace ts { function getAmbientModules(): Symbol[] { const result: Symbol[] = []; globals.forEach((global, sym) => { - if (ambientModuleSymbolRegex.test(sym)) { + if (ambientModuleSymbolRegex.test(unescapeLeadingUnderscores(sym))) { result.push(global); } }); diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 5da7e83655fe5..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 = 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 5c7536a825ed6..1520c162a836f 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -47,6 +47,22 @@ namespace ts { return new MapCtr(); } + /** Create a new escaped identifier map. */ + export function createUnderscoreEscapedMap(): UnderscoreEscapedMap { + return new MapCtr() as UnderscoreEscapedMap; + } + + /* @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 +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: Map, callback: (value: T, key: string) => 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 & __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 & __String)); if (result) { return result; } @@ -1013,10 +1031,12 @@ namespace ts { } /** `forEachEntry` for just keys. */ - export function forEachKey(map: Map<{}>, callback: (key: string) => 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 & __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); + const result = callback(key as string & __String); if (result) { return result; } @@ -1025,9 +1045,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: UnderscoreEscapedMap, target: UnderscoreEscapedMap): 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 +1121,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 +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: string) => 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: string) { + function Symbol(this: Symbol, flags: SymbolFlags, name: __String) { this.flags = flags; this.name = name; this.declarations = undefined; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 65cbee9873a35..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); @@ -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)); } /** @@ -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(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; @@ -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); } @@ -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 ed3ed36e79a03..af009047bd4f3 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(getTextOfIdentifierOrLiteral(sourceNode)); node.textSourceNode = sourceNode; return node; } @@ -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(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(jsxFactory.right.text); + const right = createIdentifier(unescapeLeadingUnderscores(jsxFactory.right.text)); right.text = jsxFactory.right.text; return createPropertyAccess(left, right); } else { - return createReactNamespace(jsxFactory.text, parent); + return createReactNamespace(unescapeLeadingUnderscores(jsxFactory.text), parent); } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a8234b850e210..8e72a4bb08b8b 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1178,12 +1178,11 @@ namespace ts { } const result = createNode(kind, scanner.getStartPos()); - (result).text = ""; + (result).text = "" as __String; return finishNode(result); } function internIdentifier(text: string): string { - text = escapeIdentifier(text); 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 = escapeLeadingUnderscores(internIdentifier(scanner.getTokenValue())); nextToken(); return finishNode(node); } @@ -1227,7 +1226,9 @@ namespace ts { function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName { if (token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral) { - return parseLiteralNode(/*internName*/ true); + const node = parseLiteralNode(); + node.text = internIdentifier(node.text); + return node; } if (allowComputedPropertyNames && token() === SyntaxKind.OpenBracketToken) { return parseComputedPropertyName(); @@ -2049,26 +2050,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; @@ -5624,7 +5625,8 @@ namespace ts { node.flags |= NodeFlags.GlobalAugmentation; } else { - node.name = parseLiteralNode(/*internName*/ true); + node.name = parseLiteralNode(); + node.name.text = internIdentifier(node.name.text); } if (token() === SyntaxKind.OpenBraceToken) { @@ -5768,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 { @@ -6990,7 +6992,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 = escapeLeadingUnderscores(content.substring(pos, end)); finishNode(result, end); nextJSDocToken(); diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 7b62fde8570dc..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: Map; + 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 = createMap(); + classifiableNames = createUnderscoreEscapedMap<__String>(); 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..eca28ee814bbf 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -411,11 +411,11 @@ namespace ts { } else if (isStringOrNumericLiteral(propertyName)) { const argumentExpression = getSynthesizedClone(propertyName); - argumentExpression.text = unescapeIdentifier(argumentExpression.text); + argumentExpression.text = argumentExpression.text; 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 4146574fe12b3..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(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, node.label.text, labelMarker); + setLabeledJump(convertedLoopState, /*isBreak*/ true, unescapeLeadingUnderscores(node.label.text), labelMarker); } else { labelMarker = `continue-${node.label.text}`; - setLabeledJump(convertedLoopState, /*isBreak*/ false, 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(node.label.text, node.label.text); + convertedLoopState.labels.set(unescapeLeadingUnderscores(node.label.text), unescapeLeadingUnderscores(node.label.text)); } function resetLabel(node: LabeledStatement) { - convertedLoopState.labels.set(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 3565547d78aa8..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(node.name.text), + createLiteral(unescapeLeadingUnderscores(node.name.text)), node ); } diff --git a/src/compiler/transformers/es5.ts b/src/compiler/transformers/es5.ts index bcecb86e75d87..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(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 a3aa0139aa41c..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(node.name.text), + createLiteral(unescapeLeadingUnderscores(node.name.text)), node ); } diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index d0049e72f0bff..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 ? 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 && 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 ? 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 && 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(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(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(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 = (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 09f361d1b131a..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(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(name.text)) { + if (/^[A-Za-z_]\w*$/.test(unescapeLeadingUnderscores(name.text))) { return name; } else { - return createLiteral(name.text); + return createLiteral(unescapeLeadingUnderscores(name.text)); } } diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 6141f52f5f4cb..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(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 fa126d1faa79f..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((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(e.name.text), + createLiteral(unescapeLeadingUnderscores(e.name.text)), createElementAccess( parameterName, - createLiteral((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 = decl.name.text; + excludeName = unescapeLeadingUnderscores(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 = getTextOfIdentifierOrLiteral(exportName); } 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(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 acfd465ff998f..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: Map; + 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 = createMap(); + 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 a39115a788e92..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(specifier.name.text)) { + if (!uniqueExports.get(unescapeLeadingUnderscores(specifier.name.text))) { const name = specifier.propertyName || specifier.name; - exportSpecifiers.add(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(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(name.text)) { + if (!uniqueExports.get(unescapeLeadingUnderscores(name.text))) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name); - uniqueExports.set(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(name.text)) { + if (!uniqueExports.get(unescapeLeadingUnderscores(name.text))) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name); - uniqueExports.set(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(decl.name.text)) { - uniqueExports.set(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 e2e14c9fd6b3b..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: string; + 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?: Map; + /* @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(): Map; + /* @internal */ getClassifiableNames(): UnderscoreEscapedMap<__String>; /* @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: __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 @@ -3005,7 +3005,51 @@ namespace ts { isRestParameter?: boolean; } - export type SymbolTable = Map; + export const enum InternalSymbolName { + 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) + } + + /** + * 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 __String = (string & { __escapedIdentifier: void }) | (void & { __escapedIdentifier: void }) | InternalSymbolName; + + /** EscapedStringMap based on ES6 Map interface. */ + export interface UnderscoreEscapedMap { + 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: __String) => void): void; + readonly size: number; + keys(): Iterator<__String>; + values(): Iterator; + entries(): Iterator<[__String, T]>; + } + + /** SymbolTable based on ES6 Map interface. */ + export type SymbolTable = UnderscoreEscapedMap; /** Represents a "prefix*suffix" pattern. */ /* @internal */ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 3d7e8c529b894..006df07d22d13 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -351,8 +351,16 @@ 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): __String { + return (identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier) as __String; + } + + /** + * @deprecated + * @param identifier The identifier to escape + */ export function escapeIdentifier(identifier: string): string { - return identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier; + return escapeLeadingUnderscores(identifier) as string; } // Make an identifier from an external module name by extracting the string after the last "/" and replacing @@ -467,16 +475,16 @@ namespace ts { return info.declaration ? declarationNameToString(info.declaration.parameters[0].name) : undefined; } - export function getTextOfPropertyName(name: PropertyName): string { + export function getTextOfPropertyName(name: PropertyName): __String { switch (name.kind) { case SyntaxKind.Identifier: return (name).text; case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: - return (name).text; + return escapeLeadingUnderscores((name).text); case SyntaxKind.ComputedPropertyName: if (isStringOrNumericLiteral((name).expression)) { - return ((name).expression).text; + return escapeLeadingUnderscores(((name).expression).text); } } @@ -486,11 +494,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 ? unescapeLeadingUnderscores(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 +1967,59 @@ 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): __String { + if (name.kind === SyntaxKind.Identifier) { + return name.text; + } + if (name.kind === SyntaxKind.StringLiteral || name.kind === SyntaxKind.NumericLiteral) { + return escapeLeadingUnderscores(name.text); } 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(unescapeLeadingUnderscores(rightHandSideName)); } else if (nameExpression.kind === SyntaxKind.StringLiteral || nameExpression.kind === SyntaxKind.NumericLiteral) { - return (nameExpression).text; + return escapeLeadingUnderscores((nameExpression).text); + } + } + + return undefined; + } + + export function getTextOfIdentifierOrLiteral(node: Identifier | LiteralLikeNode) { + if (node) { + if (node.kind === SyntaxKind.Identifier) { + return unescapeLeadingUnderscores((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 escapeLeadingUnderscores((node as LiteralLikeNode).text); } } return undefined; } - export function getPropertyNameForKnownSymbolName(symbolName: string): string { - return "__@" + symbolName; + export function getPropertyNameForKnownSymbolName(symbolName: string): __String { + return "__@" + symbolName as __String; } /** @@ -2344,8 +2385,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: __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); return ch.toLowerCase() === ch; } @@ -3974,8 +4017,19 @@ 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 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; + } + + /** + * 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 __String); } export function getNameOfDeclaration(declaration: Declaration): DeclarationName | undefined { diff --git a/src/services/classifier.ts b/src/services/classifier.ts index ff33059630d82..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: Map, 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: Map, 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/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 81aae4c0e5e3a..b45d2448a0a7c 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) { @@ -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 c2d26da4392d1..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.name; + 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 410ba636d7b77..53142b7b2da0c 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -88,10 +88,11 @@ namespace ts.Completions { if (pos === position) { return; } + const realName = unescapeLeadingUnderscores(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.getUnescapedName()); 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.getUnescapedName())) { 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 = createUnderscoreEscapedMap(); 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 = createUnderscoreEscapedMap(); 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: __String; if (m.kind === SyntaxKind.BindingElement && (m).propertyName) { // include only identifiers in completion list @@ -1502,10 +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. - existingName = (getNameOfDeclaration(m) as Identifier).text; + const name = getNameOfDeclaration(m); + existingName = getEscapedTextOfIdentifierOrLiteral(name as (Identifier | LiteralExpression)); } 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 = createUnderscoreEscapedMap(); 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 = 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 fc84b60cc1f6e..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, 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 192895cde591c..8c6cfc3185a29 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: 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), (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: string; + 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; @@ -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, (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 = 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").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; } @@ -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.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*/ createMap(), 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*/ createMap(), state.checker); + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getUnescapedName(), result, /*previousIterationSymbolsCache*/ createSymbolTable(), state.checker); return find(result, search.includes); } @@ -1568,7 +1568,7 @@ namespace ts.FindAllReferences.Core { } return undefined; } - return (node.name).text; + return getTextOfIdentifierOrLiteral(node.name); } /** 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..36a8a4dd613dc 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 = 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 5e8e7b8b3a7f4..ecd52baa7ddb6 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -595,9 +595,9 @@ namespace ts.FindAllReferences { return isExternalModuleSymbol(exportingModuleSymbol) ? { exportingModuleSymbol, exportKind } : undefined; } - function symbolName(symbol: Symbol): string | undefined { + function symbolName(symbol: Symbol): __String | undefined { if (symbol.name !== "default") { - return symbol.name; + return symbol.getName(); } return forEach(symbol.declarations, decl => { diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index 5d03ad03b0c8f..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: 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 = 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 = 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 304f64f3cdbbb..f8a0d96806e77 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -83,24 +83,11 @@ namespace ts.NavigateTo { return true; } - function getTextOfIdentifierOrLiteral(node: Node) { - if (node) { - if (node.kind === SyntaxKind.Identifier || - 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); } @@ -121,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); @@ -132,7 +119,7 @@ namespace ts.NavigateTo { if (expression.kind === SyntaxKind.PropertyAccessExpression) { const propertyAccess = expression; if (includeLastPortion) { - containers.unshift(propertyAccess.name.text); + containers.unshift(unescapeLeadingUnderscores(propertyAccess.name.text)); } return tryAddComputedPropertyName(propertyAccess.expression, containers, /*includeLastPortion*/ true); @@ -204,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 ? (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 819202ff6f4ec..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 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 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 (nameIdentifier).text; + return unescapeLeadingUnderscores((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(getTextOfIdentifierOrLiteral(moduleDeclaration.name)); while (moduleDeclaration.body && moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) { moduleDeclaration = moduleDeclaration.body; - result.push(moduleDeclaration.name.text); + result.push(getTextOfIdentifierOrLiteral(moduleDeclaration.name)); } return result.join("."); diff --git a/src/services/pathCompletions.ts b/src/services/pathCompletions.ts index 3ded126ab6552..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(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/refactors/convertFunctionToEs6Class.ts b/src/services/refactors/convertFunctionToEs6Class.ts index 745ba6d15bfd7..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.name, /*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 402baf12eecec..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: string; + 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: string) { + constructor(flags: SymbolFlags, name: __String) { this.flags = flags; this.name = name; } @@ -324,10 +324,14 @@ namespace ts { return this.flags; } - getName(): string { + getName(): __String { return this.name; } + getUnescapedName(): string { + return unescapeLeadingUnderscores(this.name); + } + getDeclarations(): Declaration[] | undefined { return this.declarations; } @@ -360,7 +364,7 @@ namespace ts { class IdentifierObject extends TokenOrIdentifierObject implements Identifier { public kind: SyntaxKind.Identifier; - public text: string; + public text: __String; _primaryExpressionBrand: any; _memberExpressionBrand: any; _leftHandSideExpressionBrand: any; @@ -509,7 +513,7 @@ namespace ts { public languageVersion: ScriptTarget; public languageVariant: LanguageVariant; public identifiers: Map; - public nameTable: Map; + public nameTable: UnderscoreEscapedMap; public resolvedModules: Map; public resolvedTypeReferenceDirectiveNames: Map; public imports: StringLiteral[]; @@ -589,7 +593,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; } @@ -597,23 +601,10 @@ namespace ts { if (name.kind === SyntaxKind.ComputedPropertyName) { const expr = (name).expression; if (expr.kind === SyntaxKind.PropertyAccessExpression) { - return (expr).name.text; + return unescapeLeadingUnderscores((expr).name.text); } - return getTextOfIdentifierOrLiteral(expr); - } - } - - return undefined; - } - - function getTextOfIdentifierOrLiteral(node: Node) { - if (node) { - if (node.kind === SyntaxKind.Identifier || - node.kind === SyntaxKind.StringLiteral || - node.kind === SyntaxKind.NumericLiteral) { - - return (node).text; + return getTextOfIdentifierOrLiteral(expr as (Identifier | LiteralExpression)); } } @@ -2082,7 +2073,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): UnderscoreEscapedMap { if (!sourceFile.nameTable) { initializeNameTable(sourceFile); } @@ -2091,7 +2082,7 @@ namespace ts { } function initializeNameTable(sourceFile: SourceFile): void { - const nameTable = createMap(); + const nameTable = createUnderscoreEscapedMap(); walk(sourceFile); sourceFile.nameTable = nameTable; @@ -2111,7 +2102,7 @@ namespace ts { node.parent.kind === SyntaxKind.ExternalModuleReference || isArgumentOfElementAccessExpression(node) || isLiteralComputedPropertyDeclarationName(node)) { - setNameTable((node).text, node); + setNameTable(getEscapedTextOfIdentifierOrLiteral((node)), node); } break; default: @@ -2124,7 +2115,7 @@ namespace ts { } } - function setNameTable(text: string, node: ts.Node): void { + function setNameTable(text: __String, node: ts.Node): void { nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1); } } @@ -2167,7 +2158,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 = 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 785c5b0ab747a..00ab016580550 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(unescapeLeadingUnderscores(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.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.name, + name: typeParameter.symbol.getUnescapedName(), documentation: emptyArray, displayParts, isOptional: false diff --git a/src/services/types.ts b/src/services/types.ts index 447029a2f668f..d440ecab28ece 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(): __String; + getUnescapedName(): string; getDeclarations(): Declaration[] | undefined; getDocumentationComment(): SymbolDisplayPart[]; getJsDocTags(): JSDocTagInfo[]; @@ -56,7 +57,7 @@ namespace ts { export interface SourceFile { /* @internal */ version: string; /* @internal */ scriptSnapshot: IScriptSnapshot; - /* @internal */ nameTable: Map; + /* @internal */ nameTable: UnderscoreEscapedMap; /* @internal */ getNamedDeclarations(): Map; diff --git a/src/services/utilities.ts b/src/services/utilities.ts index a3e44f00d1afa..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.name.charCodeAt(0) === CharacterCodes.doubleQuote; + return moduleSymbol.getUnescapedName().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 getTextOfIdentifierOrLiteral(location); } // Try to get the local symbol if we're dealing with an 'export default' 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/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/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/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/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/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: "" +}; 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/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();