From 8b7caedbec33bc442b98764ba981903a8da97993 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 2 Jun 2015 10:45:50 -0700 Subject: [PATCH 1/6] Remove EmitResolver.getExpressionNameSubstitution Add EmitResolver.getReferencedExportContainer Add EmitResolver.getReferencedImportDeclaration Clean up getGeneratedNameForNode in emitter.ts Switch isNotExpressionIdentifier to isExpressionIdentifier in emitter.ts Revise emitExpressionIdentifier in emitter.ts --- src/compiler/checker.ts | 110 ++++++++------------ src/compiler/emitter.ts | 216 +++++++++++++++++++++------------------- src/compiler/types.ts | 3 +- 3 files changed, 155 insertions(+), 174 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 759b235ad0..6257031afb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11784,76 +11784,39 @@ module ts { // Emitter support - function isExternalModuleSymbol(symbol: Symbol): boolean { - return symbol.flags & SymbolFlags.ValueModule && symbol.declarations.length === 1 && symbol.declarations[0].kind === SyntaxKind.SourceFile; - } - - function getAliasNameSubstitution(symbol: Symbol, getGeneratedNameForNode: (node: Node) => string): string { - // If this is es6 or higher, just use the name of the export - // no need to qualify it. - if (languageVersion >= ScriptTarget.ES6) { - return undefined; - } - - let node = getDeclarationOfAliasSymbol(symbol); - if (node) { - if (node.kind === SyntaxKind.ImportClause) { - let defaultKeyword: string; - - if (languageVersion === ScriptTarget.ES3) { - defaultKeyword = "[\"default\"]"; - } else { - defaultKeyword = ".default"; - } - return getGeneratedNameForNode(node.parent) + defaultKeyword; - } - if (node.kind === SyntaxKind.ImportSpecifier) { - let moduleName = getGeneratedNameForNode(node.parent.parent.parent); - let propertyName = (node).propertyName || (node).name; - return moduleName + "." + unescapeIdentifier(propertyName.text); - } - } - } - - function getExportNameSubstitution(symbol: Symbol, location: Node, getGeneratedNameForNode: (Node: Node) => string): string { - if (isExternalModuleSymbol(symbol.parent)) { - // 1. If this is es6 or higher, just use the name of the export - // no need to qualify it. - // 2. export mechanism for System modules is different from CJS\AMD - // and it does not need qualifications for exports - if (languageVersion >= ScriptTarget.ES6 || compilerOptions.module === ModuleKind.System) { - return undefined; - } - return "exports." + unescapeIdentifier(symbol.name); - } - let node = location; - let containerSymbol = getParentOfSymbol(symbol); - while (node) { - if ((node.kind === SyntaxKind.ModuleDeclaration || node.kind === SyntaxKind.EnumDeclaration) && getSymbolOfNode(node) === containerSymbol) { - return getGeneratedNameForNode(node) + "." + unescapeIdentifier(symbol.name); - } - node = node.parent; - } - } - - function getExpressionNameSubstitution(node: Identifier, getGeneratedNameForNode: (Node: Node) => string): string { - let symbol = getNodeLinks(node).resolvedSymbol || (isDeclarationName(node) ? getSymbolOfNode(node.parent) : undefined); + // When resolved as an expression identifier, if the given node references an exported entity, return the declaration + // node of the exported entity's container. Otherwise, return undefined. + function getReferencedExportContainer(node: Identifier): SourceFile | ModuleDeclaration | EnumDeclaration { + let symbol = getReferencedValueSymbol(node); if (symbol) { - // Whan an identifier resolves to a parented symbol, it references an exported entity from - // another declaration of the same internal module. - if (symbol.parent) { - return getExportNameSubstitution(symbol, node.parent, getGeneratedNameForNode); + if (symbol.flags & SymbolFlags.ExportValue) { + let exportSymbol = getMergedSymbol(symbol.exportSymbol); + if (!(exportSymbol.flags & SymbolFlags.ExportHasLocal)) { + symbol = exportSymbol; + } } - // If we reference an exported entity within the same module declaration, then whether - // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the - // kinds that we do NOT prefix. - let exportSymbol = getExportSymbolOfValueSymbolIfExported(symbol); - if (symbol !== exportSymbol && !(exportSymbol.flags & SymbolFlags.ExportHasLocal)) { - return getExportNameSubstitution(exportSymbol, node.parent, getGeneratedNameForNode); + let parentSymbol = getParentOfSymbol(symbol); + if (parentSymbol) { + if (parentSymbol.flags & SymbolFlags.ValueModule && parentSymbol.valueDeclaration.kind === SyntaxKind.SourceFile) { + return parentSymbol.valueDeclaration; + } + for (let n = node.parent; n; n = n.parent) { + if ((n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.EnumDeclaration) && getSymbolOfNode(n) === parentSymbol) { + return n; + } + } } - // Named imports from ES6 import declarations are rewritten - if (symbol.flags & SymbolFlags.Alias) { - return getAliasNameSubstitution(symbol, getGeneratedNameForNode); + } + } + + // When resolved as an expression identifier, if the given node references a default import or a named import, return + // the declaration node of that import. Otherwise, return undefined. + function getReferencedImportDeclaration(node: Identifier): ImportClause | ImportSpecifier { + let symbol = getReferencedValueSymbol(node); + if (symbol && symbol.flags & SymbolFlags.Alias) { + let declaration = getDeclarationOfAliasSymbol(symbol); + if (declaration.kind === SyntaxKind.ImportClause || declaration.kind === SyntaxKind.ImportSpecifier) { + return declaration; } } } @@ -12182,12 +12145,15 @@ module ts { return !!resolveName(location, name, SymbolFlags.Value, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined); } + function getReferencedValueSymbol(reference: Identifier): Symbol { + return getNodeLinks(reference).resolvedSymbol || + resolveName(reference, reference.text, SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias, + /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined); + } + function getReferencedValueDeclaration(reference: Identifier): Declaration { Debug.assert(!nodeIsSynthesized(reference)); - let symbol = - getNodeLinks(reference).resolvedSymbol || - resolveName(reference, reference.text, SymbolFlags.Value | SymbolFlags.Alias, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined); - + let symbol = getReferencedValueSymbol(reference); return symbol && getExportSymbolOfValueSymbolIfExported(symbol).valueDeclaration; } @@ -12233,6 +12199,8 @@ module ts { function createResolver(): EmitResolver { return { getExpressionNameSubstitution, + getReferencedExportContainer, + getReferencedImportDeclaration, isValueAliasDeclaration, hasGlobalName, isReferencedAliasDeclaration, diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 32ebeaec08..2414c88a7a 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -249,81 +249,42 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } } - function assignGeneratedName(node: Node, name: string) { - nodeToGeneratedName[getNodeId(node)] = unescapeIdentifier(name); - } - - function generateNameForFunctionOrClassDeclaration(node: Declaration) { - if (!node.name) { - assignGeneratedName(node, makeUniqueName("default")); - } - } - function generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration) { - if (node.name.kind === SyntaxKind.Identifier) { - let name = node.name.text; - // Use module/enum name itself if it is unique, otherwise make a unique variation - assignGeneratedName(node, isUniqueLocalName(name, node) ? name : makeUniqueName(name)); - } + let name = node.name.text; + // Use module/enum name itself if it is unique, otherwise make a unique variation + return isUniqueLocalName(name, node) ? name : makeUniqueName(name); } function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) { let expr = getExternalModuleName(node); let baseName = expr.kind === SyntaxKind.StringLiteral ? escapeIdentifier(makeIdentifierFromModuleName((expr).text)) : "module"; - assignGeneratedName(node, makeUniqueName(baseName)); + return makeUniqueName(baseName); } - function generateNameForImportDeclaration(node: ImportDeclaration) { - if (node.importClause) { - generateNameForImportOrExportDeclaration(node); - } - } - - function generateNameForExportDeclaration(node: ExportDeclaration) { - if (node.moduleSpecifier) { - generateNameForImportOrExportDeclaration(node); - } - } - - function generateNameForExportAssignment(node: ExportAssignment) { - if (node.expression && node.expression.kind !== SyntaxKind.Identifier) { - assignGeneratedName(node, makeUniqueName("default")); - } + function generateNameForExportDefault() { + return makeUniqueName("default"); } function generateNameForNode(node: Node) { switch (node.kind) { + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.EnumDeclaration: + return generateNameForModuleOrEnum(node); + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ExportDeclaration: + return generateNameForImportOrExportDeclaration(node); case SyntaxKind.FunctionDeclaration: case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassExpression: - generateNameForFunctionOrClassDeclaration(node); - break; - case SyntaxKind.ModuleDeclaration: - generateNameForModuleOrEnum(node); - generateNameForNode((node).body); - break; - case SyntaxKind.EnumDeclaration: - generateNameForModuleOrEnum(node); - break; - case SyntaxKind.ImportDeclaration: - generateNameForImportDeclaration(node); - break; - case SyntaxKind.ExportDeclaration: - generateNameForExportDeclaration(node); - break; case SyntaxKind.ExportAssignment: - generateNameForExportAssignment(node); - break; + return generateNameForExportDefault(); } } function getGeneratedNameForNode(node: Node) { - let nodeId = getNodeId(node); - if (!nodeToGeneratedName[nodeId]) { - generateNameForNode(node); - } - return nodeToGeneratedName[nodeId]; + let id = getNodeId(node); + return nodeToGeneratedName[id] || (nodeToGeneratedName[id] = unescapeIdentifier(generateNameForNode(node))); } function initializeEmitterWithSourceMaps() { @@ -1201,51 +1162,96 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } } - function isNotExpressionIdentifier(node: Identifier) { + function isExpressionIdentifier(node: Node): boolean { let parent = node.parent; switch (parent.kind) { - case SyntaxKind.Parameter: - case SyntaxKind.VariableDeclaration: - case SyntaxKind.BindingElement: - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.PropertySignature: - case SyntaxKind.PropertyAssignment: - case SyntaxKind.ShorthandPropertyAssignment: - case SyntaxKind.EnumMember: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - case SyntaxKind.FunctionExpression: - case SyntaxKind.ClassDeclaration: - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.EnumDeclaration: - case SyntaxKind.ModuleDeclaration: - case SyntaxKind.ImportEqualsDeclaration: - case SyntaxKind.ImportClause: - case SyntaxKind.NamespaceImport: - return (parent).name === node; - case SyntaxKind.ImportSpecifier: - case SyntaxKind.ExportSpecifier: - return (parent).name === node || (parent).propertyName === node; - case SyntaxKind.BreakStatement: - case SyntaxKind.ContinueStatement: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.BinaryExpression: + case SyntaxKind.CallExpression: + case SyntaxKind.CaseClause: + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.ConditionalExpression: + case SyntaxKind.Decorator: + case SyntaxKind.DeleteExpression: + case SyntaxKind.DoStatement: + case SyntaxKind.ElementAccessExpression: case SyntaxKind.ExportAssignment: - return false; - case SyntaxKind.LabeledStatement: - return (node.parent).label === node; + case SyntaxKind.ExpressionStatement: + case SyntaxKind.ExpressionWithTypeArguments: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.IfStatement: + case SyntaxKind.NewExpression: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.PostfixUnaryExpression: + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.ReturnStatement: + case SyntaxKind.SpreadElementExpression: + case SyntaxKind.SwitchStatement: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.TemplateSpan: + case SyntaxKind.ThrowStatement: + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.TypeOfExpression: + case SyntaxKind.VoidExpression: + case SyntaxKind.WhileStatement: + case SyntaxKind.WithStatement: + case SyntaxKind.YieldExpression: + return true; + case SyntaxKind.BindingElement: + case SyntaxKind.EnumMember: + case SyntaxKind.Parameter: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.VariableDeclaration: + return (parent).initializer === node; + case SyntaxKind.PropertyAccessExpression: + return (parent).expression === node; + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + return (parent).body === node; + case SyntaxKind.ImportEqualsDeclaration: + return (parent).moduleReference === node; + case SyntaxKind.QualifiedName: + return (parent).left === node; } + return false; } function emitExpressionIdentifier(node: Identifier) { - let substitution = resolver.getExpressionNameSubstitution(node, getGeneratedNameForNode); - if (substitution) { - write(substitution); + let container = resolver.getReferencedExportContainer(node); + if (container) { + if (container.kind === SyntaxKind.SourceFile) { + // Identifier references module export + if (languageVersion < ScriptTarget.ES6 && compilerOptions.module !== ModuleKind.System) { + write("exports."); + } + } + else { + // Identifier references namespace export + write(getGeneratedNameForNode(container)); + write("."); + } } - else { - writeTextOfNode(currentSourceFile, node); + else if (languageVersion < ScriptTarget.ES6) { + let declaration = resolver.getReferencedImportDeclaration(node); + if (declaration) { + if (declaration.kind === SyntaxKind.ImportClause) { + // Identifier references default import + write(getGeneratedNameForNode(declaration.parent)); + write(languageVersion === ScriptTarget.ES3 ? '["default"]' : ".default"); + } + else { + // Identifier references named import + write(getGeneratedNameForNode(declaration.parent.parent.parent)); + write("."); + writeTextOfNode(currentSourceFile, (declaration).propertyName || (declaration).name); + } + return; + } } + writeTextOfNode(currentSourceFile, node); } function getGeneratedNameForIdentifier(node: Identifier): string { @@ -1272,7 +1278,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { if (!node.parent) { write(node.text); } - else if (!isNotExpressionIdentifier(node)) { + else if (isExpressionIdentifier(node)) { emitExpressionIdentifier(node); } else { @@ -1709,12 +1715,15 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { emitExpressionIdentifier(node.name); } } - else if (resolver.getExpressionNameSubstitution(node.name, getGeneratedNameForNode)) { - // Emit identifier as an identifier - write(": "); - // Even though this is stored as identifier treat it as an expression - // Short-hand, { x }, is equivalent of normal form { x: x } - emitExpressionIdentifier(node.name); + else { + let container = resolver.getReferencedExportContainer(node.name); + if (container && container.kind !== SyntaxKind.SourceFile) { + // Emit identifier as an identifier + write(": "); + // Even though this is stored as identifier treat it as an expression + // Short-hand, { x }, is equivalent of normal form { x: x } + emitExpressionIdentifier(node.name); + } } } @@ -4983,13 +4992,16 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } } - function getLocalNameForExternalImport(importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration): string { - let namespaceDeclaration = getNamespaceDeclarationNode(importNode); - if (namespaceDeclaration && !isDefaultImport(importNode)) { + function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration): string { + let namespaceDeclaration = getNamespaceDeclarationNode(node); + if (namespaceDeclaration && !isDefaultImport(node)) { return getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name); } - else { - return getGeneratedNameForNode(importNode); + if (node.kind === SyntaxKind.ImportDeclaration && (node).importClause) { + return getGeneratedNameForNode(node); + } + if (node.kind === SyntaxKind.ExportDeclaration && (node).moduleSpecifier) { + return getGeneratedNameForNode(node); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 14e53ee8f7..e64d6afad8 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1396,7 +1396,8 @@ module ts { /* @internal */ export interface EmitResolver { hasGlobalName(name: string): boolean; - getExpressionNameSubstitution(node: Identifier, getGeneratedNameForNode: (node: Node) => string): string; + getReferencedExportContainer(node: Identifier): SourceFile | ModuleDeclaration | EnumDeclaration; + getReferencedImportDeclaration(node: Identifier): ImportClause | ImportSpecifier; isValueAliasDeclaration(node: Node): boolean; isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean; isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean; From 1e39130f41a702e3f8ff53d939c87115bb53c5d8 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 3 Jun 2015 06:57:20 -0700 Subject: [PATCH 2/6] Unified logic for renamed block scoped locals and other generated names --- src/compiler/checker.ts | 47 ++++++++-- src/compiler/emitter.ts | 195 ++++++++++++++-------------------------- src/compiler/types.ts | 6 +- 3 files changed, 112 insertions(+), 136 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6257031afb..78dbe9077c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11821,6 +11821,38 @@ module ts { } } + function isStatementWithLocals(node: Node) { + switch (node.kind) { + case SyntaxKind.Block: + case SyntaxKind.CaseBlock: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + return true; + } + return false; + } + + function getIsNestedRedeclaration(symbol: Symbol): boolean { + let links = getSymbolLinks(symbol); + if (links.isNestedRedeclaration === undefined) { + let container = getEnclosingBlockScopeContainer(symbol.valueDeclaration); + links.isNestedRedeclaration = isStatementWithLocals(container) && + !!resolveName(container.parent, symbol.name, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined); + } + return links.isNestedRedeclaration; + } + + function getReferencedNestedRedeclaration(node: Identifier): Declaration { + let symbol = getReferencedValueSymbol(node); + return symbol && symbol.flags & SymbolFlags.BlockScoped && getIsNestedRedeclaration(symbol) ? symbol.valueDeclaration : undefined; + } + + function isNestedRedeclaration(node: Declaration): boolean { + let symbol = getSymbolOfNode(node); + return symbol.flags & SymbolFlags.BlockScoped && getIsNestedRedeclaration(symbol); + } + function isValueAliasDeclaration(node: Node): boolean { switch (node.kind) { case SyntaxKind.ImportEqualsDeclaration: @@ -11924,8 +11956,10 @@ module ts { /** Serializes an EntityName (with substitutions) to an appropriate JS constructor value. Used by the __metadata decorator. */ function serializeEntityName(node: EntityName, getGeneratedNameForNode: (Node: Node) => string, fallbackPath?: string[]): string { if (node.kind === SyntaxKind.Identifier) { - var substitution = getExpressionNameSubstitution(node, getGeneratedNameForNode); - var text = substitution || (node).text; + // TODO(andersh): Fix this + // var substitution = getExpressionNameSubstitution(node, getGeneratedNameForNode); + // var text = substitution || (node).text; + var text = (node).text; if (fallbackPath) { fallbackPath.push(text); } @@ -12140,11 +12174,6 @@ module ts { return hasProperty(globals, name); } - function resolvesToSomeValue(location: Node, name: string): boolean { - Debug.assert(!nodeIsSynthesized(location), "resolvesToSomeValue called with a synthesized location"); - return !!resolveName(location, name, SymbolFlags.Value, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined); - } - function getReferencedValueSymbol(reference: Identifier): Symbol { return getNodeLinks(reference).resolvedSymbol || resolveName(reference, reference.text, SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias, @@ -12198,9 +12227,10 @@ module ts { function createResolver(): EmitResolver { return { - getExpressionNameSubstitution, getReferencedExportContainer, getReferencedImportDeclaration, + getReferencedNestedRedeclaration, + isNestedRedeclaration, isValueAliasDeclaration, hasGlobalName, isReferencedAliasDeclaration, @@ -12214,7 +12244,6 @@ module ts { isSymbolAccessible, isEntityNameVisible, getConstantValue, - resolvesToSomeValue, collectLinkedAliases, getBlockScopedVariableId, getReferencedValueDeclaration, diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 2414c88a7a..96dec48d82 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -125,7 +125,6 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { let generatedNameSet: Map = {}; let nodeToGeneratedName: string[] = []; - let blockScopedVariableToGeneratedName: string[]; let computedPropertyNamesToGeneratedNames: string[]; let extendsEmitted = false; @@ -268,6 +267,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { function generateNameForNode(node: Node) { switch (node.kind) { + case SyntaxKind.Identifier: + return makeUniqueName((node).text); case SyntaxKind.ModuleDeclaration: case SyntaxKind.EnumDeclaration: return generateNameForModuleOrEnum(node); @@ -648,19 +649,19 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { sourceMapDir = getDirectoryPath(normalizePath(jsFilePath)); } - function emitNodeWithSourceMap(node: Node, allowGeneratedIdentifiers?: boolean) { + function emitNodeWithSourceMap(node: Node) { if (node) { if (nodeIsSynthesized(node)) { - return emitNodeWithoutSourceMap(node, /*allowGeneratedIdentifiers*/ false); + return emitNodeWithoutSourceMap(node); } if (node.kind != SyntaxKind.SourceFile) { recordEmitNodeStartSpan(node); - emitNodeWithoutSourceMap(node, allowGeneratedIdentifiers); + emitNodeWithoutSourceMap(node); recordEmitNodeEndSpan(node); } else { recordNewSourceFileStart(node); - emitNodeWithoutSourceMap(node, /*allowGeneratedIdentifiers*/ false); + emitNodeWithoutSourceMap(node); } } } @@ -1187,6 +1188,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { case SyntaxKind.PostfixUnaryExpression: case SyntaxKind.PrefixUnaryExpression: case SyntaxKind.ReturnStatement: + case SyntaxKind.ShorthandPropertyAssignment: case SyntaxKind.SpreadElementExpression: case SyntaxKind.SwitchStatement: case SyntaxKind.TaggedTemplateExpression: @@ -1235,52 +1237,54 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } } else if (languageVersion < ScriptTarget.ES6) { - let declaration = resolver.getReferencedImportDeclaration(node); - if (declaration) { - if (declaration.kind === SyntaxKind.ImportClause) { + let alias = resolver.getReferencedImportDeclaration(node); + if (alias) { + if (alias.kind === SyntaxKind.ImportClause) { // Identifier references default import - write(getGeneratedNameForNode(declaration.parent)); + write(getGeneratedNameForNode(alias.parent)); write(languageVersion === ScriptTarget.ES3 ? '["default"]' : ".default"); } else { // Identifier references named import - write(getGeneratedNameForNode(declaration.parent.parent.parent)); + write(getGeneratedNameForNode(alias.parent.parent.parent)); write("."); - writeTextOfNode(currentSourceFile, (declaration).propertyName || (declaration).name); + writeTextOfNode(currentSourceFile, (alias).propertyName || (alias).name); } return; } + let local = resolver.getReferencedNestedRedeclaration(node); + if (local) { + write(getGeneratedNameForNode(local.name)); + return; + } } writeTextOfNode(currentSourceFile, node); } - function getGeneratedNameForIdentifier(node: Identifier): string { - if (nodeIsSynthesized(node) || !blockScopedVariableToGeneratedName) { - return undefined; - } - - var variableId = resolver.getBlockScopedVariableId(node) - if (variableId === undefined) { - return undefined; - } - - return blockScopedVariableToGeneratedName[variableId]; - } - - function emitIdentifier(node: Identifier, allowGeneratedIdentifiers: boolean) { - if (allowGeneratedIdentifiers) { - let generatedName = getGeneratedNameForIdentifier(node); - if (generatedName) { - write(generatedName); - return; + function isNameOfNestedRedeclaration(node: Identifier) { + if (languageVersion < ScriptTarget.ES6) { + let parent = node.parent; + switch (parent.kind) { + case SyntaxKind.BindingElement: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.VariableDeclaration: + return (parent).name === node && resolver.isNestedRedeclaration(parent); } } + return false; + } + + function emitIdentifier(node: Identifier) { if (!node.parent) { write(node.text); } else if (isExpressionIdentifier(node)) { emitExpressionIdentifier(node); } + else if (isNameOfNestedRedeclaration(node)) { + write(getGeneratedNameForNode(node)); + } else { writeTextOfNode(currentSourceFile, node); } @@ -1326,7 +1330,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { function emitBindingElement(node: BindingElement) { if (node.propertyName) { - emit(node.propertyName, /*allowGeneratedIdentifiers*/ false); + emit(node.propertyName); write(": "); } if (node.dotDotDotToken) { @@ -1679,7 +1683,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { write("*"); } - emit(node.name, /*allowGeneratedIdentifiers*/ false); + emit(node.name); if (languageVersion < ScriptTarget.ES6) { write(": function "); } @@ -1687,43 +1691,34 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } function emitPropertyAssignment(node: PropertyDeclaration) { - emit(node.name, /*allowGeneratedIdentifiers*/ false); + emit(node.name); write(": "); emit(node.initializer); } + // Return true if identifier resolves to an exported member of a namespace + function isNamespaceExportReference(node: Identifier) { + let container = resolver.getReferencedExportContainer(node); + return container && container.kind !== SyntaxKind.SourceFile; + } + function emitShorthandPropertyAssignment(node: ShorthandPropertyAssignment) { - emit(node.name, /*allowGeneratedIdentifiers*/ false); - // If short-hand property has a prefix, then regardless of the target version, we will emit it as normal property assignment. For example: - // module m { - // export let y; - // } - // module m { - // export let obj = { y }; - // } - // The short-hand property in obj need to emit as such ... = { y : m.y } regardless of the TargetScript version - if (languageVersion < ScriptTarget.ES6) { + // The name property of a short-hand property assignment is considered an expression position, so here + // we manually emit the identifier to avoid rewriting. + writeTextOfNode(currentSourceFile, node.name); + // If emitting pre-ES6 code, or if the name requires rewriting when resolved as an expression identifier, + // we emit a normal property assignment. For example: + // module m { + // export let y; + // } + // module m { + // let obj = { y }; + // } + // Here we need to emit obj = { y : m.y } regardless of the output target. + if (languageVersion < ScriptTarget.ES6 || isNamespaceExportReference(node.name)) { // Emit identifier as an identifier write(": "); - var generatedName = getGeneratedNameForIdentifier(node.name); - if (generatedName) { - write(generatedName); - } - else { - // Even though this is stored as identifier treat it as an expression - // Short-hand, { x }, is equivalent of normal form { x: x } - emitExpressionIdentifier(node.name); - } - } - else { - let container = resolver.getReferencedExportContainer(node.name); - if (container && container.kind !== SyntaxKind.SourceFile) { - // Emit identifier as an identifier - write(": "); - // Even though this is stored as identifier treat it as an expression - // Short-hand, { x }, is equivalent of normal form { x: x } - emitExpressionIdentifier(node.name); - } + emit(node.name); } } @@ -1776,7 +1771,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { let indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, node.dotToken); write("."); let indentedAfterDot = indentIfOnDifferentLines(node, node.dotToken, node.name); - emit(node.name, /*allowGeneratedIdentifiers*/ false); + emit(node.name); decreaseIndentIf(indentedBeforeDot, indentedAfterDot); } @@ -2778,8 +2773,6 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { write(", "); } - renameNonTopLevelLetAndConst(name); - const isVariableDeclarationOrBindingElement = name.parent && (name.parent.kind === SyntaxKind.VariableDeclaration || name.parent.kind === SyntaxKind.BindingElement); @@ -2847,11 +2840,12 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } function createPropertyAccessForDestructuringProperty(object: Expression, propName: Identifier | LiteralExpression): Expression { - if (propName.kind !== SyntaxKind.Identifier) { - return createElementAccessExpression(object, propName); + let syntheticName = createSynthesizedNode(propName.kind); + syntheticName.text = propName.text; + if (syntheticName.kind !== SyntaxKind.Identifier) { + return createElementAccessExpression(object, syntheticName); } - - return createPropertyAccessExpression(object, propName); + return createPropertyAccessExpression(object, syntheticName); } function createSliceCall(value: Expression, sliceIndex: number): CallExpression { @@ -2873,8 +2867,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } for (let p of properties) { if (p.kind === SyntaxKind.PropertyAssignment || p.kind === SyntaxKind.ShorthandPropertyAssignment) { - // TODO(andersh): Computed property support - let propName = ((p).name); + let propName = (p).name; emitDestructuringAssignment((p).initializer || propName, createPropertyAccessForDestructuringProperty(value, propName)); } } @@ -2988,8 +2981,6 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } } else { - renameNonTopLevelLetAndConst(node.name); - let initializer = node.initializer; if (!initializer && languageVersion < ScriptTarget.ES6) { @@ -3049,54 +3040,6 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { return getCombinedNodeFlags(node.parent); } - function renameNonTopLevelLetAndConst(node: Node): void { - // do not rename if - // - language version is ES6+ - // - node is synthesized - // - node is not identifier (can happen when tree is malformed) - // - node is definitely not name of variable declaration. - // it still can be part of parameter declaration, this check will be done next - if (languageVersion >= ScriptTarget.ES6 || - nodeIsSynthesized(node) || - node.kind !== SyntaxKind.Identifier || - (node.parent.kind !== SyntaxKind.VariableDeclaration && node.parent.kind !== SyntaxKind.BindingElement)) { - return; - } - - let combinedFlags = getCombinedFlagsForIdentifier(node); - if (((combinedFlags & NodeFlags.BlockScoped) === 0) || combinedFlags & NodeFlags.Export) { - // do not rename exported or non-block scoped variables - return; - } - - // here it is known that node is a block scoped variable - let list = getAncestor(node, SyntaxKind.VariableDeclarationList); - if (list.parent.kind === SyntaxKind.VariableStatement) { - let isSourceFileLevelBinding = list.parent.parent.kind === SyntaxKind.SourceFile; - let isModuleLevelBinding = list.parent.parent.kind === SyntaxKind.ModuleBlock; - let isFunctionLevelBinding = - list.parent.parent.kind === SyntaxKind.Block && isFunctionLike(list.parent.parent.parent); - if (isSourceFileLevelBinding || isModuleLevelBinding || isFunctionLevelBinding) { - return; - } - } - - let blockScopeContainer = getEnclosingBlockScopeContainer(node); - let parent = blockScopeContainer.kind === SyntaxKind.SourceFile - ? blockScopeContainer - : blockScopeContainer.parent; - - if (resolver.resolvesToSomeValue(parent, (node).text)) { - let variableId = resolver.getBlockScopedVariableId(node); - if (!blockScopedVariableToGeneratedName) { - blockScopedVariableToGeneratedName = []; - } - - let generatedName = makeUniqueName((node).text); - blockScopedVariableToGeneratedName[variableId] = generatedName; - } - } - function isES6ExportedDeclaration(node: Node) { return !!(node.flags & NodeFlags.Export) && languageVersion >= ScriptTarget.ES6 && @@ -3260,7 +3203,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { function emitAccessor(node: AccessorDeclaration) { write(node.kind === SyntaxKind.GetAccessor ? "get " : "set "); - emit(node.name, /*allowGeneratedIdentifiers*/ false); + emit(node.name); emitSignatureAndBody(node); } @@ -5786,7 +5729,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { emitLeadingComments(node.endOfFileToken); } - function emitNodeWithoutSourceMap(node: Node, allowGeneratedIdentifiers?: boolean): void { + function emitNodeWithoutSourceMap(node: Node): void { if (!node) { return; } @@ -5800,7 +5743,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { emitLeadingComments(node); } - emitJavaScriptWorker(node, allowGeneratedIdentifiers); + emitJavaScriptWorker(node); if (emitComments) { emitTrailingComments(node); @@ -5850,11 +5793,11 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { return true; } - function emitJavaScriptWorker(node: Node, allowGeneratedIdentifiers: boolean = true) { + function emitJavaScriptWorker(node: Node) { // Check if the node can be emitted regardless of the ScriptTarget switch (node.kind) { case SyntaxKind.Identifier: - return emitIdentifier(node, allowGeneratedIdentifiers); + return emitIdentifier(node); case SyntaxKind.Parameter: return emitParameter(node); case SyntaxKind.MethodDeclaration: diff --git a/src/compiler/types.ts b/src/compiler/types.ts index e64d6afad8..a8478a8279 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1398,6 +1398,8 @@ module ts { hasGlobalName(name: string): boolean; getReferencedExportContainer(node: Identifier): SourceFile | ModuleDeclaration | EnumDeclaration; getReferencedImportDeclaration(node: Identifier): ImportClause | ImportSpecifier; + getReferencedNestedRedeclaration(node: Identifier): Declaration; + isNestedRedeclaration(node: Declaration): boolean; isValueAliasDeclaration(node: Node): boolean; isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean; isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean; @@ -1412,7 +1414,6 @@ module ts { isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult; // Returns the constant value this property access resolves to, or 'undefined' for a non-constant getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number; - resolvesToSomeValue(location: Node, name: string): boolean; getBlockScopedVariableId(node: Identifier): number; getReferencedValueDeclaration(reference: Identifier): Declaration; serializeTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[]; @@ -1494,6 +1495,8 @@ module ts { HasExports = Class | Enum | Module, HasMembers = Class | Interface | TypeLiteral | ObjectLiteral, + BlockScoped = BlockScopedVariable | Class | Enum, + IsContainer = HasLocals | HasExports | HasMembers, PropertyOrAccessor = Property | Accessor, Export = ExportNamespace | ExportType | ExportValue, @@ -1523,6 +1526,7 @@ module ts { unionType?: UnionType; // Containing union type for union property resolvedExports?: SymbolTable; // Resolved exports of module exportsChecked?: boolean; // True if exports of external module have been checked + isNestedRedeclaration?: boolean; // True if symbol is block scoped redeclaration } /* @internal */ From 334b22452a038725bad262c64fedea725eeefc41 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 3 Jun 2015 10:59:14 -0700 Subject: [PATCH 3/6] Moving logic around in getReferencedImportDeclaration --- src/compiler/checker.ts | 39 ++++++++++++++++++++------------------- src/compiler/emitter.ts | 23 ++++++++++++----------- src/compiler/types.ts | 2 +- 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 78dbe9077c..85bb37c135 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11809,16 +11809,11 @@ module ts { } } - // When resolved as an expression identifier, if the given node references a default import or a named import, return - // the declaration node of that import. Otherwise, return undefined. - function getReferencedImportDeclaration(node: Identifier): ImportClause | ImportSpecifier { + // When resolved as an expression identifier, if the given node references an import, return the declaration of + // that import. Otherwise, return undefined. + function getReferencedImportDeclaration(node: Identifier): Declaration { let symbol = getReferencedValueSymbol(node); - if (symbol && symbol.flags & SymbolFlags.Alias) { - let declaration = getDeclarationOfAliasSymbol(symbol); - if (declaration.kind === SyntaxKind.ImportClause || declaration.kind === SyntaxKind.ImportSpecifier) { - return declaration; - } - } + return symbol && symbol.flags & SymbolFlags.Alias ? getDeclarationOfAliasSymbol(symbol) : undefined; } function isStatementWithLocals(node: Node) { @@ -11833,24 +11828,30 @@ module ts { return false; } - function getIsNestedRedeclaration(symbol: Symbol): boolean { - let links = getSymbolLinks(symbol); - if (links.isNestedRedeclaration === undefined) { - let container = getEnclosingBlockScopeContainer(symbol.valueDeclaration); - links.isNestedRedeclaration = isStatementWithLocals(container) && - !!resolveName(container.parent, symbol.name, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined); + function isNestedRedeclarationSymbol(symbol: Symbol): boolean { + if (symbol.flags & SymbolFlags.BlockScoped) { + let links = getSymbolLinks(symbol); + if (links.isNestedRedeclaration === undefined) { + let container = getEnclosingBlockScopeContainer(symbol.valueDeclaration); + links.isNestedRedeclaration = isStatementWithLocals(container) && + !!resolveName(container.parent, symbol.name, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined); + } + return links.isNestedRedeclaration; } - return links.isNestedRedeclaration; + return false; } + // When resolved as an expression identifier, if the given node references a nested block scoped entity with + // a name that hides an existing name, return the declaration of that entity. Otherwise, return undefined. function getReferencedNestedRedeclaration(node: Identifier): Declaration { let symbol = getReferencedValueSymbol(node); - return symbol && symbol.flags & SymbolFlags.BlockScoped && getIsNestedRedeclaration(symbol) ? symbol.valueDeclaration : undefined; + return symbol && isNestedRedeclarationSymbol(symbol) ? symbol.valueDeclaration : undefined; } + // Return true if the given node is a declaration of a nested block scoped entity with a name that hides an + // existing name. function isNestedRedeclaration(node: Declaration): boolean { - let symbol = getSymbolOfNode(node); - return symbol.flags & SymbolFlags.BlockScoped && getIsNestedRedeclaration(symbol); + return isNestedRedeclarationSymbol(getSymbolOfNode(node)); } function isValueAliasDeclaration(node: Node): boolean { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 96dec48d82..6a68c6b0e8 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1237,24 +1237,25 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } } else if (languageVersion < ScriptTarget.ES6) { - let alias = resolver.getReferencedImportDeclaration(node); - if (alias) { - if (alias.kind === SyntaxKind.ImportClause) { + let declaration = resolver.getReferencedImportDeclaration(node); + if (declaration) { + if (declaration.kind === SyntaxKind.ImportClause) { // Identifier references default import - write(getGeneratedNameForNode(alias.parent)); + write(getGeneratedNameForNode(declaration.parent)); write(languageVersion === ScriptTarget.ES3 ? '["default"]' : ".default"); + return; } - else { + else if (declaration.kind === SyntaxKind.ImportSpecifier) { // Identifier references named import - write(getGeneratedNameForNode(alias.parent.parent.parent)); + write(getGeneratedNameForNode(declaration.parent.parent.parent)); write("."); - writeTextOfNode(currentSourceFile, (alias).propertyName || (alias).name); + writeTextOfNode(currentSourceFile, (declaration).propertyName || (declaration).name); + return; } - return; } - let local = resolver.getReferencedNestedRedeclaration(node); - if (local) { - write(getGeneratedNameForNode(local.name)); + declaration = resolver.getReferencedNestedRedeclaration(node); + if (declaration) { + write(getGeneratedNameForNode(declaration.name)); return; } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a8478a8279..205e103444 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1397,7 +1397,7 @@ module ts { export interface EmitResolver { hasGlobalName(name: string): boolean; getReferencedExportContainer(node: Identifier): SourceFile | ModuleDeclaration | EnumDeclaration; - getReferencedImportDeclaration(node: Identifier): ImportClause | ImportSpecifier; + getReferencedImportDeclaration(node: Identifier): Declaration; getReferencedNestedRedeclaration(node: Identifier): Declaration; isNestedRedeclaration(node: Declaration): boolean; isValueAliasDeclaration(node: Node): boolean; From f3e6f5ba1f098496414857753894623a4ce73ffe Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 4 Jun 2015 07:16:06 -0700 Subject: [PATCH 4/6] Removing getGeneratedNameForNode from type serializers --- src/compiler/checker.ts | 41 +++++++++++++++++++++-------------------- src/compiler/emitter.ts | 6 +++--- src/compiler/types.ts | 6 +++--- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 85bb37c135..1076fac90b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11955,9 +11955,10 @@ module ts { } /** Serializes an EntityName (with substitutions) to an appropriate JS constructor value. Used by the __metadata decorator. */ - function serializeEntityName(node: EntityName, getGeneratedNameForNode: (Node: Node) => string, fallbackPath?: string[]): string { + function serializeEntityName(node: EntityName, fallbackPath?: string[]): string { if (node.kind === SyntaxKind.Identifier) { - // TODO(andersh): Fix this + // TODO(ron.buckton): The getExpressionNameSubstitution function has been removed, but calling it + // here has no effect anyway as an identifier in a type name is not an expression. // var substitution = getExpressionNameSubstitution(node, getGeneratedNameForNode); // var text = substitution || (node).text; var text = (node).text; @@ -11969,8 +11970,8 @@ module ts { } } else { - var left = serializeEntityName((node).left, getGeneratedNameForNode, fallbackPath); - var right = serializeEntityName((node).right, getGeneratedNameForNode, fallbackPath); + var left = serializeEntityName((node).left, fallbackPath); + var right = serializeEntityName((node).right, fallbackPath); if (!fallbackPath) { return left + "." + right; } @@ -11978,7 +11979,7 @@ module ts { } /** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */ - function serializeTypeReferenceNode(node: TypeReferenceNode, getGeneratedNameForNode: (Node: Node) => string): string | string[] { + function serializeTypeReferenceNode(node: TypeReferenceNode): string | string[] { // serialization of a TypeReferenceNode uses the following rules: // // * The serialized type of a TypeReference that is `void` is "void 0". @@ -12011,11 +12012,11 @@ module ts { } else if (type === unknownType) { var fallbackPath: string[] = []; - serializeEntityName(node.typeName, getGeneratedNameForNode, fallbackPath); + serializeEntityName(node.typeName, fallbackPath); return fallbackPath; } else if (type.symbol && type.symbol.valueDeclaration) { - return serializeEntityName(node.typeName, getGeneratedNameForNode); + return serializeEntityName(node.typeName); } else if (typeHasCallOrConstructSignatures(type)) { return "Function"; @@ -12025,7 +12026,7 @@ module ts { } /** Serializes a TypeNode to an appropriate JS constructor value. Used by the __metadata decorator. */ - function serializeTypeNode(node: TypeNode | LiteralExpression, getGeneratedNameForNode: (Node: Node) => string): string | string[] { + function serializeTypeNode(node: TypeNode | LiteralExpression): string | string[] { // serialization of a TypeNode uses the following rules: // // * The serialized type of `void` is "void 0" (undefined). @@ -12041,7 +12042,7 @@ module ts { case SyntaxKind.VoidKeyword: return "void 0"; case SyntaxKind.ParenthesizedType: - return serializeTypeNode((node).type, getGeneratedNameForNode); + return serializeTypeNode((node).type); case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: return "Function"; @@ -12056,7 +12057,7 @@ module ts { case SyntaxKind.NumberKeyword: return "Number"; case SyntaxKind.TypeReference: - return serializeTypeReferenceNode(node, getGeneratedNameForNode); + return serializeTypeReferenceNode(node); case SyntaxKind.TypeQuery: case SyntaxKind.TypeLiteral: case SyntaxKind.UnionType: @@ -12072,7 +12073,7 @@ module ts { } /** Serializes the type of a declaration to an appropriate JS constructor value. Used by the __metadata decorator for a class member. */ - function serializeTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[] { + function serializeTypeOfNode(node: Node): string | string[] { // serialization of the type of a declaration uses the following rules: // // * The serialized type of a ClassDeclaration is "Function" @@ -12085,10 +12086,10 @@ module ts { // For rules on serializing type annotations, see `serializeTypeNode`. switch (node.kind) { case SyntaxKind.ClassDeclaration: return "Function"; - case SyntaxKind.PropertyDeclaration: return serializeTypeNode((node).type, getGeneratedNameForNode); - case SyntaxKind.Parameter: return serializeTypeNode((node).type, getGeneratedNameForNode); - case SyntaxKind.GetAccessor: return serializeTypeNode((node).type, getGeneratedNameForNode); - case SyntaxKind.SetAccessor: return serializeTypeNode(getSetAccessorTypeAnnotationNode(node), getGeneratedNameForNode); + case SyntaxKind.PropertyDeclaration: return serializeTypeNode((node).type); + case SyntaxKind.Parameter: return serializeTypeNode((node).type); + case SyntaxKind.GetAccessor: return serializeTypeNode((node).type); + case SyntaxKind.SetAccessor: return serializeTypeNode(getSetAccessorTypeAnnotationNode(node)); } if (isFunctionLike(node)) { return "Function"; @@ -12097,7 +12098,7 @@ module ts { } /** Serializes the parameter types of a function or the constructor of a class. Used by the __metadata decorator for a method or set accessor. */ - function serializeParameterTypesOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): (string | string[])[] { + function serializeParameterTypesOfNode(node: Node): (string | string[])[] { // serialization of parameter types uses the following rules: // // * If the declaration is a class, the parameters of the first constructor with a body are used. @@ -12130,10 +12131,10 @@ module ts { else { parameterType = undefined; } - result[i] = serializeTypeNode(parameterType, getGeneratedNameForNode); + result[i] = serializeTypeNode(parameterType); } else { - result[i] = serializeTypeOfNode(parameters[i], getGeneratedNameForNode); + result[i] = serializeTypeOfNode(parameters[i]); } } return result; @@ -12144,9 +12145,9 @@ module ts { } /** Serializes the return type of function. Used by the __metadata decorator for a method. */ - function serializeReturnTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[] { + function serializeReturnTypeOfNode(node: Node): string | string[] { if (node && isFunctionLike(node)) { - return serializeTypeNode((node).type, getGeneratedNameForNode); + return serializeTypeNode((node).type); } return "void 0"; } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 6a68c6b0e8..2ad3f3634e 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -4307,7 +4307,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { let argumentsWritten = 0; if (compilerOptions.emitDecoratorMetadata) { if (shouldEmitTypeMetadata(node)) { - var serializedType = resolver.serializeTypeOfNode(node, getGeneratedNameForNode); + var serializedType = resolver.serializeTypeOfNode(node); if (serializedType) { if (writeComma) { write(", "); @@ -4320,7 +4320,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } } if (shouldEmitParamTypesMetadata(node)) { - var serializedTypes = resolver.serializeParameterTypesOfNode(node, getGeneratedNameForNode); + var serializedTypes = resolver.serializeParameterTypesOfNode(node); if (serializedTypes) { if (writeComma || argumentsWritten) { write(", "); @@ -4338,7 +4338,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } } if (shouldEmitReturnTypeMetadata(node)) { - var serializedType = resolver.serializeReturnTypeOfNode(node, getGeneratedNameForNode); + var serializedType = resolver.serializeReturnTypeOfNode(node); if (serializedType) { if (writeComma || argumentsWritten) { write(", "); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 205e103444..26736b69d8 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1416,9 +1416,9 @@ module ts { getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number; getBlockScopedVariableId(node: Identifier): number; getReferencedValueDeclaration(reference: Identifier): Declaration; - serializeTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[]; - serializeParameterTypesOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): (string | string[])[]; - serializeReturnTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[]; + serializeTypeOfNode(node: Node): string | string[]; + serializeParameterTypesOfNode(node: Node): (string | string[])[]; + serializeReturnTypeOfNode(node: Node): string | string[]; } export const enum SymbolFlags { From fc1bafdc578ac6ccdb0dc4f950436c95b9411288 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 4 Jun 2015 09:44:54 -0700 Subject: [PATCH 5/6] Accepting new baselines --- tests/baselines/reference/ES5For-of17.js | 2 +- tests/baselines/reference/ES5For-of20.js | 2 +- .../baselines/reference/classDeclarationBlockScoping1.js | 6 +++--- .../baselines/reference/classDeclarationBlockScoping2.js | 8 ++++---- tests/baselines/reference/exportsAndImports3-amd.js | 8 ++++---- tests/baselines/reference/exportsAndImports3.js | 8 ++++---- tests/baselines/reference/localTypes1.js | 8 ++++---- .../amd/testGlo.js | 4 ++-- .../node/testGlo.js | 4 ++-- 9 files changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/baselines/reference/ES5For-of17.js b/tests/baselines/reference/ES5For-of17.js index 50064d8293..fb3a02fd0e 100644 --- a/tests/baselines/reference/ES5For-of17.js +++ b/tests/baselines/reference/ES5For-of17.js @@ -11,7 +11,7 @@ for (let v of []) { for (var _i = 0, _a = []; _i < _a.length; _i++) { var v = _a[_i]; v; - for (var _b = 0, _c = [v]; _b < _c.length; _b++) { + for (var _b = 0, _c = [v_1]; _b < _c.length; _b++) { var v_1 = _c[_b]; var x = v_1; v_1++; diff --git a/tests/baselines/reference/ES5For-of20.js b/tests/baselines/reference/ES5For-of20.js index c6376ab05d..d21ab73f8b 100644 --- a/tests/baselines/reference/ES5For-of20.js +++ b/tests/baselines/reference/ES5For-of20.js @@ -10,7 +10,7 @@ for (let v of []) { for (var _i = 0, _a = []; _i < _a.length; _i++) { var v = _a[_i]; var v_1; - for (var _b = 0, _c = [v]; _b < _c.length; _b++) { + for (var _b = 0, _c = [v_2]; _b < _c.length; _b++) { var v_2 = _c[_b]; var v_3; } diff --git a/tests/baselines/reference/classDeclarationBlockScoping1.js b/tests/baselines/reference/classDeclarationBlockScoping1.js index 717c2f788c..4c7f9d8e24 100644 --- a/tests/baselines/reference/classDeclarationBlockScoping1.js +++ b/tests/baselines/reference/classDeclarationBlockScoping1.js @@ -14,9 +14,9 @@ var C = (function () { return C; })(); { - var C = (function () { - function C() { + var C_1 = (function () { + function C_1() { } - return C; + return C_1; })(); } diff --git a/tests/baselines/reference/classDeclarationBlockScoping2.js b/tests/baselines/reference/classDeclarationBlockScoping2.js index 9e46807711..57001d0d28 100644 --- a/tests/baselines/reference/classDeclarationBlockScoping2.js +++ b/tests/baselines/reference/classDeclarationBlockScoping2.js @@ -18,12 +18,12 @@ function f() { })(); var c1 = C; { - var C = (function () { - function C() { + var C_1 = (function () { + function C_1() { } - return C; + return C_1; })(); - var c2 = C; + var c2 = C_1; } return C === c1; } diff --git a/tests/baselines/reference/exportsAndImports3-amd.js b/tests/baselines/reference/exportsAndImports3-amd.js index e816dec9f6..3a33b12c7f 100644 --- a/tests/baselines/reference/exportsAndImports3-amd.js +++ b/tests/baselines/reference/exportsAndImports3-amd.js @@ -40,25 +40,25 @@ define(["require", "exports"], function (require, exports) { exports.v1 = exports.v; function f() { } exports.f = f; - exports.f1 = exports.f; + exports.f1 = f; var C = (function () { function C() { } return C; })(); exports.C = C; - exports.C1 = exports.C; + exports.C1 = C; (function (E) { E[E["A"] = 0] = "A"; E[E["B"] = 1] = "B"; E[E["C"] = 2] = "C"; })(exports.E || (exports.E = {})); var E = exports.E; - exports.E1 = exports.E; + exports.E1 = E; var M; (function (M) { })(M = exports.M || (exports.M = {})); - exports.M1 = exports.M; + exports.M1 = M; exports.a = M.x; exports.a1 = exports.a; }); diff --git a/tests/baselines/reference/exportsAndImports3.js b/tests/baselines/reference/exportsAndImports3.js index db29b62449..47491ccbc0 100644 --- a/tests/baselines/reference/exportsAndImports3.js +++ b/tests/baselines/reference/exportsAndImports3.js @@ -39,25 +39,25 @@ exports.v = 1; exports.v1 = exports.v; function f() { } exports.f = f; -exports.f1 = exports.f; +exports.f1 = f; var C = (function () { function C() { } return C; })(); exports.C = C; -exports.C1 = exports.C; +exports.C1 = C; (function (E) { E[E["A"] = 0] = "A"; E[E["B"] = 1] = "B"; E[E["C"] = 2] = "C"; })(exports.E || (exports.E = {})); var E = exports.E; -exports.E1 = exports.E; +exports.E1 = E; var M; (function (M) { })(M = exports.M || (exports.M = {})); -exports.M1 = exports.M; +exports.M1 = M; exports.a = M.x; exports.a1 = exports.a; //// [t2.js] diff --git a/tests/baselines/reference/localTypes1.js b/tests/baselines/reference/localTypes1.js index d1c3758920..09fa9c04f3 100644 --- a/tests/baselines/reference/localTypes1.js +++ b/tests/baselines/reference/localTypes1.js @@ -202,12 +202,12 @@ function f3(b) { return a; } else { - var A = (function () { - function A() { + var A_1 = (function () { + function A_1() { } - return A; + return A_1; })(); - var c = [new A()]; + var c = [new A_1()]; c[0].x = E.B; return c; } diff --git a/tests/baselines/reference/project/privacyCheckOnImportedModuleDeclarationsInsideModule/amd/testGlo.js b/tests/baselines/reference/project/privacyCheckOnImportedModuleDeclarationsInsideModule/amd/testGlo.js index 5bdce5cf48..1ce3452dbe 100644 --- a/tests/baselines/reference/project/privacyCheckOnImportedModuleDeclarationsInsideModule/amd/testGlo.js +++ b/tests/baselines/reference/project/privacyCheckOnImportedModuleDeclarationsInsideModule/amd/testGlo.js @@ -18,7 +18,7 @@ var m2; _super.apply(this, arguments); } return class1; - })(mExported.me.class1); + })(m2.mExported.me.class1); m2.class1 = class1; var c2 = new m2.mExported.me.class1; function f2() { @@ -31,7 +31,7 @@ var m2; _super.apply(this, arguments); } return class2; - })(mExported.me.class1); + })(m2.mExported.me.class1); m2.c3 = new mNonExported.mne.class1; function f3() { return new mNonExported.mne.class1(); diff --git a/tests/baselines/reference/project/privacyCheckOnImportedModuleDeclarationsInsideModule/node/testGlo.js b/tests/baselines/reference/project/privacyCheckOnImportedModuleDeclarationsInsideModule/node/testGlo.js index 5bdce5cf48..1ce3452dbe 100644 --- a/tests/baselines/reference/project/privacyCheckOnImportedModuleDeclarationsInsideModule/node/testGlo.js +++ b/tests/baselines/reference/project/privacyCheckOnImportedModuleDeclarationsInsideModule/node/testGlo.js @@ -18,7 +18,7 @@ var m2; _super.apply(this, arguments); } return class1; - })(mExported.me.class1); + })(m2.mExported.me.class1); m2.class1 = class1; var c2 = new m2.mExported.me.class1; function f2() { @@ -31,7 +31,7 @@ var m2; _super.apply(this, arguments); } return class2; - })(mExported.me.class1); + })(m2.mExported.me.class1); m2.c3 = new mNonExported.mne.class1; function f3() { return new mNonExported.mne.class1(); From 7b67ac243cb0a4524fdeaaf92697517176e48189 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 9 Jun 2015 06:48:20 -0700 Subject: [PATCH 6/6] Addressing CR feedback --- src/compiler/checker.ts | 8 ++++++-- src/compiler/emitter.ts | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1076fac90b..7132a4b711 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11790,10 +11790,14 @@ module ts { let symbol = getReferencedValueSymbol(node); if (symbol) { if (symbol.flags & SymbolFlags.ExportValue) { + // If we reference an exported entity within the same module declaration, then whether + // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the + // kinds that we do NOT prefix. let exportSymbol = getMergedSymbol(symbol.exportSymbol); - if (!(exportSymbol.flags & SymbolFlags.ExportHasLocal)) { - symbol = exportSymbol; + if (exportSymbol.flags & SymbolFlags.ExportHasLocal) { + return undefined; } + symbol = exportSymbol; } let parentSymbol = getParentOfSymbol(symbol); if (parentSymbol) { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 2ad3f3634e..50421c61f4 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2841,6 +2841,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } function createPropertyAccessForDestructuringProperty(object: Expression, propName: Identifier | LiteralExpression): Expression { + // We create a synthetic copy of the identifier in order to avoid the rewriting that might + // otherwise occur when the identifier is emitted. let syntheticName = createSynthesizedNode(propName.kind); syntheticName.text = propName.text; if (syntheticName.kind !== SyntaxKind.Identifier) {