Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get name of declaration uniformly, even for JS-style assignment declarations. #15594

Merged
merged 12 commits into from
May 10, 2017
21 changes: 11 additions & 10 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,12 +227,13 @@ 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 {
if (node.name) {
const name = getNameOfDeclaration(node);
if (name) {
if (isAmbientModule(node)) {
return isGlobalScopeAugmentation(<ModuleDeclaration>node) ? "__global" : `"${(<LiteralExpression>node.name).text}"`;
return isGlobalScopeAugmentation(<ModuleDeclaration>node) ? "__global" : `"${(<LiteralExpression>name).text}"`;
}
if (node.name.kind === SyntaxKind.ComputedPropertyName) {
const nameExpression = (<ComputedPropertyName>node.name).expression;
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;
Expand All @@ -241,7 +242,7 @@ namespace ts {
Debug.assert(isWellKnownSymbolSyntactically(nameExpression));
return getPropertyNameForKnownSymbolName((<PropertyAccessExpression>nameExpression).name.text);
}
return (<Identifier | LiteralExpression>node.name).text;
return (<Identifier | LiteralExpression>name).text;
}
switch (node.kind) {
case SyntaxKind.Constructor:
Expand Down Expand Up @@ -303,7 +304,7 @@ namespace ts {
}

function getDisplayName(node: Declaration): string {
return node.name ? declarationNameToString(node.name) : getDeclarationName(node);
return (node as RealDeclaration).name ? declarationNameToString((node as RealDeclaration).name) : getDeclarationName(node);
}

/**
Expand Down Expand Up @@ -366,8 +367,8 @@ namespace ts {
symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name));
}
else {
if (node.name) {
node.name.parent = node;
if ((node as RealDeclaration).name) {
(node as RealDeclaration).name.parent = node;
}

// Report errors every position with duplicate declaration
Expand Down Expand Up @@ -396,9 +397,9 @@ namespace ts {
}

forEach(symbol.declarations, declaration => {
file.bindDiagnostics.push(createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration)));
file.bindDiagnostics.push(createDiagnosticForNode(getNameOfDeclaration(declaration) || declaration, message, getDisplayName(declaration)));
});
file.bindDiagnostics.push(createDiagnosticForNode(node.name || node, message, getDisplayName(node)));
file.bindDiagnostics.push(createDiagnosticForNode(getNameOfDeclaration(node) || node, message, getDisplayName(node)));

symbol = createSymbol(SymbolFlags.None, name);
}
Expand Down
102 changes: 58 additions & 44 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/compiler/declarationEmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1134,7 +1134,7 @@ namespace ts {
return {
diagnosticMessage,
errorNode: node,
typeName: (<Declaration>node.parent.parent).name
typeName: getNameOfDeclaration(node.parent.parent)
};
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/compiler/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3064,9 +3064,10 @@ namespace ts {
}

function getName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags?: EmitFlags) {
if (node.name && isIdentifier(node.name) && !isGeneratedIdentifier(node.name)) {
const name = getMutableClone(node.name);
emitFlags |= getEmitFlags(node.name);
const nodeName = getNameOfDeclaration(node);
if (nodeName && isIdentifier(nodeName) && !isGeneratedIdentifier(nodeName)) {
const name = getMutableClone(nodeName);
emitFlags |= getEmitFlags(nodeName);
if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap;
if (!allowComments) emitFlags |= EmitFlags.NoComments;
if (emitFlags) setEmitFlags(name, emitFlags);
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/transformers/es2015.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3748,7 +3748,7 @@ namespace ts {
case SyntaxKind.ClassDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.VariableDeclaration:
return (<Declaration>parent).name === node
return (<RealDeclaration>parent).name === node
&& resolver.isDeclarationWithCollidingName(<Declaration>parent);
}

Expand Down Expand Up @@ -3781,7 +3781,7 @@ namespace ts {
if (enabledSubstitutions & ES2015SubstitutionFlags.BlockScopedBindings && !isInternalName(node)) {
const declaration = resolver.getReferencedDeclarationWithCollidingName(node);
if (declaration && !(isClassLike(declaration) && isPartOfClassBody(declaration, node))) {
return setTextRange(getGeneratedNameForNode(declaration.name), node);
return setTextRange(getGeneratedNameForNode(getNameOfDeclaration(declaration)), node);
}
}

Expand Down
58 changes: 30 additions & 28 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -603,12 +603,15 @@ namespace ts {

export type DeclarationName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | BindingPattern;

export interface Declaration extends Node {
export interface RealDeclaration extends Node {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we find a better name for this...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not certain I'm a big fan of renaming this at all.

_declarationBrand: any;
name?: DeclarationName;
}

export interface DeclarationStatement extends Declaration, Statement {
// Binary expressions can be declarations if they are 'exports.foo = bar' expressions in JS files
export type Declaration = RealDeclaration | BinaryExpression;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not name this DeclarationLike?


export interface DeclarationStatement extends RealDeclaration, Statement {
name?: Identifier | StringLiteral | NumericLiteral;
}

Expand All @@ -622,7 +625,7 @@ namespace ts {
expression: LeftHandSideExpression;
}

export interface TypeParameterDeclaration extends Declaration {
export interface TypeParameterDeclaration extends RealDeclaration {
kind: SyntaxKind.TypeParameter;
parent?: DeclarationWithTypeParameters;
name: Identifier;
Expand All @@ -633,7 +636,7 @@ namespace ts {
expression?: Expression;
}

export interface SignatureDeclaration extends Declaration {
export interface SignatureDeclaration extends RealDeclaration {
name?: PropertyName;
typeParameters?: NodeArray<TypeParameterDeclaration>;
parameters: NodeArray<ParameterDeclaration>;
Expand All @@ -650,7 +653,7 @@ namespace ts {

export type BindingName = Identifier | BindingPattern;

export interface VariableDeclaration extends Declaration {
export interface VariableDeclaration extends RealDeclaration {
kind: SyntaxKind.VariableDeclaration;
parent?: VariableDeclarationList | CatchClause;
name: BindingName; // Declared variable name
Expand All @@ -664,7 +667,7 @@ namespace ts {
declarations: NodeArray<VariableDeclaration>;
}

export interface ParameterDeclaration extends Declaration {
export interface ParameterDeclaration extends RealDeclaration {
kind: SyntaxKind.Parameter;
parent?: SignatureDeclaration;
dotDotDotToken?: DotDotDotToken; // Present on rest parameter
Expand All @@ -674,7 +677,7 @@ namespace ts {
initializer?: Expression; // Optional initializer
}

export interface BindingElement extends Declaration {
export interface BindingElement extends RealDeclaration {
kind: SyntaxKind.BindingElement;
parent?: BindingPattern;
propertyName?: PropertyName; // Binding property name (in object binding pattern)
Expand All @@ -699,7 +702,7 @@ namespace ts {
initializer?: Expression; // Optional initializer
}

export interface ObjectLiteralElement extends Declaration {
export interface ObjectLiteralElement extends RealDeclaration {
_objectLiteralBrandBrand: any;
name?: PropertyName;
}
Expand Down Expand Up @@ -743,7 +746,7 @@ namespace ts {
// SyntaxKind.ShorthandPropertyAssignment
// SyntaxKind.EnumMember
// SyntaxKind.JSDocPropertyTag
export interface VariableLikeDeclaration extends Declaration {
export interface VariableLikeDeclaration extends RealDeclaration {
propertyName?: PropertyName;
dotDotDotToken?: DotDotDotToken;
name: DeclarationName;
Expand All @@ -752,7 +755,7 @@ namespace ts {
initializer?: Expression;
}

export interface PropertyLikeDeclaration extends Declaration {
export interface PropertyLikeDeclaration extends RealDeclaration {
name: PropertyName;
}

Expand Down Expand Up @@ -901,7 +904,7 @@ namespace ts {
}

// A TypeLiteral is the declaration node for an anonymous symbol.
export interface TypeLiteralNode extends TypeNode, Declaration {
export interface TypeLiteralNode extends TypeNode, RealDeclaration {
kind: SyntaxKind.TypeLiteral;
members: NodeArray<TypeElement>;
}
Expand Down Expand Up @@ -945,7 +948,7 @@ namespace ts {
indexType: TypeNode;
}

export interface MappedTypeNode extends TypeNode, Declaration {
export interface MappedTypeNode extends TypeNode, RealDeclaration {
kind: SyntaxKind.MappedType;
parent?: TypeAliasDeclaration;
readonlyToken?: ReadonlyToken;
Expand Down Expand Up @@ -1216,8 +1219,7 @@ namespace ts {

export type BinaryOperatorToken = Token<BinaryOperator>;

// Binary expressions can be declarations if they are 'exports.foo = bar' expressions in JS files
export interface BinaryExpression extends Expression, Declaration {
export interface BinaryExpression extends Expression {
kind: SyntaxKind.BinaryExpression;
left: Expression;
operatorToken: BinaryOperatorToken;
Expand Down Expand Up @@ -1403,7 +1405,7 @@ namespace ts {
* JSXAttribute or JSXSpreadAttribute. ObjectLiteralExpression, on the other hand, can only have properties of type
* ObjectLiteralElement (e.g. PropertyAssignment, ShorthandPropertyAssignment etc.)
*/
export interface ObjectLiteralExpressionBase<T extends ObjectLiteralElement> extends PrimaryExpression, Declaration {
export interface ObjectLiteralExpressionBase<T extends ObjectLiteralElement> extends PrimaryExpression, RealDeclaration {
properties: NodeArray<T>;
}

Expand All @@ -1417,7 +1419,7 @@ namespace ts {
export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression | ParenthesizedExpression;
export type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression;

export interface PropertyAccessExpression extends MemberExpression, Declaration {
export interface PropertyAccessExpression extends MemberExpression, RealDeclaration {
kind: SyntaxKind.PropertyAccessExpression;
expression: LeftHandSideExpression;
name: Identifier;
Expand Down Expand Up @@ -1449,7 +1451,7 @@ namespace ts {
| SuperElementAccessExpression
;

export interface CallExpression extends LeftHandSideExpression, Declaration {
export interface CallExpression extends LeftHandSideExpression, RealDeclaration {
kind: SyntaxKind.CallExpression;
expression: LeftHandSideExpression;
typeArguments?: NodeArray<TypeNode>;
Expand All @@ -1468,7 +1470,7 @@ namespace ts {
typeArguments?: NodeArray<TypeNode>;
}

export interface NewExpression extends PrimaryExpression, Declaration {
export interface NewExpression extends PrimaryExpression, RealDeclaration {
kind: SyntaxKind.NewExpression;
expression: LeftHandSideExpression;
typeArguments?: NodeArray<TypeNode>;
Expand Down Expand Up @@ -1762,7 +1764,7 @@ namespace ts {

export type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration;

export interface ClassLikeDeclaration extends Declaration {
export interface ClassLikeDeclaration extends RealDeclaration {
name?: Identifier;
typeParameters?: NodeArray<TypeParameterDeclaration>;
heritageClauses?: NodeArray<HeritageClause>;
Expand All @@ -1778,12 +1780,12 @@ namespace ts {
kind: SyntaxKind.ClassExpression;
}

export interface ClassElement extends Declaration {
export interface ClassElement extends RealDeclaration {
_classElementBrand: any;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we feasibly remove the brand with this change?

name?: PropertyName;
}

export interface TypeElement extends Declaration {
export interface TypeElement extends RealDeclaration {
_typeElementBrand: any;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we feasibly remove the brand with this change?

name?: PropertyName;
questionToken?: QuestionToken;
Expand Down Expand Up @@ -1811,7 +1813,7 @@ namespace ts {
type: TypeNode;
}

export interface EnumMember extends Declaration {
export interface EnumMember extends RealDeclaration {
kind: SyntaxKind.EnumMember;
parent?: EnumDeclaration;
// This does include ComputedPropertyName, but the parser will give an error
Expand Down Expand Up @@ -1900,14 +1902,14 @@ namespace ts {
// import d, * as ns from "mod" => name = d, namedBinding: NamespaceImport = { name: ns }
// import { a, b as x } from "mod" => name = undefined, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]}
// import d, { a, b as x } from "mod" => name = d, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]}
export interface ImportClause extends Declaration {
export interface ImportClause extends RealDeclaration {
kind: SyntaxKind.ImportClause;
parent?: ImportDeclaration;
name?: Identifier; // Default binding
namedBindings?: NamedImportBindings;
}

export interface NamespaceImport extends Declaration {
export interface NamespaceImport extends RealDeclaration {
kind: SyntaxKind.NamespaceImport;
parent?: ImportClause;
name: Identifier;
Expand Down Expand Up @@ -1940,14 +1942,14 @@ namespace ts {

export type NamedImportsOrExports = NamedImports | NamedExports;

export interface ImportSpecifier extends Declaration {
export interface ImportSpecifier extends RealDeclaration {
kind: SyntaxKind.ImportSpecifier;
parent?: NamedImports;
propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent)
name: Identifier; // Declared name
}

export interface ExportSpecifier extends Declaration {
export interface ExportSpecifier extends RealDeclaration {
kind: SyntaxKind.ExportSpecifier;
parent?: NamedExports;
propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent)
Expand Down Expand Up @@ -2113,7 +2115,7 @@ namespace ts {
typeExpression: JSDocTypeExpression;
}

export interface JSDocTypedefTag extends JSDocTag, Declaration {
export interface JSDocTypedefTag extends JSDocTag, RealDeclaration {
kind: SyntaxKind.JSDocTypedefTag;
fullName?: JSDocNamespaceDeclaration | Identifier;
name?: Identifier;
Expand Down Expand Up @@ -2247,7 +2249,7 @@ namespace ts {


// Source files are declarations when they are external modules.
export interface SourceFile extends Declaration {
export interface SourceFile extends RealDeclaration {
kind: SyntaxKind.SourceFile;
statements: NodeArray<Statement>;
endOfFileToken: Token<SyntaxKind.EndOfFileToken>;
Expand Down
Loading