getNameOfDeclaration uniformly, including JS decls

JS-style assignment declarations have a name, but it's not stored on the
name property of the BinaryExpression. This commit adds
`getNameOfDeclaration` to uniformly get the name of a declaration.

It also reworks the declaration of `Declaration` so that accessing
`name` is an error unless the type does *not* include
BinaryExpression.
This commit is contained in:
Nathan Shively-Sanders 2017-05-04 16:12:54 -07:00
parent 96aca4c7d0
commit d35f6c3581
17 changed files with 184 additions and 127 deletions

View file

@ -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;
@ -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:
@ -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);
}
/**
@ -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
@ -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);
}

View file

@ -580,16 +580,16 @@ namespace ts {
recordMergedSymbol(target, source);
}
else if (target.flags & SymbolFlags.NamespaceModule) {
error(source.declarations[0].name, Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target));
error(getNameOfDeclaration(source.declarations[0]), Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target));
}
else {
const message = target.flags & SymbolFlags.BlockScopedVariable || source.flags & SymbolFlags.BlockScopedVariable
? Diagnostics.Cannot_redeclare_block_scoped_variable_0 : Diagnostics.Duplicate_identifier_0;
forEach(source.declarations, node => {
error(node.name ? node.name : node, message, symbolToString(source));
error(getNameOfDeclaration(node) || node, message, symbolToString(source));
});
forEach(target.declarations, node => {
error(node.name ? node.name : node, message, symbolToString(source));
error(getNameOfDeclaration(node) || node, message, symbolToString(source));
});
}
}
@ -1240,13 +1240,13 @@ namespace ts {
if (!isInAmbientContext(declaration) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) {
if (result.flags & SymbolFlags.BlockScopedVariable) {
error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationNameToString(declaration.name));
error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration)));
}
else if (result.flags & SymbolFlags.Class) {
error(errorLocation, Diagnostics.Class_0_used_before_its_declaration, declarationNameToString(declaration.name));
error(errorLocation, Diagnostics.Class_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration)));
}
else if (result.flags & SymbolFlags.Enum) {
error(errorLocation, Diagnostics.Enum_0_used_before_its_declaration, declarationNameToString(declaration.name));
error(errorLocation, Diagnostics.Enum_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration)));
}
}
}
@ -2809,8 +2809,9 @@ namespace ts {
function getNameOfSymbol(symbol: Symbol): string {
const declaration = firstOrUndefined(symbol.declarations);
if (declaration) {
if (declaration.name) {
return declarationNameToString(declaration.name);
const name = getNameOfDeclaration(declaration);
if (name) {
return declarationNameToString(name);
}
if (declaration.parent && declaration.parent.kind === SyntaxKind.VariableDeclaration) {
return declarationNameToString((<VariableDeclaration>declaration.parent).name);
@ -2897,8 +2898,9 @@ namespace ts {
function getNameOfSymbol(symbol: Symbol): string {
if (symbol.declarations && symbol.declarations.length) {
const declaration = symbol.declarations[0];
if (declaration.name) {
return declarationNameToString(declaration.name);
const name = getNameOfDeclaration(declaration);
if (name) {
return declarationNameToString(name);
}
if (declaration.parent && declaration.parent.kind === SyntaxKind.VariableDeclaration) {
return declarationNameToString((<VariableDeclaration>declaration.parent).name);
@ -6234,8 +6236,8 @@ namespace ts {
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return (<Declaration>node).name.kind === SyntaxKind.ComputedPropertyName
&& traverse((<Declaration>node).name);
return (<RealDeclaration>node).name.kind === SyntaxKind.ComputedPropertyName
&& traverse((<RealDeclaration>node).name);
default:
return !nodeStartsNewLexicalEnvironment(node) && !isPartOfTypeNode(node) && forEachChild(node, traverse);
@ -6315,8 +6317,9 @@ namespace ts {
type = anyType;
if (noImplicitAny) {
const declaration = <Declaration>signature.declaration;
if (declaration.name) {
error(declaration.name, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, declarationNameToString(declaration.name));
const name = getNameOfDeclaration(declaration);
if (name) {
error(name, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, declarationNameToString(name));
}
else {
error(declaration, Diagnostics.Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions);
@ -9931,7 +9934,7 @@ namespace ts {
default:
diagnostic = Diagnostics.Variable_0_implicitly_has_an_1_type;
}
error(declaration, diagnostic, declarationNameToString(declaration.name), typeAsString);
error(declaration, diagnostic, declarationNameToString(getNameOfDeclaration(declaration)), typeAsString);
}
function reportErrorsFromWidening(declaration: Declaration, type: Type) {
@ -11836,7 +11839,7 @@ namespace ts {
if (type === autoType || type === autoArrayType) {
if (flowType === autoType || flowType === autoArrayType) {
if (noImplicitAny) {
error(declaration.name, Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined, symbolToString(symbol), typeToString(flowType));
error(getNameOfDeclaration(declaration), Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined, symbolToString(symbol), typeToString(flowType));
error(node, Diagnostics.Variable_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType));
}
return convertAutoToAny(flowType);
@ -15399,7 +15402,7 @@ namespace ts {
// only the class declaration node will have the Abstract flag set.
const valueDecl = expressionType.symbol && getClassLikeDeclarationOfSymbol(expressionType.symbol);
if (valueDecl && getModifierFlags(valueDecl) & ModifierFlags.Abstract) {
error(node, Diagnostics.Cannot_create_an_instance_of_the_abstract_class_0, declarationNameToString(valueDecl.name));
error(node, Diagnostics.Cannot_create_an_instance_of_the_abstract_class_0, declarationNameToString(getNameOfDeclaration(valueDecl)));
return resolveErrorCall(node);
}
@ -15863,11 +15866,11 @@ namespace ts {
const links = getSymbolLinks(parameter);
if (!links.type) {
links.type = instantiateType(contextualType, mapper);
const name = getNameOfDeclaration(parameter.valueDeclaration);
// if inference didn't come up with anything but {}, fall back to the binding pattern if present.
if (links.type === emptyObjectType &&
(parameter.valueDeclaration.name.kind === SyntaxKind.ObjectBindingPattern ||
parameter.valueDeclaration.name.kind === SyntaxKind.ArrayBindingPattern)) {
links.type = getTypeFromBindingPattern(<BindingPattern>parameter.valueDeclaration.name);
(name.kind === SyntaxKind.ObjectBindingPattern || name.kind === SyntaxKind.ArrayBindingPattern)) {
links.type = getTypeFromBindingPattern(<BindingPattern>name);
}
assignBindingElementTypes(<ParameterDeclaration>parameter.valueDeclaration);
}
@ -17711,7 +17714,7 @@ namespace ts {
}
if (names.get(memberName)) {
error(member.symbol.valueDeclaration.name, Diagnostics.Duplicate_identifier_0, memberName);
error(getNameOfDeclaration(member.symbol.valueDeclaration), Diagnostics.Duplicate_identifier_0, memberName);
error(member.name, Diagnostics.Duplicate_identifier_0, memberName);
}
else {
@ -17812,7 +17815,8 @@ namespace ts {
}
function containsSuperCallAsComputedPropertyName(n: Declaration): boolean {
return n.name && containsSuperCall(n.name);
const name = getNameOfDeclaration(n);
return name && containsSuperCall(name);
}
function containsSuperCall(n: Node): boolean {
@ -18106,17 +18110,18 @@ namespace ts {
forEach(overloads, o => {
const deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags;
const name = getNameOfDeclaration(o);
if (deviation & ModifierFlags.Export) {
error(o.name, Diagnostics.Overload_signatures_must_all_be_exported_or_non_exported);
error(name, Diagnostics.Overload_signatures_must_all_be_exported_or_non_exported);
}
else if (deviation & ModifierFlags.Ambient) {
error(o.name, Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient);
error(name, Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient);
}
else if (deviation & (ModifierFlags.Private | ModifierFlags.Protected)) {
error(o.name || o, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected);
error(name || o, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected);
}
else if (deviation & ModifierFlags.Abstract) {
error(o.name, Diagnostics.Overload_signatures_must_all_be_abstract_or_non_abstract);
error(name, Diagnostics.Overload_signatures_must_all_be_abstract_or_non_abstract);
}
});
}
@ -18128,7 +18133,7 @@ namespace ts {
forEach(overloads, o => {
const deviation = hasQuestionToken(o) !== canonicalHasQuestionToken;
if (deviation) {
error(o.name, Diagnostics.Overload_signatures_must_all_be_optional_or_required);
error(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_optional_or_required);
}
});
}
@ -18264,7 +18269,7 @@ namespace ts {
if (duplicateFunctionDeclaration) {
forEach(declarations, declaration => {
error(declaration.name, Diagnostics.Duplicate_function_implementation);
error(getNameOfDeclaration(declaration), Diagnostics.Duplicate_function_implementation);
});
}
@ -18346,12 +18351,13 @@ namespace ts {
for (const d of symbol.declarations) {
const declarationSpaces = getDeclarationSpaces(d);
const name = getNameOfDeclaration(d);
// Only error on the declarations that contributed to the intersecting spaces.
if (declarationSpaces & commonDeclarationSpacesForDefaultAndNonDefault) {
error(d.name, Diagnostics.Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead, declarationNameToString(d.name));
error(name, Diagnostics.Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead, declarationNameToString(name));
}
else if (declarationSpaces & commonDeclarationSpacesForExportsAndLocals) {
error(d.name, Diagnostics.Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local, declarationNameToString(d.name));
error(name, Diagnostics.Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local, declarationNameToString(name));
}
}
}
@ -18990,15 +18996,16 @@ namespace ts {
if (!local.isReferenced) {
if (local.valueDeclaration && getRootDeclaration(local.valueDeclaration).kind === SyntaxKind.Parameter) {
const parameter = <ParameterDeclaration>getRootDeclaration(local.valueDeclaration);
const name = getNameOfDeclaration(local.valueDeclaration);
if (compilerOptions.noUnusedParameters &&
!isParameterPropertyDeclaration(parameter) &&
!parameterIsThisKeyword(parameter) &&
!parameterNameStartsWithUnderscore(local.valueDeclaration.name)) {
error(local.valueDeclaration.name, Diagnostics._0_is_declared_but_never_used, local.name);
!parameterNameStartsWithUnderscore(name)) {
error(name, Diagnostics._0_is_declared_but_never_used, local.name);
}
}
else if (compilerOptions.noUnusedLocals) {
forEach(local.declarations, d => errorUnusedLocal(d.name || d, local.name));
forEach(local.declarations, d => errorUnusedLocal(getNameOfDeclaration(d) || d, local.name));
}
}
});
@ -19082,7 +19089,7 @@ namespace ts {
if (!local.isReferenced && !local.exportSymbol) {
for (const declaration of local.declarations) {
if (!isAmbientModule(declaration)) {
errorUnusedLocal(declaration.name, local.name);
errorUnusedLocal(getNameOfDeclaration(declaration), local.name);
}
}
}
@ -19161,7 +19168,7 @@ namespace ts {
if (getNodeCheckFlags(current) & NodeCheckFlags.CaptureThis) {
const isDeclaration = node.kind !== SyntaxKind.Identifier;
if (isDeclaration) {
error((<Declaration>node).name, Diagnostics.Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference);
error(getNameOfDeclaration(<Declaration>node), Diagnostics.Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference);
}
else {
error(node, Diagnostics.Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference);
@ -19176,7 +19183,7 @@ namespace ts {
if (getNodeCheckFlags(current) & NodeCheckFlags.CaptureNewTarget) {
const isDeclaration = node.kind !== SyntaxKind.Identifier;
if (isDeclaration) {
error((<Declaration>node).name, Diagnostics.Duplicate_identifier_newTarget_Compiler_uses_variable_declaration_newTarget_to_capture_new_target_meta_property_reference);
error(getNameOfDeclaration(<Declaration>node), Diagnostics.Duplicate_identifier_newTarget_Compiler_uses_variable_declaration_newTarget_to_capture_new_target_meta_property_reference);
}
else {
error(node, Diagnostics.Expression_resolves_to_variable_declaration_newTarget_that_compiler_uses_to_capture_new_target_meta_property_reference);
@ -19475,7 +19482,7 @@ namespace ts {
checkTypeAssignableTo(checkExpressionCached(node.initializer), declarationType, node, /*headMessage*/ undefined);
}
if (!areDeclarationFlagsIdentical(node, symbol.valueDeclaration)) {
error(symbol.valueDeclaration.name, Diagnostics.All_declarations_of_0_must_have_identical_modifiers, declarationNameToString(node.name));
error(getNameOfDeclaration(symbol.valueDeclaration), Diagnostics.All_declarations_of_0_must_have_identical_modifiers, declarationNameToString(node.name));
error(node.name, Diagnostics.All_declarations_of_0_must_have_identical_modifiers, declarationNameToString(node.name));
}
}
@ -20306,16 +20313,23 @@ namespace ts {
const propDeclaration = prop.valueDeclaration;
// index is numeric and property name is not valid numeric literal
if (indexKind === IndexKind.Number && !(propDeclaration ? isNumericName(propDeclaration.name) : isNumericLiteralName(prop.name))) {
if (indexKind === IndexKind.Number && !(propDeclaration ? isNumericName(getNameOfDeclaration(propDeclaration)) : isNumericLiteralName(prop.name))) {
return;
}
let errorNode: Node;
if (propDeclaration && propDeclaration.kind === SyntaxKind.BinaryExpression) {
const specialAssignmentKind = getSpecialPropertyAssignmentKind(propDeclaration as BinaryExpression);
if (specialAssignmentKind === SpecialPropertyAssignmentKind.Property ||
specialAssignmentKind === SpecialPropertyAssignmentKind.PrototypeProperty ||
specialAssignmentKind === SpecialPropertyAssignmentKind.ThisProperty) {
errorNode = propDeclaration;
}
}
// perform property check if property or indexer is declared in 'type'
// this allows to rule out cases when both property and indexer are inherited from the base class
let errorNode: Node;
if (propDeclaration &&
(getSpecialPropertyAssignmentKind(propDeclaration as BinaryExpression) === SpecialPropertyAssignmentKind.ThisProperty ||
propDeclaration.name.kind === SyntaxKind.ComputedPropertyName ||
(getNameOfDeclaration(propDeclaration).kind === SyntaxKind.ComputedPropertyName ||
prop.parent === containingType.symbol)) {
errorNode = propDeclaration;
}
@ -20679,7 +20693,7 @@ namespace ts {
errorMessage = Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function;
}
error(derived.valueDeclaration.name || derived.valueDeclaration, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type));
error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type));
}
}
}
@ -21010,7 +21024,7 @@ namespace ts {
// check that const is placed\omitted on all enum declarations
forEach(enumSymbol.declarations, decl => {
if (isConstEnumDeclaration(decl) !== enumIsConst) {
error(decl.name, Diagnostics.Enum_declarations_must_all_be_const_or_non_const);
error(getNameOfDeclaration(decl), Diagnostics.Enum_declarations_must_all_be_const_or_non_const);
}
});
}
@ -21903,7 +21917,7 @@ namespace ts {
function isTypeDeclarationName(name: Node): boolean {
return name.kind === SyntaxKind.Identifier &&
isTypeDeclaration(name.parent) &&
(<Declaration>name.parent).name === name;
(<RealDeclaration>name.parent).name === name;
}
function isTypeDeclaration(node: Node): boolean {

View file

@ -1134,7 +1134,7 @@ namespace ts {
return {
diagnosticMessage,
errorNode: node,
typeName: (<Declaration>node.parent.parent).name
typeName: getNameOfDeclaration(node.parent.parent)
};
}
}

View file

@ -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);

View file

@ -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);
}
@ -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);
}
}

View file

@ -603,12 +603,15 @@ namespace ts {
export type DeclarationName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | BindingPattern;
export interface Declaration extends Node {
export interface RealDeclaration extends Node {
_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;
export interface DeclarationStatement extends RealDeclaration, Statement {
name?: Identifier | StringLiteral | NumericLiteral;
}
@ -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;
@ -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>;
@ -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
@ -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
@ -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)
@ -699,7 +702,7 @@ namespace ts {
initializer?: Expression; // Optional initializer
}
export interface ObjectLiteralElement extends Declaration {
export interface ObjectLiteralElement extends RealDeclaration {
_objectLiteralBrandBrand: any;
name?: PropertyName;
}
@ -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;
@ -752,7 +755,7 @@ namespace ts {
initializer?: Expression;
}
export interface PropertyLikeDeclaration extends Declaration {
export interface PropertyLikeDeclaration extends RealDeclaration {
name: PropertyName;
}
@ -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>;
}
@ -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;
@ -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;
@ -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>;
}
@ -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;
@ -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>;
@ -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>;
@ -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>;
@ -1778,12 +1780,12 @@ namespace ts {
kind: SyntaxKind.ClassExpression;
}
export interface ClassElement extends Declaration {
export interface ClassElement extends RealDeclaration {
_classElementBrand: any;
name?: PropertyName;
}
export interface TypeElement extends Declaration {
export interface TypeElement extends RealDeclaration {
_typeElementBrand: any;
name?: PropertyName;
questionToken?: QuestionToken;
@ -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
@ -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;
@ -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)
@ -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;
@ -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>;

View file

@ -11,6 +11,36 @@ namespace ts {
isTypeReferenceDirective?: boolean;
}
export function getNameOfDeclaration(declaration: Declaration): DeclarationName {
if (!declaration) {
return undefined;
}
if (declaration.kind === SyntaxKind.BinaryExpression) {
const kind = getSpecialPropertyAssignmentKind(declaration as BinaryExpression);
const lhs = (declaration as BinaryExpression).left;
switch (kind) {
case SpecialPropertyAssignmentKind.None:
case SpecialPropertyAssignmentKind.ModuleExports:
return undefined;
case SpecialPropertyAssignmentKind.ExportsProperty:
if (lhs.kind === SyntaxKind.Identifier) {
return (lhs as PropertyAccessExpression).name;
}
else {
return ((lhs as PropertyAccessExpression).expression as PropertyAccessExpression).name;
}
case SpecialPropertyAssignmentKind.ThisProperty:
case SpecialPropertyAssignmentKind.Property:
return (lhs as PropertyAccessExpression).name;
case SpecialPropertyAssignmentKind.PrototypeProperty:
return ((lhs as PropertyAccessExpression).expression as PropertyAccessExpression).name;
}
}
else {
return declaration.name;
}
}
export function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration {
const declarations = symbol.declarations;
if (declarations) {
@ -566,7 +596,7 @@ namespace ts {
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.TypeAliasDeclaration:
errorNode = (<Declaration>node).name;
errorNode = (<RealDeclaration>node).name;
break;
case SyntaxKind.ArrowFunction:
return getErrorSpanForArrowFunction(sourceFile, <ArrowFunction>node);
@ -1770,7 +1800,7 @@ namespace ts {
}
if (isDeclaration(parent)) {
return (<Declaration>parent).name === name;
return parent.name === name;
}
return false;
@ -1796,7 +1826,7 @@ namespace ts {
case SyntaxKind.PropertyAssignment:
case SyntaxKind.PropertyAccessExpression:
// Name in member declaration or property name in property access
return (<Declaration | PropertyAccessExpression>parent).name === node;
return (<RealDeclaration | PropertyAccessExpression>parent).name === node;
case SyntaxKind.QualifiedName:
// Name on right hand side of dot in a type query
if ((<QualifiedName>parent).right === node) {
@ -1994,7 +2024,7 @@ namespace ts {
* Symbol.
*/
export function hasDynamicName(declaration: Declaration): boolean {
return declaration.name && isDynamicName(declaration.name);
return getNameOfDeclaration(declaration) && isDynamicName(getNameOfDeclaration(declaration));
}
export function isDynamicName(name: DeclarationName): boolean {
@ -4071,7 +4101,7 @@ namespace ts {
|| kind === SyntaxKind.MergeDeclarationMarker;
}
export function isDeclaration(node: Node): node is Declaration {
export function isDeclaration(node: Node): node is RealDeclaration {
return isDeclarationKind(node.kind);
}

View file

@ -655,7 +655,7 @@ namespace FourSlash {
ts.zipWith(endMarkers, definitions, (endMarker, definition, i) => {
const marker = this.getMarkerByName(endMarker);
if (marker.fileName !== definition.fileName || marker.position !== definition.textSpan.start) {
this.raiseError(`goToDefinition failed for definition ${i}: expected ${marker.fileName} at ${marker.position}, got ${definition.fileName} at ${definition.textSpan.start}`);
this.raiseError(`goToDefinition failed for definition ${endMarker} (${i}): expected ${marker.fileName} at ${marker.position}, got ${definition.fileName} at ${definition.textSpan.start}`);
}
});
}

View file

@ -63,7 +63,7 @@ namespace ts.codefix {
const declaration = declarations[0] as Declaration;
// Clone name to remove leading trivia.
const name = getSynthesizedClone(<PropertyName>declaration.name);
const name = getSynthesizedClone(getNameOfDeclaration(declaration)) as PropertyName;
const visibilityModifier = createVisibilityModifier(getModifierFlags(declaration));
const modifiers = visibilityModifier ? createNodeArray([visibilityModifier]) : undefined;
const type = checker.getWidenedType(checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration));
@ -231,4 +231,4 @@ namespace ts.codefix {
}
return undefined;
}
}
}

View file

@ -908,7 +908,7 @@ namespace ts.FindAllReferences.Core {
* position of property accessing, the referenceEntry of such position will be handled in the first case.
*/
if (!(flags & SymbolFlags.Transient) && search.includes(shorthandValueSymbol)) {
addReference(valueDeclaration.name, shorthandValueSymbol, search.location, state);
addReference(getNameOfDeclaration(valueDeclaration), shorthandValueSymbol, search.location, state);
}
}

View file

@ -487,7 +487,7 @@ namespace ts.formatting {
// falls through
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.Parameter:
return (<Declaration>node).name.kind;
return getNameOfDeclaration(<Declaration>node).kind;
}
}

View file

@ -235,7 +235,7 @@ namespace ts.GoToDefinition {
/** Creates a DefinitionInfo from a Declaration, using the declaration's name if possible. */
function createDefinitionInfo(node: Declaration, symbolKind: string, symbolName: string, containerName: string): DefinitionInfo {
return createDefinitionInfoFromName(node.name || node, symbolKind, symbolName, containerName);
return createDefinitionInfoFromName(getNameOfDeclaration(node) || node, symbolKind, symbolName, containerName);
}
/** Creates a DefinitionInfo directly from the name of a declaration. */

View file

@ -537,7 +537,10 @@ namespace ts.FindAllReferences {
return symbol.name;
}
const name = forEach(symbol.declarations, ({ name }) => name && name.kind === SyntaxKind.Identifier && name.text);
const name = forEach(symbol.declarations, decl => {
const name = getNameOfDeclaration(decl);
return name && name.kind === SyntaxKind.Identifier && name.text;
});
Debug.assert(!!name);
return name;
}

View file

@ -97,17 +97,20 @@ namespace ts.NavigateTo {
}
function tryAddSingleDeclarationName(declaration: Declaration, containers: string[]) {
if (declaration && declaration.name) {
const text = getTextOfIdentifierOrLiteral(declaration.name);
if (text !== undefined) {
containers.unshift(text);
}
else if (declaration.name.kind === SyntaxKind.ComputedPropertyName) {
return tryAddComputedPropertyName((<ComputedPropertyName>declaration.name).expression, containers, /*includeLastPortion*/ true);
}
else {
// Don't know how to add this.
return false;
if (declaration) {
const name = getNameOfDeclaration(declaration);
if (name) {
const text = getTextOfIdentifierOrLiteral(name);
if (text !== undefined) {
containers.unshift(text);
}
else if (name.kind === SyntaxKind.ComputedPropertyName) {
return tryAddComputedPropertyName((<ComputedPropertyName>name).expression, containers, /*includeLastPortion*/ true);
}
else {
// Don't know how to add this.
return false;
}
}
}
@ -143,8 +146,9 @@ namespace ts.NavigateTo {
// First, if we started with a computed property name, then add all but the last
// portion into the container array.
if (declaration.name.kind === SyntaxKind.ComputedPropertyName) {
if (!tryAddComputedPropertyName((<ComputedPropertyName>declaration.name).expression, containers, /*includeLastPortion*/ false)) {
const name = getNameOfDeclaration(declaration);
if (name.kind === SyntaxKind.ComputedPropertyName) {
if (!tryAddComputedPropertyName((<ComputedPropertyName>name).expression, containers, /*includeLastPortion*/ false)) {
return undefined;
}
}
@ -190,6 +194,7 @@ namespace ts.NavigateTo {
function createNavigateToItem(rawItem: RawNavigateToItem): NavigateToItem {
const declaration = rawItem.declaration;
const container = <Declaration>getContainerNode(declaration);
const containerName = container && getNameOfDeclaration(container);
return {
name: rawItem.name,
kind: getNodeKind(declaration),
@ -199,9 +204,9 @@ namespace ts.NavigateTo {
fileName: rawItem.fileName,
textSpan: createTextSpanFromNode(declaration),
// TODO(jfreeman): What should be the containerName when the container has a computed name?
containerName: container && container.name ? (<Identifier>container.name).text : "",
containerKind: container && container.name ? getNodeKind(container) : ""
containerName: containerName ? (<Identifier>containerName).text : "",
containerKind: containerName ? getNodeKind(container) : ""
};
}
}
}
}

View file

@ -279,8 +279,8 @@ namespace ts.NavigationBar {
function mergeChildren(children: NavigationBarNode[]): void {
const nameToItems = createMap<NavigationBarNode | NavigationBarNode[]>();
filterMutate(children, child => {
const decl = <Declaration>child.node;
const name = decl.name && nodeText(decl.name);
const declName = getNameOfDeclaration(<Declaration>child.node);
const name = declName && nodeText(declName);
if (!name) {
// Anonymous items are never merged.
return true;
@ -378,9 +378,9 @@ namespace ts.NavigationBar {
return getModuleName(<ModuleDeclaration>node);
}
const decl = <Declaration>node;
if (decl.name) {
return getPropertyNameForPropertyNameNode(decl.name);
const declName = getNameOfDeclaration(<Declaration>node);
if (declName) {
return getPropertyNameForPropertyNameNode(declName);
}
switch (node.kind) {
case SyntaxKind.FunctionExpression:
@ -399,7 +399,7 @@ namespace ts.NavigationBar {
return getModuleName(<ModuleDeclaration>node);
}
const name = (<Declaration>node).name;
const name = getNameOfDeclaration(<Declaration>node);
if (name) {
const text = nodeText(name);
if (text.length > 0) {

View file

@ -578,14 +578,15 @@ namespace ts {
}
function getDeclarationName(declaration: Declaration) {
if (declaration.name) {
const result = getTextOfIdentifierOrLiteral(declaration.name);
const name = getNameOfDeclaration(declaration);
if (name) {
const result = getTextOfIdentifierOrLiteral(name);
if (result !== undefined) {
return result;
}
if (declaration.name.kind === SyntaxKind.ComputedPropertyName) {
const expr = (<ComputedPropertyName>declaration.name).expression;
if (name.kind === SyntaxKind.ComputedPropertyName) {
const expr = (<ComputedPropertyName>name).expression;
if (expr.kind === SyntaxKind.PropertyAccessExpression) {
return (<PropertyAccessExpression>expr).name.text;
}

View file

@ -238,7 +238,7 @@ namespace ts {
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.ModuleDeclaration:
return (<Declaration>node.parent).name === node;
return getNameOfDeclaration(<Declaration>node.parent) === node;
case SyntaxKind.ElementAccessExpression:
return (<ElementAccessExpression>node.parent).argumentExpression === node;
case SyntaxKind.ComputedPropertyName: