Created a branded type for identifier-escaped strings (#16915)

* Created a branded type for escaped strings

Then flowed it throughout the compiler, finding and fixing a handful of
bugs relating to underscore-prefixed identifiers in the process.
Includes a test for two cases noticed - diagnostics from conflicting
symbols from export *'s, and enum with underscore prefixed member emit.

* Correctly double underscores WRT mapped types

* Add fourslash tests for other fixed issues

* use function call over cast

* Update forEachEntry type accuracy

* Just use escaped names for ActiveLabel

* Remove casts from getPropertyNameForPropertyNameNode

* This pattern has occurred a few times, could use a helper function.

* Remove duplicated helper

* Remove unneeded check, use helper

* Identifiers list is no longer escaped strings

* Extract repeated string-getting code into helper

* Rename type and associated functions

* Make getName() return UnderscoreEscapedString, add getUnescapedName()

* Add list of internal symbol names to escaped string type to cut back on casting

* Remove outdated comments

* Reassign interned values to nodes, just in case

* Swap to string enum

* Add deprecated aliases to escapeIdentifier and unescapeIdentifier

* Add temp var

* Remove unsafe casts

* Rename escaped string type as per @sandersn's suggestion, fix string enum usages

* Reorganize double underscore tests

* Remove jfreeman from TODO

* Remove unneeded parenthesis
This commit is contained in:
Wesley Wigham
2017-07-06 14:45:50 -07:00
committed by GitHub
parent ad291d924d
commit 4e6b2f3c93
63 changed files with 1206 additions and 514 deletions
+54 -53
View File
@@ -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<string>;
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<string>();
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>();
symbol.exports = createSymbolTable();
}
if (symbolFlags & SymbolFlags.HasMembers && !symbol.members) {
symbol.members = createMap<Symbol>();
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(<ModuleDeclaration>node) ? "__global" : `"${(<LiteralExpression>name).text}"`;
const moduleName = getTextOfIdentifierOrLiteral(<Identifier | LiteralExpression>name);
return (isGlobalScopeAugmentation(<ModuleDeclaration>node) ? "__global" : `"${moduleName}"`) as __String;
}
if (name.kind === SyntaxKind.ComputedPropertyName) {
const nameExpression = (<ComputedPropertyName>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((<PropertyAccessExpression>nameExpression).name.text);
return getPropertyNameForKnownSymbolName(unescapeLeadingUnderscores((<PropertyAccessExpression>nameExpression).name.text));
}
return (<Identifier | LiteralExpression>name).text;
return getEscapedTextOfIdentifierOrLiteral(<Identifier | LiteralExpression>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 (<ExportAssignment>node).isExportEquals ? "export=" : "default";
return (<ExportAssignment>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 = <JSDocFunctionType>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 ((<VariableStatement>parentNode).declarationList.declarations.length > 0) {
const nameIdentifier = (<VariableStatement>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<Symbol>();
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<Symbol>();
typeLiteralSymbol.members = createSymbolTable();
typeLiteralSymbol.members.set(symbol.name, symbol);
}
@@ -1658,14 +1659,14 @@ namespace ts {
}
if (inStrictMode) {
const seen = createMap<ElementKind>();
const seen = createUnderscoreEscapedMap<ElementKind>();
for (const prop of node.properties) {
if (prop.kind === SyntaxKind.SpreadAssignment || prop.name.kind !== SyntaxKind.Identifier) {
continue;
}
const identifier = <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<Symbol>();
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((<SignatureDeclaration>node.parent).parameters, node);
function getDestructuringParameterName(node: Declaration): __String {
return "__" + indexOf((<SignatureDeclaration>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(<Declaration>node, SymbolFlags.TypeLiteral, "__type");
return bindAnonymousDeclaration(<Declaration>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<Symbol>();
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<Symbol>();
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<Symbol>())) :
(targetSymbol.exports || (targetSymbol.exports = createMap<Symbol>()));
(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);
}
+250 -251
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -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));
+35 -11
View File
@@ -47,6 +47,22 @@ namespace ts {
return new MapCtr<T>();
}
/** Create a new escaped identifier map. */
export function createUnderscoreEscapedMap<T>(): UnderscoreEscapedMap<T> {
return new MapCtr<T>() as UnderscoreEscapedMap<T>;
}
/* @internal */
export function createSymbolTable(symbols?: Symbol[]): SymbolTable {
const result = createMap<Symbol>() as SymbolTable;
if (symbols) {
for (const symbol of symbols) {
result.set(symbol.name, symbol);
}
}
return result;
}
export function createMapFromTemplate<T>(template?: MapLike<T>): Map<T> {
const map: Map<T> = new MapCtr<T>();
@@ -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<T, U>(map: Map<T>, callback: (value: T, key: string) => U | undefined): U | undefined {
export function forEachEntry<T, U>(map: UnderscoreEscapedMap<T>, callback: (value: T, key: __String) => U | undefined): U | undefined;
export function forEachEntry<T, U>(map: Map<T>, callback: (value: T, key: string) => U | undefined): U | undefined;
export function forEachEntry<T, U>(map: UnderscoreEscapedMap<T> | Map<T>, 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<T>(map: Map<{}>, callback: (key: string) => T | undefined): T | undefined {
export function forEachKey<T>(map: UnderscoreEscapedMap<{}>, callback: (key: __String) => T | undefined): T | undefined;
export function forEachKey<T>(map: Map<{}>, callback: (key: string) => T | undefined): T | undefined;
export function forEachKey<T>(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<T>(source: Map<T>, target: Map<T>): void {
source.forEach((value, key) => {
target.set(key, value);
export function copyEntries<T>(source: UnderscoreEscapedMap<T>, target: UnderscoreEscapedMap<T>): void;
export function copyEntries<T>(source: Map<T>, target: Map<T>): void;
export function copyEntries<T, U extends UnderscoreEscapedMap<T> | Map<T>>(source: U, target: U): void {
(source as Map<T>).forEach((value, key) => {
(target as Map<T>).set(key, value);
});
}
@@ -1099,9 +1121,11 @@ namespace ts {
return arrayToMap<T, true>(array, makeKey, () => true);
}
export function cloneMap<T>(map: Map<T>) {
export function cloneMap(map: SymbolTable): SymbolTable;
export function cloneMap<T>(map: Map<T>): Map<T>;
export function cloneMap<T>(map: Map<T> | SymbolTable): Map<T> | SymbolTable {
const clone = createMap<T>();
copyEntries(map, clone);
copyEntries(map as Map<T>, clone);
return clone;
}
@@ -2272,13 +2296,13 @@ namespace ts {
getTokenConstructor(): new <TKind extends SyntaxKind>(kind: TKind, pos?: number, end?: number) => Token<TKind>;
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;
+6 -6
View File
@@ -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 && (<StringLiteral>node).textSourceNode) {
return getTextOfNode((<StringLiteral>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((<LiteralExpression>expr).text)) : "module";
makeIdentifierFromModuleName((<LiteralExpression>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.");
+5 -5
View File
@@ -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 = <Identifier>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<TypeNode> | undefined): Identifier {
return node.typeArguments !== typeArguments
? updateNode(createIdentifier(node.text, typeArguments), node)
? updateNode(createIdentifier(unescapeLeadingUnderscores(node.text), typeArguments), node)
: node;
}
@@ -2645,12 +2645,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);
}
}
+15 -13
View File
@@ -1178,12 +1178,11 @@ namespace ts {
}
const result = createNode(kind, scanner.getStartPos());
(<Identifier>result).text = "";
(<Identifier>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 <StringLiteral | NumericLiteral>parseLiteralNode(/*internName*/ true);
const node = <StringLiteral | NumericLiteral>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 <LiteralExpression>parseLiteralLikeNode(token(), internName);
function parseLiteralNode(): LiteralExpression {
return <LiteralExpression>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 <TemplateHead>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 <TemplateMiddle | TemplateTail>fragment;
}
function parseLiteralLikeNode(kind: SyntaxKind, internName: boolean): LiteralLikeNode {
function parseLiteralLikeNode(kind: SyntaxKind): LiteralLikeNode {
const node = <LiteralExpression>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 = <StringLiteral>parseLiteralNode(/*internName*/ true);
node.name = <StringLiteral>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((<LiteralExpression>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 = <Identifier>createNode(SyntaxKind.Identifier, pos);
result.text = content.substring(pos, end);
result.text = escapeLeadingUnderscores(content.substring(pos, end));
finishNode(result, end);
nextJSDocToken();
+2 -2
View File
@@ -405,7 +405,7 @@ namespace ts {
let commonSourceDirectory: string;
let diagnosticsProducingTypeChecker: TypeChecker;
let noDiagnosticsTypeChecker: TypeChecker;
let classifiableNames: Map<string>;
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<string>();
classifiableNames = createUnderscoreEscapedMap<__String>();
for (const sourceFile of files) {
copyEntries(sourceFile.classifiableNames, classifiableNames);
+2 -2
View File
@@ -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);
}
}
+6 -6
View File
@@ -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<Statement> {
@@ -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 });
}
}
+1 -1
View File
@@ -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
);
}
+1 -1
View File
@@ -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);
}
+1 -1
View File
@@ -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
);
}
+8 -8
View File
@@ -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 = (<Identifier>variable.name).text;
const text = unescapeLeadingUnderscores((<Identifier>variable.name).text);
name = declareLocal(text);
if (!renamedCatchVariables) {
renamedCatchVariables = createMap<boolean>();
+3 -3
View File
@@ -253,7 +253,7 @@ namespace ts {
else {
const name = (<JsxOpeningLikeElement>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));
}
}
+1 -1
View File
@@ -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);
+6 -6
View File
@@ -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 (<ExportDeclaration>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) {
+4 -4
View File
@@ -65,7 +65,7 @@ namespace ts {
let currentNamespace: ModuleDeclaration;
let currentNamespaceContainerName: Identifier;
let currentScope: SourceFile | Block | ModuleBlock | CaseBlock;
let currentScopeFirstDeclarationsOfName: Map<Node>;
let currentScopeFirstDeclarationsOfName: UnderscoreEscapedMap<Node>;
/**
* Keeps track of whether expression substitution has been enabled for specific edge cases.
@@ -2007,7 +2007,7 @@ namespace ts {
: (<ComputedPropertyName>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<Node>();
currentScopeFirstDeclarationsOfName = createUnderscoreEscapedMap<Node>();
}
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;
+9 -9
View File
@@ -58,9 +58,9 @@ namespace ts {
else {
// export { x, y }
for (const specifier of (<ExportDeclaration>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 = (<FunctionDeclaration>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 = (<ClassDeclaration>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);
}
}
+49 -5
View File
@@ -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<string>;
/* @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<string>;
/* @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<Symbol>;
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<T> {
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<T>;
entries(): Iterator<[__String, T]>;
}
/** SymbolTable based on ES6 Map interface. */
export type SymbolTable = UnderscoreEscapedMap<Symbol>;
/** Represents a "prefix*suffix" pattern. */
/* @internal */
+73 -19
View File
@@ -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 (<Identifier>name).text;
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
return (<LiteralExpression>name).text;
return escapeLeadingUnderscores((<LiteralExpression>name).text);
case SyntaxKind.ComputedPropertyName:
if (isStringOrNumericLiteral((<ComputedPropertyName>name).expression)) {
return (<LiteralExpression>(<ComputedPropertyName>name).expression).text;
return escapeLeadingUnderscores((<LiteralExpression>(<ComputedPropertyName>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((<Identifier>name).text) : getTextOfNode(name);
return getFullWidth(name) === 0 ? unescapeLeadingUnderscores(name.text) : getTextOfNode(name);
case SyntaxKind.QualifiedName:
return entityNameToString((<QualifiedName>name).left) + "." + entityNameToString((<QualifiedName>name).right);
return entityNameToString(name.left) + "." + entityNameToString(name.right);
case SyntaxKind.PropertyAccessExpression:
return entityNameToString((<PropertyAccessEntityNameExpression>name).expression) + "." + entityNameToString((<PropertyAccessEntityNameExpression>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 (<Identifier | LiteralExpression>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 = (<ComputedPropertyName>name).expression;
const nameExpression = name.expression;
if (isWellKnownSymbolSyntactically(nameExpression)) {
const rightHandSideName = (<PropertyAccessExpression>nameExpression).name.text;
return getPropertyNameForKnownSymbolName(rightHandSideName);
return getPropertyNameForKnownSymbolName(unescapeLeadingUnderscores(rightHandSideName));
}
else if (nameExpression.kind === SyntaxKind.StringLiteral || nameExpression.kind === SyntaxKind.NumericLiteral) {
return (<LiteralExpression>nameExpression).text;
return escapeLeadingUnderscores((<LiteralExpression>nameExpression).text);
}
}
return undefined;
}
export function getPropertyNameForKnownSymbolName(symbolName: string): string {
return "__@" + symbolName;
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 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 {
+2 -2
View File
@@ -462,7 +462,7 @@ namespace ts {
}
/* @internal */
export function getSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: Map<string>, 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<string>, span: TextSpan): Classifications {
export function getEncodedSemanticClassifications(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFile: SourceFile, classifiableNames: UnderscoreEscapedMap<__String>, span: TextSpan): Classifications {
const result: number[] = [];
processNode(sourceFile);
+2 -2
View File
@@ -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);
+1 -1
View File
@@ -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");
+15 -13
View File
@@ -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(<PropertyAccessExpression>(node.parent), symbol.name);
const isValidValueAccess = (symbol: Symbol) => typeChecker.isValidPropertyAccess(<PropertyAccessExpression>(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(<PropertyAccessExpression>(node.parent), symbol.name)) {
if (typeChecker.isValidPropertyAccess(<PropertyAccessExpression>(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<boolean>();
const existingImportsOrExports = createUnderscoreEscapedMap<boolean>();
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<boolean>();
const existingMemberNames = createUnderscoreEscapedMap<boolean>();
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 && (<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<boolean>();
const existingMemberNames = createUnderscoreEscapedMap<boolean>();
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<JsxAttribute | JsxSpreadAttribute>): Symbol[] {
const seenNames = createMap<boolean>();
const seenNames = createUnderscoreEscapedMap<boolean>();
for (const attr of attributes) {
// If this is the current item we are editing right now, do not filter it out
if (isCurrentlyEditingNode(attr)) {
+1 -1
View File
@@ -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;
+13 -13
View File
@@ -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((<BreakOrContinueStatement>node.parent), (<Identifier>node).text);
const labelDefinition = getTargetLabel((<BreakOrContinueStatement>node.parent), unescapeLeadingUnderscores((<Identifier>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<BindingElement>(symbol, SyntaxKind.BindingElement);
const typeOfPattern = checker.getTypeAtLocation(bindingElement.parent);
return typeOfPattern && checker.getPropertyOfType(typeOfPattern, (<Identifier>bindingElement.name).text);
return typeOfPattern && checker.getPropertyOfType(typeOfPattern, unescapeLeadingUnderscores((<Identifier>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(<ParameterDeclaration>symbol.valueDeclaration)) {
addRange(result, checker.getSymbolsOfParameterPropertyDeclaration(<ParameterDeclaration>symbol.valueDeclaration, symbol.name));
addRange(result, checker.getSymbolsOfParameterPropertyDeclaration(<ParameterDeclaration>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<Symbol>(), 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<Symbol>(), 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 (<Identifier | LiteralExpression>node.name).text;
return getTextOfIdentifierOrLiteral(node.name);
}
/** Gets all symbols for one property. Does not get symbols for every property. */
+2 -2
View File
@@ -26,8 +26,8 @@ namespace ts.GoToDefinition {
// Labels
if (isJumpStatementTarget(node)) {
const labelName = (<Identifier>node).text;
const label = getTargetLabel((<BreakOrContinueStatement>node.parent), (<Identifier>node).text);
const labelName = unescapeLeadingUnderscores((<Identifier>node).text);
const label = getTargetLabel((<BreakOrContinueStatement>node.parent), labelName);
return label ? [createDefinitionInfoFromName(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined;
}
+2 -2
View File
@@ -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 => {
+3 -3
View File
@@ -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;
+4 -17
View File
@@ -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 (<Identifier | LiteralExpression>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 = <PropertyAccessExpression>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 ? (<Identifier>containerName).text : "",
containerName: containerName ? unescapeLeadingUnderscores((<Identifier>containerName).text) : "",
containerKind: containerName ? getNodeKind(container) : ScriptElementKind.unknown
};
}
+5 -5
View File
@@ -380,7 +380,7 @@ namespace ts.NavigationBar {
const declName = getNameOfDeclaration(<Declaration>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 ((<VariableStatement>parentNode).declarationList.declarations.length > 0) {
const nameIdentifier = (<VariableStatement>parentNode).declarationList.declarations[0].name;
if (nameIdentifier.kind === SyntaxKind.Identifier) {
return (<Identifier>nameIdentifier).text;
return unescapeLeadingUnderscores((<Identifier>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>moduleDeclaration.body;
result.push(moduleDeclaration.name.text);
result.push(getTextOfIdentifierOrLiteral(moduleDeclaration.name));
}
return result.join(".");
+1 -1
View File
@@ -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
@@ -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);
}
+17 -26
View File
@@ -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<string>;
public nameTable: Map<number>;
public nameTable: UnderscoreEscapedMap<number>;
public resolvedModules: Map<ResolvedModuleFull>;
public resolvedTypeReferenceDirectiveNames: Map<ResolvedTypeReferenceDirective>;
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 = (<ComputedPropertyName>name).expression;
if (expr.kind === SyntaxKind.PropertyAccessExpression) {
return (<PropertyAccessExpression>expr).name.text;
return unescapeLeadingUnderscores((<PropertyAccessExpression>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 (<Identifier | LiteralExpression>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<number> {
export function getNameTable(sourceFile: SourceFile): UnderscoreEscapedMap<number> {
if (!sourceFile.nameTable) {
initializeNameTable(sourceFile);
}
@@ -2091,7 +2082,7 @@ namespace ts {
}
function initializeNameTable(sourceFile: SourceFile): void {
const nameTable = createMap<number>();
const nameTable = createUnderscoreEscapedMap<number>();
walk(sourceFile);
sourceFile.nameTable = nameTable;
@@ -2111,7 +2102,7 @@ namespace ts {
node.parent.kind === SyntaxKind.ExternalModuleReference ||
isArgumentOfElementAccessExpression(node) ||
isLiteralComputedPropertyDeclarationName(node)) {
setNameTable((<LiteralExpression>node).text, node);
setNameTable(getEscapedTextOfIdentifierOrLiteral((<LiteralExpression>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 = <ObjectLiteralExpression | JsxAttributes>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);
+3 -3
View File
@@ -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(<ParameterDeclaration>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
+3 -2
View File
@@ -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<number>;
/* @internal */ nameTable: UnderscoreEscapedMap<number>;
/* @internal */ getNamedDeclarations(): Map<Declaration[]>;
+2 -2
View File
@@ -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'
@@ -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 = {}));
@@ -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;
}
}
@@ -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
}
}
@@ -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 {}
@@ -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"));
@@ -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();
@@ -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))
@@ -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
@@ -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<Properties> = {
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: ""
};
@@ -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<Properties> = {
>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))
};
@@ -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<Properties> = {
>partial : Partial<Properties>
>Partial : Partial<T>
>Properties : Properties
>{ property1: "", __property2: ""} : { property1: string; __property2: string; }
property1: "",
>property1 : string
>"" : ""
__property2: ""
>__property2 : string
>"" : ""
};
@@ -0,0 +1,19 @@
//// [index.tsx]
declare global {
namespace JSX {
interface IntrinsicElements {
__foot: any;
}
}
function __make (params: object): any;
}
const thing = <__foot></__foot>;
export {}
//// [index.js]
"use strict";
exports.__esModule = true;
var thing = __make("__foot", null);
@@ -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></__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 {}
@@ -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></__foot>;
>thing : any
><__foot></__foot> : any
>__foot : any
>__foot : any
export {}
@@ -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;
@@ -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;
@@ -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 = {
@@ -7,7 +7,7 @@ class X {
>this['__proto__'] = null : null
>this['__proto__'] : any
>this : this
>'__proto__' : "___proto__"
>'__proto__' : "__proto__"
>null : null
}
}
@@ -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;
}
}
@@ -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 {}
@@ -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();
@@ -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<Properties> = {
property1: "",
__property2: ""
};
@@ -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></__foot>;
export {}
@@ -0,0 +1,12 @@
/// <reference path='fourslash.ts'/>
// @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");
@@ -0,0 +1,12 @@
/// <reference path='fourslash.ts'/>
// @Filename: fileA.ts
//// export function [|__foo|]() {
//// }
////
// @Filename: fileB.ts
//// import { [|__foo|] as bar } from "./fileA";
////
//// bar();
verify.rangesAreRenameLocations();