mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-19 01:33:15 -05:00
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
This commit is contained in:
@@ -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(<ImportDeclaration>node.parent) + defaultKeyword;
|
||||
}
|
||||
if (node.kind === SyntaxKind.ImportSpecifier) {
|
||||
let moduleName = getGeneratedNameForNode(<ImportDeclaration>node.parent.parent.parent);
|
||||
let propertyName = (<ImportSpecifier>node).propertyName || (<ImportSpecifier>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(<ModuleDeclaration | EnumDeclaration>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 <SourceFile>parentSymbol.valueDeclaration;
|
||||
}
|
||||
for (let n = node.parent; n; n = n.parent) {
|
||||
if ((n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.EnumDeclaration) && getSymbolOfNode(n) === parentSymbol) {
|
||||
return <ModuleDeclaration | EnumDeclaration>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 <ImportClause | ImportSpecifier>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,
|
||||
|
||||
@@ -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((<LiteralExpression>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(<ModuleDeclaration | EnumDeclaration>node);
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
return generateNameForImportOrExportDeclaration(<ImportDeclaration | ExportDeclaration>node);
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
generateNameForFunctionOrClassDeclaration(<Declaration>node);
|
||||
break;
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
generateNameForModuleOrEnum(<ModuleDeclaration>node);
|
||||
generateNameForNode((<ModuleDeclaration>node).body);
|
||||
break;
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
generateNameForModuleOrEnum(<EnumDeclaration>node);
|
||||
break;
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
generateNameForImportDeclaration(<ImportDeclaration>node);
|
||||
break;
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
generateNameForExportDeclaration(<ExportDeclaration>node);
|
||||
break;
|
||||
case SyntaxKind.ExportAssignment:
|
||||
generateNameForExportAssignment(<ExportAssignment>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 (<Declaration>parent).name === node;
|
||||
case SyntaxKind.ImportSpecifier:
|
||||
case SyntaxKind.ExportSpecifier:
|
||||
return (<ImportOrExportSpecifier>parent).name === node || (<ImportOrExportSpecifier>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 (<LabeledStatement>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 (<BindingElement | EnumMember | ParameterDeclaration | PropertyAssignment | PropertyDeclaration | VariableDeclaration>parent).initializer === node;
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
return (<ExpressionStatement>parent).expression === node;
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
return (<FunctionLikeDeclaration>parent).body === node;
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
return (<ImportEqualsDeclaration>parent).moduleReference === node;
|
||||
case SyntaxKind.QualifiedName:
|
||||
return (<QualifiedName>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(<ImportDeclaration>declaration.parent));
|
||||
write(languageVersion === ScriptTarget.ES3 ? '["default"]' : ".default");
|
||||
}
|
||||
else {
|
||||
// Identifier references named import
|
||||
write(getGeneratedNameForNode(<ImportDeclaration>declaration.parent.parent.parent));
|
||||
write(".");
|
||||
writeTextOfNode(currentSourceFile, (<ImportSpecifier>declaration).propertyName || (<ImportSpecifier>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(<ImportDeclaration | ExportDeclaration>importNode);
|
||||
if (node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).importClause) {
|
||||
return getGeneratedNameForNode(node);
|
||||
}
|
||||
if (node.kind === SyntaxKind.ExportDeclaration && (<ExportDeclaration>node).moduleSpecifier) {
|
||||
return getGeneratedNameForNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user