mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-20 13:45:34 -05:00
Merge pull request #23834 from Microsoft/generateNamesEarlier
Pre-generate names ahead of time
This commit is contained in:
@@ -1378,6 +1378,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitObjectLiteralExpression(node: ObjectLiteralExpression) {
|
||||
forEach(node.properties, generateMemberNames);
|
||||
|
||||
const indentedFlag = getEmitFlags(node) & EmitFlags.Indented;
|
||||
if (indentedFlag) {
|
||||
increaseIndent();
|
||||
@@ -1481,6 +1483,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitFunctionExpression(node: FunctionExpression) {
|
||||
generateNameIfNeeded(node.name);
|
||||
emitFunctionDeclarationOrExpression(node);
|
||||
}
|
||||
|
||||
@@ -1606,6 +1609,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitClassExpression(node: ClassExpression) {
|
||||
generateNameIfNeeded(node.name);
|
||||
emitClassDeclarationOrExpression(node);
|
||||
}
|
||||
|
||||
@@ -1911,6 +1915,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
pushNameGenerationScope(node);
|
||||
forEach(node.parameters, generateNames);
|
||||
generateNames(node.body);
|
||||
|
||||
emitSignatureHead(node);
|
||||
if (onEmitNode) {
|
||||
onEmitNode(EmitHint.Unspecified, body, emitBlockCallback);
|
||||
@@ -2025,6 +2032,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitClassDeclarationOrExpression(node: ClassDeclaration | ClassExpression) {
|
||||
forEach(node.members, generateMemberNames);
|
||||
|
||||
emitDecorators(node, node.decorators);
|
||||
emitModifiers(node, node.modifiers);
|
||||
writeKeyword("class");
|
||||
@@ -2113,6 +2122,7 @@ namespace ts {
|
||||
|
||||
function emitModuleBlock(node: ModuleBlock) {
|
||||
pushNameGenerationScope(node);
|
||||
forEach(node.statements, generateNames);
|
||||
emitBlockStatements(node, /*forceSingleLine*/ isEmptyBlock(node));
|
||||
popNameGenerationScope(node);
|
||||
}
|
||||
@@ -2516,6 +2526,7 @@ namespace ts {
|
||||
function emitSourceFileWorker(node: SourceFile) {
|
||||
const statements = node.statements;
|
||||
pushNameGenerationScope(node);
|
||||
forEach(node.statements, generateNames);
|
||||
emitHelpers(node);
|
||||
const index = findIndex(statements, statement => !isPrologueDirective(statement));
|
||||
emitTripleSlashDirectivesIfNeeded(node);
|
||||
@@ -3222,6 +3233,114 @@ namespace ts {
|
||||
reservedNames.set(name, true);
|
||||
}
|
||||
|
||||
function generateNames(node: Node | undefined) {
|
||||
if (!node) return;
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.Block:
|
||||
forEach((<Block>node).statements, generateNames);
|
||||
break;
|
||||
case SyntaxKind.LabeledStatement:
|
||||
case SyntaxKind.WithStatement:
|
||||
case SyntaxKind.DoStatement:
|
||||
case SyntaxKind.WhileStatement:
|
||||
generateNames((<LabeledStatement | WithStatement | DoStatement | WhileStatement>node).statement);
|
||||
break;
|
||||
case SyntaxKind.IfStatement:
|
||||
generateNames((<IfStatement>node).thenStatement);
|
||||
generateNames((<IfStatement>node).elseStatement);
|
||||
break;
|
||||
case SyntaxKind.ForStatement:
|
||||
case SyntaxKind.ForOfStatement:
|
||||
case SyntaxKind.ForInStatement:
|
||||
generateNames((<ForStatement | ForInOrOfStatement>node).initializer);
|
||||
generateNames((<ForStatement | ForInOrOfStatement>node).statement);
|
||||
break;
|
||||
case SyntaxKind.SwitchStatement:
|
||||
generateNames((<SwitchStatement>node).caseBlock);
|
||||
break;
|
||||
case SyntaxKind.CaseBlock:
|
||||
forEach((<CaseBlock>node).clauses, generateNames);
|
||||
break;
|
||||
case SyntaxKind.CaseClause:
|
||||
case SyntaxKind.DefaultClause:
|
||||
forEach((<CaseOrDefaultClause>node).statements, generateNames);
|
||||
break;
|
||||
case SyntaxKind.TryStatement:
|
||||
generateNames((<TryStatement>node).tryBlock);
|
||||
generateNames((<TryStatement>node).catchClause);
|
||||
generateNames((<TryStatement>node).finallyBlock);
|
||||
break;
|
||||
case SyntaxKind.CatchClause:
|
||||
generateNames((<CatchClause>node).variableDeclaration);
|
||||
generateNames((<CatchClause>node).block);
|
||||
break;
|
||||
case SyntaxKind.VariableStatement:
|
||||
generateNames((<VariableStatement>node).declarationList);
|
||||
break;
|
||||
case SyntaxKind.VariableDeclarationList:
|
||||
forEach((<VariableDeclarationList>node).declarations, generateNames);
|
||||
break;
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.Parameter:
|
||||
case SyntaxKind.BindingElement:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
generateNameIfNeeded((<NamedDeclaration>node).name);
|
||||
break;
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
generateNameIfNeeded((<FunctionDeclaration>node).name);
|
||||
if (getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) {
|
||||
forEach((<FunctionDeclaration>node).parameters, generateNames);
|
||||
generateNames((<FunctionDeclaration>node).body);
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
forEach((<BindingPattern>node).elements, generateNames);
|
||||
break;
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
generateNames((<ImportDeclaration>node).importClause);
|
||||
break;
|
||||
case SyntaxKind.ImportClause:
|
||||
generateNameIfNeeded((<ImportClause>node).name);
|
||||
generateNames((<ImportClause>node).namedBindings);
|
||||
break;
|
||||
case SyntaxKind.NamespaceImport:
|
||||
generateNameIfNeeded((<NamespaceImport>node).name);
|
||||
break;
|
||||
case SyntaxKind.NamedImports:
|
||||
forEach((<NamedImports>node).elements, generateNames);
|
||||
break;
|
||||
case SyntaxKind.ImportSpecifier:
|
||||
generateNameIfNeeded((<ImportSpecifier>node).propertyName || (<ImportSpecifier>node).name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function generateMemberNames(node: Node | undefined) {
|
||||
if (!node) return;
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
generateNameIfNeeded((<NamedDeclaration>node).name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function generateNameIfNeeded(name: DeclarationName | undefined) {
|
||||
if (name) {
|
||||
if (isGeneratedIdentifier(name)) {
|
||||
generateName(name);
|
||||
}
|
||||
else if (isBindingPattern(name)) {
|
||||
generateNames(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the text for a generated identifier.
|
||||
*/
|
||||
@@ -3229,17 +3348,7 @@ namespace ts {
|
||||
if ((name.autoGenerateFlags & GeneratedIdentifierFlags.KindMask) === GeneratedIdentifierFlags.Node) {
|
||||
// Node names generate unique names based on their original node
|
||||
// and are cached based on that node's id.
|
||||
if (name.autoGenerateFlags & GeneratedIdentifierFlags.SkipNameGenerationScope) {
|
||||
const savedTempFlags = tempFlags;
|
||||
popNameGenerationScope(/*node*/ undefined);
|
||||
const result = generateNameCached(getNodeForGeneratedName(name));
|
||||
pushNameGenerationScope(/*node*/ undefined);
|
||||
tempFlags = savedTempFlags;
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return generateNameCached(getNodeForGeneratedName(name));
|
||||
}
|
||||
return generateNameCached(getNodeForGeneratedName(name));
|
||||
}
|
||||
else {
|
||||
// Auto, Loop, and Unique names are cached based on their unique
|
||||
|
||||
@@ -188,16 +188,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
/** Create a unique name generated for a node. */
|
||||
export function getGeneratedNameForNode(node: Node): Identifier;
|
||||
/* @internal */ export function getGeneratedNameForNode(node: Node, shouldSkipNameGenerationScope?: boolean): Identifier; // tslint:disable-line unified-signatures
|
||||
export function getGeneratedNameForNode(node: Node, shouldSkipNameGenerationScope?: boolean): Identifier {
|
||||
export function getGeneratedNameForNode(node: Node): Identifier {
|
||||
const name = createIdentifier("");
|
||||
name.autoGenerateFlags = GeneratedIdentifierFlags.Node;
|
||||
name.autoGenerateId = nextAutoGenerateId;
|
||||
name.original = node;
|
||||
if (shouldSkipNameGenerationScope) {
|
||||
name.autoGenerateFlags |= GeneratedIdentifierFlags.SkipNameGenerationScope;
|
||||
}
|
||||
nextAutoGenerateId++;
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -1248,7 +1248,7 @@ namespace ts {
|
||||
function transformInitializedProperty(property: PropertyDeclaration, receiver: LeftHandSideExpression) {
|
||||
// We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name)
|
||||
const propertyName = isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression)
|
||||
? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name, !hasModifier(property, ModifierFlags.Static)))
|
||||
? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name))
|
||||
: property.name;
|
||||
const initializer = visitNode(property.initializer, visitor, isExpression);
|
||||
const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName);
|
||||
|
||||
@@ -710,10 +710,9 @@ namespace ts {
|
||||
KindMask = 7, // Mask to extract the kind of identifier from its flags.
|
||||
|
||||
// Flags
|
||||
SkipNameGenerationScope = 1 << 3, // Should skip a name generation scope when generating the name for this identifier
|
||||
ReservedInNestedScopes = 1 << 4, // Reserve the generated name in nested scopes
|
||||
Optimistic = 1 << 5, // First instance won't use '_#' if there's no conflict
|
||||
FileLevel = 1 << 6, // Use only the file identifiers list and not generated names to search for conflicts
|
||||
ReservedInNestedScopes = 1 << 3, // Reserve the generated name in nested scopes
|
||||
Optimistic = 1 << 4, // First instance won't use '_#' if there's no conflict
|
||||
FileLevel = 1 << 5, // Use only the file identifiers list and not generated names to search for conflicts
|
||||
}
|
||||
|
||||
export interface Identifier extends PrimaryExpression, Declaration {
|
||||
|
||||
Reference in New Issue
Block a user