From d35f6c3581943d5b473efa47f36c67707951cad6 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 4 May 2017 16:12:54 -0700 Subject: [PATCH 01/11] 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. --- src/compiler/binder.ts | 21 +++--- src/compiler/checker.ts | 102 +++++++++++++++----------- src/compiler/declarationEmitter.ts | 2 +- src/compiler/factory.ts | 7 +- src/compiler/transformers/es2015.ts | 4 +- src/compiler/types.ts | 58 ++++++++------- src/compiler/utilities.ts | 40 ++++++++-- src/harness/fourslash.ts | 2 +- src/services/codefixes/helpers.ts | 4 +- src/services/findAllReferences.ts | 2 +- src/services/formatting/formatting.ts | 2 +- src/services/goToDefinition.ts | 2 +- src/services/importTracker.ts | 5 +- src/services/navigateTo.ts | 37 ++++++---- src/services/navigationBar.ts | 12 +-- src/services/services.ts | 9 ++- src/services/utilities.ts | 2 +- 17 files changed, 184 insertions(+), 127 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 562a650a7f075..38cb93bff7e57 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -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(node) ? "__global" : `"${(node.name).text}"`; + return isGlobalScopeAugmentation(node) ? "__global" : `"${(name).text}"`; } - if (node.name.kind === SyntaxKind.ComputedPropertyName) { - const nameExpression = (node.name).expression; + if (name.kind === SyntaxKind.ComputedPropertyName) { + const nameExpression = (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((nameExpression).name.text); } - return (node.name).text; + return (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); } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 603f45cbf07a3..8979510461ea5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -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((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((declaration.parent).name); @@ -6234,8 +6236,8 @@ namespace ts { case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - return (node).name.kind === SyntaxKind.ComputedPropertyName - && traverse((node).name); + return (node).name.kind === SyntaxKind.ComputedPropertyName + && traverse((node).name); default: return !nodeStartsNewLexicalEnvironment(node) && !isPartOfTypeNode(node) && forEachChild(node, traverse); @@ -6315,8 +6317,9 @@ namespace ts { type = anyType; if (noImplicitAny) { const 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(parameter.valueDeclaration.name); + (name.kind === SyntaxKind.ObjectBindingPattern || name.kind === SyntaxKind.ArrayBindingPattern)) { + links.type = getTypeFromBindingPattern(name); } assignBindingElementTypes(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 = 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((node).name, Diagnostics.Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference); + error(getNameOfDeclaration(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((node).name, Diagnostics.Duplicate_identifier_newTarget_Compiler_uses_variable_declaration_newTarget_to_capture_new_target_meta_property_reference); + error(getNameOfDeclaration(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) && - (name.parent).name === name; + (name.parent).name === name; } function isTypeDeclaration(node: Node): boolean { diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 2bd8d5971fb2f..0a7f9a2a3ec8c 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -1134,7 +1134,7 @@ namespace ts { return { diagnosticMessage, errorNode: node, - typeName: (node.parent.parent).name + typeName: getNameOfDeclaration(node.parent.parent) }; } } diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index cce95c23c2258..1a8b91c8ff27b 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -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); diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 734fbcaeb1643..188da04b36cbb 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -3748,7 +3748,7 @@ namespace ts { case SyntaxKind.ClassDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.VariableDeclaration: - return (parent).name === node + return (parent).name === node && resolver.isDeclarationWithCollidingName(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); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 7e45dabaf95ec..51e9d6717ee28 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -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; parameters: NodeArray; @@ -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; } - 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; } @@ -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; - // 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 extends PrimaryExpression, Declaration { + export interface ObjectLiteralExpressionBase extends PrimaryExpression, RealDeclaration { properties: NodeArray; } @@ -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; @@ -1468,7 +1470,7 @@ namespace ts { typeArguments?: NodeArray; } - export interface NewExpression extends PrimaryExpression, Declaration { + export interface NewExpression extends PrimaryExpression, RealDeclaration { kind: SyntaxKind.NewExpression; expression: LeftHandSideExpression; typeArguments?: NodeArray; @@ -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; heritageClauses?: NodeArray; @@ -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; endOfFileToken: Token; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f1b181a03b03a..5b1cbb849bc76 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -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 = (node).name; + errorNode = (node).name; break; case SyntaxKind.ArrowFunction: return getErrorSpanForArrowFunction(sourceFile, node); @@ -1770,7 +1800,7 @@ namespace ts { } if (isDeclaration(parent)) { - return (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 (parent).name === node; + return (parent).name === node; case SyntaxKind.QualifiedName: // Name on right hand side of dot in a type query if ((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); } diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index a56d21ae3454a..83d27c951beac 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -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}`); } }); } diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 0de04d7a9b959..6585e99454378 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -63,7 +63,7 @@ namespace ts.codefix { const declaration = declarations[0] as Declaration; // Clone name to remove leading trivia. - const name = getSynthesizedClone(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; } -} \ No newline at end of file +} diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index fd717fc546ea0..9ca90cfd5effb 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -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); } } diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index 5c2171cc4ae75..d5bd33e33cc05 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -487,7 +487,7 @@ namespace ts.formatting { // falls through case SyntaxKind.PropertyDeclaration: case SyntaxKind.Parameter: - return (node).name.kind; + return getNameOfDeclaration(node).kind; } } diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index f2602903be38c..09d1f2a248cfe 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -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. */ diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index c94d5cc314385..6e9a12a4c4d81 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -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; } diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index 2c8d43b535be7..c29b29143c57f 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -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((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((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((declaration.name).expression, containers, /*includeLastPortion*/ false)) { + const name = getNameOfDeclaration(declaration); + if (name.kind === SyntaxKind.ComputedPropertyName) { + if (!tryAddComputedPropertyName((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 = 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 ? (container.name).text : "", - containerKind: container && container.name ? getNodeKind(container) : "" + containerName: containerName ? (containerName).text : "", + containerKind: containerName ? getNodeKind(container) : "" }; } } -} \ No newline at end of file +} diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 7a2508fcfd66c..819202ff6f4ec 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -279,8 +279,8 @@ namespace ts.NavigationBar { function mergeChildren(children: NavigationBarNode[]): void { const nameToItems = createMap(); filterMutate(children, child => { - const decl = child.node; - const name = decl.name && nodeText(decl.name); + const declName = getNameOfDeclaration(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(node); } - const decl = node; - if (decl.name) { - return getPropertyNameForPropertyNameNode(decl.name); + const declName = getNameOfDeclaration(node); + if (declName) { + return getPropertyNameForPropertyNameNode(declName); } switch (node.kind) { case SyntaxKind.FunctionExpression: @@ -399,7 +399,7 @@ namespace ts.NavigationBar { return getModuleName(node); } - const name = (node).name; + const name = getNameOfDeclaration(node); if (name) { const text = nodeText(name); if (text.length > 0) { diff --git a/src/services/services.ts b/src/services/services.ts index fa15568f86e29..1b4678b5dbc7a 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -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 = (declaration.name).expression; + if (name.kind === SyntaxKind.ComputedPropertyName) { + const expr = (name).expression; if (expr.kind === SyntaxKind.PropertyAccessExpression) { return (expr).name.text; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index e884b342feff1..065c42245f601 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -238,7 +238,7 @@ namespace ts { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: case SyntaxKind.ModuleDeclaration: - return (node.parent).name === node; + return getNameOfDeclaration(node.parent) === node; case SyntaxKind.ElementAccessExpression: return (node.parent).argumentExpression === node; case SyntaxKind.ComputedPropertyName: From aceadeb04b06356dd7d3b4fc2f94d08e29e745e0 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 4 May 2017 16:13:32 -0700 Subject: [PATCH 02/11] Update baselines --- .../reference/checkJsFiles_noErrorLocation.errors.txt | 4 ++-- tests/cases/fourslash/javaScriptClass3.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/baselines/reference/checkJsFiles_noErrorLocation.errors.txt b/tests/baselines/reference/checkJsFiles_noErrorLocation.errors.txt index 758b295a49d70..d9104608284a9 100644 --- a/tests/baselines/reference/checkJsFiles_noErrorLocation.errors.txt +++ b/tests/baselines/reference/checkJsFiles_noErrorLocation.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/a.js(14,5): error TS2424: Class 'A' defines instance member function 'foo', but extended class 'B' defines it as instance member property. +tests/cases/compiler/a.js(14,10): error TS2424: Class 'A' defines instance member function 'foo', but extended class 'B' defines it as instance member property. ==== tests/cases/compiler/a.js (1 errors) ==== @@ -16,7 +16,7 @@ tests/cases/compiler/a.js(14,5): error TS2424: Class 'A' defines instance member constructor() { super(); this.foo = () => 3; - ~~~~~~~~~~~~~~~~~~ + ~~~ !!! error TS2424: Class 'A' defines instance member function 'foo', but extended class 'B' defines it as instance member property. } } diff --git a/tests/cases/fourslash/javaScriptClass3.ts b/tests/cases/fourslash/javaScriptClass3.ts index 41ce79b35eb35..fd67f6f53a536 100644 --- a/tests/cases/fourslash/javaScriptClass3.ts +++ b/tests/cases/fourslash/javaScriptClass3.ts @@ -1,13 +1,13 @@ /// -// In an inferred class, we can to-to-def successfully +// In an inferred class, we can go-to-def successfully // @allowNonTsExtensions: true // @Filename: Foo.js //// class Foo { //// constructor() { -//// /*dst1*/this.alpha = 10; -//// /*dst2*/this.beta = 'gamma'; +//// this./*dst1*/alpha = 10; +//// this./*dst2*/beta = 'gamma'; //// } //// method() { return this.alpha; } //// } From 573040f0cfa713929bfa1fe84f4fd2a81cc82658 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 5 May 2017 13:47:28 -0700 Subject: [PATCH 03/11] Convert `Declaration` to union, not type hierarchy --- src/compiler/binder.ts | 6 +- src/compiler/checker.ts | 20 +-- src/compiler/transformers/es2015.ts | 2 +- src/compiler/types.ts | 184 +++++++++++++++++++++------- src/compiler/utilities.ts | 67 +++++----- 5 files changed, 191 insertions(+), 88 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 38cb93bff7e57..8506378e216c9 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -304,7 +304,7 @@ namespace ts { } function getDisplayName(node: Declaration): string { - return (node as RealDeclaration).name ? declarationNameToString((node as RealDeclaration).name) : getDeclarationName(node); + return (node as DeclarationBase).name ? declarationNameToString((node as DeclarationBase).name) : getDeclarationName(node); } /** @@ -367,8 +367,8 @@ namespace ts { symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name)); } else { - if ((node as RealDeclaration).name) { - (node as RealDeclaration).name.parent = node; + if ((node as DeclarationBase).name) { + (node as DeclarationBase).name.parent = node; } // Report errors every position with duplicate declaration diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8979510461ea5..05af363fb8e7d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3621,7 +3621,7 @@ namespace ts { }); } - function isDeclarationVisible(node: Declaration): boolean { + function isDeclarationVisible(node: Node): boolean { if (node) { const links = getNodeLinks(node); if (links.isVisible === undefined) { @@ -3635,10 +3635,10 @@ namespace ts { function determineIfDeclarationIsVisible() { switch (node.kind) { case SyntaxKind.BindingElement: - return isDeclarationVisible(node.parent.parent); + return isDeclarationVisible(node.parent.parent); case SyntaxKind.VariableDeclaration: - if (isBindingPattern(node.name) && - !(node.name).elements.length) { + const declaration = node as VariableDeclaration; + if (isBindingPattern(declaration.name) && !declaration.name.elements.length) { // If the binding pattern is empty, this variable declaration is not visible return false; } @@ -3661,7 +3661,7 @@ namespace ts { return isGlobalSourceFile(parent); } // Exported members/ambient module elements (exception import declaration) are visible if parent is visible - return isDeclarationVisible(parent); + return isDeclarationVisible(parent); case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: @@ -3691,7 +3691,7 @@ namespace ts { case SyntaxKind.UnionType: case SyntaxKind.IntersectionType: case SyntaxKind.ParenthesizedType: - return isDeclarationVisible(node.parent); + return isDeclarationVisible(node.parent); // Default binding, import specifier and namespace import is visible // only on demand so by default it is not visible @@ -6236,8 +6236,8 @@ namespace ts { case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - return (node).name.kind === SyntaxKind.ComputedPropertyName - && traverse((node).name); + return (node).name.kind === SyntaxKind.ComputedPropertyName + && traverse((node).name); default: return !nodeStartsNewLexicalEnvironment(node) && !isPartOfTypeNode(node) && forEachChild(node, traverse); @@ -21917,7 +21917,7 @@ namespace ts { function isTypeDeclarationName(name: Node): boolean { return name.kind === SyntaxKind.Identifier && isTypeDeclaration(name.parent) && - (name.parent).name === name; + (name.parent).name === name; } function isTypeDeclaration(node: Node): boolean { @@ -22545,7 +22545,7 @@ namespace ts { // Return true if the given node is a declaration of a nested block scoped entity with a name that either hides an // existing name or might hide a name when compiled downlevel - function isDeclarationWithCollidingName(node: Declaration): boolean { + function isDeclarationWithCollidingName(node: Node): boolean { node = getParseTreeNode(node, isDeclaration); if (node) { const symbol = getSymbolOfNode(node); diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 188da04b36cbb..4165b0679e1ef 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -3748,7 +3748,7 @@ namespace ts { case SyntaxKind.ClassDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.VariableDeclaration: - return (parent).name === node + return (parent).name === node && resolver.isDeclarationWithCollidingName(parent); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 51e9d6717ee28..de71fbfdabee7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -603,15 +603,75 @@ namespace ts { export type DeclarationName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | BindingPattern; - export interface RealDeclaration extends Node { + export interface DeclarationBase extends Node { _declarationBrand: any; name?: DeclarationName; } - // 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 { + export type Declaration = + | ArrowFunction + // Binary expressions can be declarations if they are 'exports.foo = bar' expressions in JS files + | BinaryExpression + | BindingElement + | CallExpression + | CallSignatureDeclaration + | ClassDeclaration + | ClassElement + | ClassExpression + | ClassLikeDeclaration + | ConstructSignatureDeclaration + | ConstructorDeclaration + | ConstructorTypeNode + | EnumDeclaration + | EnumMember + | ExportAssignment + | ExportDeclaration + | ExportSpecifier + | FunctionDeclaration + | FunctionExpression + | FunctionTypeNode + | GetAccessorDeclaration + | ImportClause + | ImportEqualsDeclaration + | ImportSpecifier + | IndexSignatureDeclaration + | InterfaceDeclaration + | JSDocFunctionType + | JSDocNamespaceDeclaration + | JSDocPropertyTag + | JSDocTypedefTag + | JsxAttribute + | JsxAttributes + | JsxSpreadAttribute + | MappedTypeNode + | MethodDeclaration + | MethodSignature + | MissingDeclaration + | ModuleDeclaration + | NamespaceDeclaration + | NamespaceExportDeclaration + | NamespaceImport + | NewExpression + | ObjectLiteralExpression + | ParameterDeclaration + | PropertyAccessExpression + | PropertyAssignment + | PropertyDeclaration + | PropertySignature + | SemicolonClassElement + | SetAccessorDeclaration + | ShorthandPropertyAssignment + | SignatureDeclaration + | SourceFile + | SpreadAssignment + | TypeAliasDeclaration + | TypeElement + | TypeLiteralNode + | TypeParameterDeclaration + | VariableDeclaration + | VariableLikeDeclaration; + + export interface DeclarationStatement extends DeclarationBase, Statement { name?: Identifier | StringLiteral | NumericLiteral; } @@ -625,7 +685,7 @@ namespace ts { expression: LeftHandSideExpression; } - export interface TypeParameterDeclaration extends RealDeclaration { + export interface TypeParameterDeclaration extends DeclarationBase { kind: SyntaxKind.TypeParameter; parent?: DeclarationWithTypeParameters; name: Identifier; @@ -636,7 +696,23 @@ namespace ts { expression?: Expression; } - export interface SignatureDeclaration extends RealDeclaration { + export interface SignatureDeclaration extends DeclarationBase { + kind: + | SyntaxKind.CallSignature + | SyntaxKind.ConstructSignature + | SyntaxKind.ConstructorType + | SyntaxKind.MethodSignature + | SyntaxKind.IndexSignature + | SyntaxKind.FunctionType + | SyntaxKind.JSDocFunctionType + | SyntaxKind.FunctionDeclaration + | SyntaxKind.MethodDeclaration + | SyntaxKind.GetAccessor + | SyntaxKind.SetAccessor + | SyntaxKind.Constructor + | SyntaxKind.ArrowFunction + | SyntaxKind.FunctionExpression + name?: PropertyName; typeParameters?: NodeArray; parameters: NodeArray; @@ -653,7 +729,7 @@ namespace ts { export type BindingName = Identifier | BindingPattern; - export interface VariableDeclaration extends RealDeclaration { + export interface VariableDeclaration extends DeclarationBase { kind: SyntaxKind.VariableDeclaration; parent?: VariableDeclarationList | CatchClause; name: BindingName; // Declared variable name @@ -667,7 +743,7 @@ namespace ts { declarations: NodeArray; } - export interface ParameterDeclaration extends RealDeclaration { + export interface ParameterDeclaration extends DeclarationBase { kind: SyntaxKind.Parameter; parent?: SignatureDeclaration; dotDotDotToken?: DotDotDotToken; // Present on rest parameter @@ -677,7 +753,7 @@ namespace ts { initializer?: Expression; // Optional initializer } - export interface BindingElement extends RealDeclaration { + export interface BindingElement extends DeclarationBase { kind: SyntaxKind.BindingElement; parent?: BindingPattern; propertyName?: PropertyName; // Binding property name (in object binding pattern) @@ -702,7 +778,7 @@ namespace ts { initializer?: Expression; // Optional initializer } - export interface ObjectLiteralElement extends RealDeclaration { + export interface ObjectLiteralElement extends DeclarationBase { _objectLiteralBrandBrand: any; name?: PropertyName; } @@ -737,16 +813,24 @@ namespace ts { expression: Expression; } - // SyntaxKind.VariableDeclaration - // SyntaxKind.Parameter - // SyntaxKind.BindingElement - // SyntaxKind.Property - // SyntaxKind.PropertyAssignment - // SyntaxKind.JsxAttribute - // SyntaxKind.ShorthandPropertyAssignment - // SyntaxKind.EnumMember - // SyntaxKind.JSDocPropertyTag - export interface VariableLikeDeclaration extends RealDeclaration { + /** + * There aren't any explicit subtypes of VariableLikeDeclaration; + * it's just structurally relatable to a number of types. + * (Maybe it should be an intersection of the below types.) + */ + export interface VariableLikeDeclaration extends DeclarationBase { + kind: + | SyntaxKind.VariableDeclaration + | SyntaxKind.Parameter + | SyntaxKind.BindingElement + | SyntaxKind.PropertyAssignment + | SyntaxKind.PropertyDeclaration + | SyntaxKind.PropertySignature + | SyntaxKind.JsxAttribute + | SyntaxKind.ShorthandPropertyAssignment + | SyntaxKind.EnumMember + | SyntaxKind.JSDocPropertyTag + | SyntaxKind.JSDocRecordMember; propertyName?: PropertyName; dotDotDotToken?: DotDotDotToken; name: DeclarationName; @@ -755,10 +839,6 @@ namespace ts { initializer?: Expression; } - export interface PropertyLikeDeclaration extends RealDeclaration { - name: PropertyName; - } - export interface ObjectBindingPattern extends Node { kind: SyntaxKind.ObjectBindingPattern; parent?: VariableDeclaration | ParameterDeclaration | BindingElement; @@ -904,7 +984,7 @@ namespace ts { } // A TypeLiteral is the declaration node for an anonymous symbol. - export interface TypeLiteralNode extends TypeNode, RealDeclaration { + export interface TypeLiteralNode extends TypeNode, DeclarationBase { kind: SyntaxKind.TypeLiteral; members: NodeArray; } @@ -948,7 +1028,7 @@ namespace ts { indexType: TypeNode; } - export interface MappedTypeNode extends TypeNode, RealDeclaration { + export interface MappedTypeNode extends TypeNode, DeclarationBase { kind: SyntaxKind.MappedType; parent?: TypeAliasDeclaration; readonlyToken?: ReadonlyToken; @@ -1405,7 +1485,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 extends PrimaryExpression, RealDeclaration { + export interface ObjectLiteralExpressionBase extends PrimaryExpression, DeclarationBase { properties: NodeArray; } @@ -1419,7 +1499,7 @@ namespace ts { export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression | ParenthesizedExpression; export type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression; - export interface PropertyAccessExpression extends MemberExpression, RealDeclaration { + export interface PropertyAccessExpression extends MemberExpression, DeclarationBase { kind: SyntaxKind.PropertyAccessExpression; expression: LeftHandSideExpression; name: Identifier; @@ -1451,7 +1531,7 @@ namespace ts { | SuperElementAccessExpression ; - export interface CallExpression extends LeftHandSideExpression, RealDeclaration { + export interface CallExpression extends LeftHandSideExpression, DeclarationBase { kind: SyntaxKind.CallExpression; expression: LeftHandSideExpression; typeArguments?: NodeArray; @@ -1470,7 +1550,7 @@ namespace ts { typeArguments?: NodeArray; } - export interface NewExpression extends PrimaryExpression, RealDeclaration { + export interface NewExpression extends PrimaryExpression, DeclarationBase { kind: SyntaxKind.NewExpression; expression: LeftHandSideExpression; typeArguments?: NodeArray; @@ -1528,6 +1608,7 @@ namespace ts { export type JsxTagNameExpression = PrimaryExpression | PropertyAccessExpression; export interface JsxAttributes extends ObjectLiteralExpressionBase { + kind: SyntaxKind.JsxAttributes; parent?: JsxOpeningLikeElement; } @@ -1764,7 +1845,10 @@ namespace ts { export type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration; - export interface ClassLikeDeclaration extends RealDeclaration { + export interface ClassLikeDeclaration extends DeclarationBase { + kind: + | SyntaxKind.ClassDeclaration + | SyntaxKind.ClassExpression; name?: Identifier; typeParameters?: NodeArray; heritageClauses?: NodeArray; @@ -1780,12 +1864,30 @@ namespace ts { kind: SyntaxKind.ClassExpression; } - export interface ClassElement extends RealDeclaration { + export interface ClassElement extends DeclarationBase { + kind: + | SyntaxKind.PropertyDeclaration + | SyntaxKind.MethodDeclaration + | SyntaxKind.Constructor + | SyntaxKind.SemicolonClassElement + | SyntaxKind.GetAccessor + | SyntaxKind.SetAccessor + | SyntaxKind.IndexSignature + | SyntaxKind.MissingDeclaration; _classElementBrand: any; name?: PropertyName; } - export interface TypeElement extends RealDeclaration { + export interface TypeElement extends DeclarationBase { + kind: + | SyntaxKind.CallSignature + | SyntaxKind.ConstructSignature + | SyntaxKind.PropertySignature + | SyntaxKind.MethodSignature + | SyntaxKind.IndexSignature + | SyntaxKind.MissingDeclaration + | SyntaxKind.JSDocPropertyTag + | SyntaxKind.JSDocRecordMember; _typeElementBrand: any; name?: PropertyName; questionToken?: QuestionToken; @@ -1813,7 +1915,7 @@ namespace ts { type: TypeNode; } - export interface EnumMember extends RealDeclaration { + export interface EnumMember extends DeclarationBase { kind: SyntaxKind.EnumMember; parent?: EnumDeclaration; // This does include ComputedPropertyName, but the parser will give an error @@ -1902,14 +2004,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 RealDeclaration { + export interface ImportClause extends DeclarationBase { kind: SyntaxKind.ImportClause; parent?: ImportDeclaration; name?: Identifier; // Default binding namedBindings?: NamedImportBindings; } - export interface NamespaceImport extends RealDeclaration { + export interface NamespaceImport extends DeclarationBase { kind: SyntaxKind.NamespaceImport; parent?: ImportClause; name: Identifier; @@ -1942,14 +2044,14 @@ namespace ts { export type NamedImportsOrExports = NamedImports | NamedExports; - export interface ImportSpecifier extends RealDeclaration { + export interface ImportSpecifier extends DeclarationBase { 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 RealDeclaration { + export interface ExportSpecifier extends DeclarationBase { kind: SyntaxKind.ExportSpecifier; parent?: NamedExports; propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent) @@ -2115,7 +2217,7 @@ namespace ts { typeExpression: JSDocTypeExpression; } - export interface JSDocTypedefTag extends JSDocTag, RealDeclaration { + export interface JSDocTypedefTag extends JSDocTag, DeclarationBase { kind: SyntaxKind.JSDocTypedefTag; fullName?: JSDocNamespaceDeclaration | Identifier; name?: Identifier; @@ -2249,7 +2351,7 @@ namespace ts { // Source files are declarations when they are external modules. - export interface SourceFile extends RealDeclaration { + export interface SourceFile extends DeclarationBase { kind: SyntaxKind.SourceFile; statements: NodeArray; endOfFileToken: Token; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 5b1cbb849bc76..e38f0ad331a3a 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -11,36 +11,6 @@ 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) { @@ -596,7 +566,7 @@ namespace ts { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: case SyntaxKind.TypeAliasDeclaration: - errorNode = (node).name; + errorNode = (node).name; break; case SyntaxKind.ArrowFunction: return getErrorSpanForArrowFunction(sourceFile, node); @@ -1806,6 +1776,37 @@ namespace ts { return false; } + export function getNameOfDeclaration(declaration: Declaration): DeclarationName { + if (!declaration) { + return undefined; + } + if (declaration.kind === SyntaxKind.BinaryExpression) { + const kind = getSpecialPropertyAssignmentKind(declaration); + 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 isLiteralComputedPropertyDeclarationName(node: Node) { return (node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NumericLiteral) && node.parent.kind === SyntaxKind.ComputedPropertyName && @@ -1826,7 +1827,7 @@ namespace ts { case SyntaxKind.PropertyAssignment: case SyntaxKind.PropertyAccessExpression: // Name in member declaration or property name in property access - return (parent).name === node; + return (parent).name === node; case SyntaxKind.QualifiedName: // Name on right hand side of dot in a type query if ((parent).right === node) { @@ -4101,7 +4102,7 @@ namespace ts { || kind === SyntaxKind.MergeDeclarationMarker; } - export function isDeclaration(node: Node): node is RealDeclaration { + export function isDeclaration(node: Node): node is DeclarationBase { return isDeclarationKind(node.kind); } From b39c319f0c4ee9b460ed51eba77e8c0958896c80 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 5 May 2017 13:48:45 -0700 Subject: [PATCH 04/11] Fix lint --- src/compiler/types.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index de71fbfdabee7..043c8b9a0b1e0 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -711,7 +711,7 @@ namespace ts { | SyntaxKind.SetAccessor | SyntaxKind.Constructor | SyntaxKind.ArrowFunction - | SyntaxKind.FunctionExpression + | SyntaxKind.FunctionExpression; name?: PropertyName; typeParameters?: NodeArray; @@ -814,9 +814,8 @@ namespace ts { } /** - * There aren't any explicit subtypes of VariableLikeDeclaration; + * There aren't any explicit subtypes of VariableLikeDeclaration, * it's just structurally relatable to a number of types. - * (Maybe it should be an intersection of the below types.) */ export interface VariableLikeDeclaration extends DeclarationBase { kind: From 6a175321bf432f31490dd81fcc7fd0f7257c4baa Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 5 May 2017 15:09:54 -0700 Subject: [PATCH 05/11] Address comments: simplify, dedupe and clean up --- src/compiler/checker.ts | 24 ++++++++---------------- src/compiler/utilities.ts | 29 +++++++++++++++-------------- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 05af363fb8e7d..aea175ac8b162 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18110,18 +18110,17 @@ namespace ts { forEach(overloads, o => { const deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags; - const name = getNameOfDeclaration(o); if (deviation & ModifierFlags.Export) { - error(name, Diagnostics.Overload_signatures_must_all_be_exported_or_non_exported); + error(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_exported_or_non_exported); } else if (deviation & ModifierFlags.Ambient) { - error(name, Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient); + error(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient); } else if (deviation & (ModifierFlags.Private | ModifierFlags.Protected)) { - error(name || o, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected); + error(getNameOfDeclaration(o) || o, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected); } else if (deviation & ModifierFlags.Abstract) { - error(name, Diagnostics.Overload_signatures_must_all_be_abstract_or_non_abstract); + error(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_abstract_or_non_abstract); } }); } @@ -20317,19 +20316,12 @@ namespace ts { 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 + // this allows us to rule out cases when both property and indexer are inherited from the base class + let errorNode: Node; if (propDeclaration && - (getNameOfDeclaration(propDeclaration).kind === SyntaxKind.ComputedPropertyName || + (propDeclaration.kind === SyntaxKind.BinaryExpression || + getNameOfDeclaration(propDeclaration).kind === SyntaxKind.ComputedPropertyName || prop.parent === containingType.symbol)) { errorNode = propDeclaration; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index e38f0ad331a3a..7b92dbf68b5c3 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1784,21 +1784,21 @@ namespace ts { const kind = getSpecialPropertyAssignmentKind(declaration); const lhs = (declaration as BinaryExpression).left; switch (kind) { - case SpecialPropertyAssignmentKind.None: - case SpecialPropertyAssignmentKind.ModuleExports: - return undefined; - case SpecialPropertyAssignmentKind.ExportsProperty: - if (lhs.kind === SyntaxKind.Identifier) { + 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; - } - else { + case SpecialPropertyAssignmentKind.PrototypeProperty: 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 { @@ -2025,7 +2025,8 @@ namespace ts { * Symbol. */ export function hasDynamicName(declaration: Declaration): boolean { - return getNameOfDeclaration(declaration) && isDynamicName(getNameOfDeclaration(declaration)); + const name = getNameOfDeclaration(declaration); + return name && isDynamicName(name); } export function isDynamicName(name: DeclarationName): boolean { From 22f353ac940bfd4e170d9e56a094fdd385476191 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 8 May 2017 09:35:21 -0700 Subject: [PATCH 06/11] Turn ClassElement and TypeElement into unions too Slows down compilation another 3%, so I'm not sure we'll want to take this change. --- src/compiler/types.ts | 75 ++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 043c8b9a0b1e0..4ec5c0f97bf31 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -616,7 +616,6 @@ namespace ts { | CallExpression | CallSignatureDeclaration | ClassDeclaration - | ClassElement | ClassExpression | ClassLikeDeclaration | ConstructSignatureDeclaration @@ -717,13 +716,14 @@ namespace ts { typeParameters?: NodeArray; parameters: NodeArray; type?: TypeNode; + questionToken?: QuestionToken; } - export interface CallSignatureDeclaration extends SignatureDeclaration, TypeElement { + export interface CallSignatureDeclaration extends SignatureDeclaration { kind: SyntaxKind.CallSignature; } - export interface ConstructSignatureDeclaration extends SignatureDeclaration, TypeElement { + export interface ConstructSignatureDeclaration extends SignatureDeclaration { kind: SyntaxKind.ConstructSignature; } @@ -762,7 +762,7 @@ namespace ts { initializer?: Expression; // Optional initializer } - export interface PropertySignature extends TypeElement { + export interface PropertySignature extends DeclarationBase { kind: SyntaxKind.PropertySignature | SyntaxKind.JSDocRecordMember; name: PropertyName; // Declared property name questionToken?: QuestionToken; // Present on optional property @@ -770,7 +770,7 @@ namespace ts { initializer?: Expression; // Optional initializer } - export interface PropertyDeclaration extends ClassElement { + export interface PropertyDeclaration extends DeclarationBase { kind: SyntaxKind.PropertyDeclaration; questionToken?: QuestionToken; // Present for use with reporting a grammar error name: PropertyName; @@ -876,7 +876,7 @@ namespace ts { body?: FunctionBody; } - export interface MethodSignature extends SignatureDeclaration, TypeElement { + export interface MethodSignature extends SignatureDeclaration { kind: SyntaxKind.MethodSignature; name: PropertyName; } @@ -890,27 +890,28 @@ namespace ts { // Because of this, it may be necessary to determine what sort of MethodDeclaration you have // at later stages of the compiler pipeline. In that case, you can either check the parent kind // of the method, or use helpers like isObjectLiteralMethodDeclaration - export interface MethodDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement { + export interface MethodDeclaration extends FunctionLikeDeclaration, ObjectLiteralElement { kind: SyntaxKind.MethodDeclaration; name: PropertyName; body?: FunctionBody; } - export interface ConstructorDeclaration extends FunctionLikeDeclaration, ClassElement { + export interface ConstructorDeclaration extends FunctionLikeDeclaration { kind: SyntaxKind.Constructor; parent?: ClassDeclaration | ClassExpression; body?: FunctionBody; } /** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */ - export interface SemicolonClassElement extends ClassElement { + export interface SemicolonClassElement extends DeclarationBase { kind: SyntaxKind.SemicolonClassElement; parent?: ClassDeclaration | ClassExpression; + name?: PropertyName; } // See the comment on MethodDeclaration for the intuition behind GetAccessorDeclaration being a // ClassElement and an ObjectLiteralElement. - export interface GetAccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement { + export interface GetAccessorDeclaration extends FunctionLikeDeclaration, ObjectLiteralElement { kind: SyntaxKind.GetAccessor; parent?: ClassDeclaration | ClassExpression | ObjectLiteralExpression; name: PropertyName; @@ -919,7 +920,7 @@ namespace ts { // See the comment on MethodDeclaration for the intuition behind SetAccessorDeclaration being a // ClassElement and an ObjectLiteralElement. - export interface SetAccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement { + export interface SetAccessorDeclaration extends FunctionLikeDeclaration, ObjectLiteralElement { kind: SyntaxKind.SetAccessor; parent?: ClassDeclaration | ClassExpression | ObjectLiteralExpression; name: PropertyName; @@ -928,7 +929,7 @@ namespace ts { export type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration; - export interface IndexSignatureDeclaration extends SignatureDeclaration, ClassElement, TypeElement { + export interface IndexSignatureDeclaration extends SignatureDeclaration { kind: SyntaxKind.IndexSignature; parent?: ClassDeclaration | ClassExpression | InterfaceDeclaration | TypeLiteralNode; } @@ -1695,7 +1696,7 @@ namespace ts { kind: SyntaxKind.DebuggerStatement; } - export interface MissingDeclaration extends DeclarationStatement, ClassElement, ObjectLiteralElement, TypeElement { + export interface MissingDeclaration extends DeclarationStatement, ObjectLiteralElement { kind: SyntaxKind.MissingDeclaration; name?: Identifier; } @@ -1863,34 +1864,26 @@ namespace ts { kind: SyntaxKind.ClassExpression; } - export interface ClassElement extends DeclarationBase { - kind: - | SyntaxKind.PropertyDeclaration - | SyntaxKind.MethodDeclaration - | SyntaxKind.Constructor - | SyntaxKind.SemicolonClassElement - | SyntaxKind.GetAccessor - | SyntaxKind.SetAccessor - | SyntaxKind.IndexSignature - | SyntaxKind.MissingDeclaration; - _classElementBrand: any; - name?: PropertyName; - } + export type ClassElement = + | PropertyDeclaration + | MethodDeclaration + | ConstructorDeclaration + | SemicolonClassElement + | GetAccessorDeclaration + | SetAccessorDeclaration + | IndexSignatureDeclaration + | MissingDeclaration; - export interface TypeElement extends DeclarationBase { - kind: - | SyntaxKind.CallSignature - | SyntaxKind.ConstructSignature - | SyntaxKind.PropertySignature - | SyntaxKind.MethodSignature - | SyntaxKind.IndexSignature - | SyntaxKind.MissingDeclaration - | SyntaxKind.JSDocPropertyTag - | SyntaxKind.JSDocRecordMember; - _typeElementBrand: any; - name?: PropertyName; - questionToken?: QuestionToken; - } + export type TypeElement = + | CallSignatureDeclaration + | ConstructSignatureDeclaration + | PropertySignature + | MethodSignature + | IndexSignatureDeclaration + | MissingDeclaration + | IndexSignatureDeclaration + | JSDocPropertyTag + | JSDocRecordMember; export interface InterfaceDeclaration extends DeclarationStatement { kind: SyntaxKind.InterfaceDeclaration; @@ -2224,7 +2217,7 @@ namespace ts { jsDocTypeLiteral?: JSDocTypeLiteral; } - export interface JSDocPropertyTag extends JSDocTag, TypeElement { + export interface JSDocPropertyTag extends JSDocTag { kind: SyntaxKind.JSDocPropertyTag; name: Identifier; typeExpression: JSDocTypeExpression; From dd94ad239abaafb9a4524bb8a437d55189b3807f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 8 May 2017 14:16:53 -0700 Subject: [PATCH 07/11] Revert "Turn ClassElement and TypeElement into unions too" This reverts commit 22f353ac940bfd4e170d9e56a094fdd385476191. --- src/compiler/types.ts | 75 +++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4ec5c0f97bf31..043c8b9a0b1e0 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -616,6 +616,7 @@ namespace ts { | CallExpression | CallSignatureDeclaration | ClassDeclaration + | ClassElement | ClassExpression | ClassLikeDeclaration | ConstructSignatureDeclaration @@ -716,14 +717,13 @@ namespace ts { typeParameters?: NodeArray; parameters: NodeArray; type?: TypeNode; - questionToken?: QuestionToken; } - export interface CallSignatureDeclaration extends SignatureDeclaration { + export interface CallSignatureDeclaration extends SignatureDeclaration, TypeElement { kind: SyntaxKind.CallSignature; } - export interface ConstructSignatureDeclaration extends SignatureDeclaration { + export interface ConstructSignatureDeclaration extends SignatureDeclaration, TypeElement { kind: SyntaxKind.ConstructSignature; } @@ -762,7 +762,7 @@ namespace ts { initializer?: Expression; // Optional initializer } - export interface PropertySignature extends DeclarationBase { + export interface PropertySignature extends TypeElement { kind: SyntaxKind.PropertySignature | SyntaxKind.JSDocRecordMember; name: PropertyName; // Declared property name questionToken?: QuestionToken; // Present on optional property @@ -770,7 +770,7 @@ namespace ts { initializer?: Expression; // Optional initializer } - export interface PropertyDeclaration extends DeclarationBase { + export interface PropertyDeclaration extends ClassElement { kind: SyntaxKind.PropertyDeclaration; questionToken?: QuestionToken; // Present for use with reporting a grammar error name: PropertyName; @@ -876,7 +876,7 @@ namespace ts { body?: FunctionBody; } - export interface MethodSignature extends SignatureDeclaration { + export interface MethodSignature extends SignatureDeclaration, TypeElement { kind: SyntaxKind.MethodSignature; name: PropertyName; } @@ -890,28 +890,27 @@ namespace ts { // Because of this, it may be necessary to determine what sort of MethodDeclaration you have // at later stages of the compiler pipeline. In that case, you can either check the parent kind // of the method, or use helpers like isObjectLiteralMethodDeclaration - export interface MethodDeclaration extends FunctionLikeDeclaration, ObjectLiteralElement { + export interface MethodDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement { kind: SyntaxKind.MethodDeclaration; name: PropertyName; body?: FunctionBody; } - export interface ConstructorDeclaration extends FunctionLikeDeclaration { + export interface ConstructorDeclaration extends FunctionLikeDeclaration, ClassElement { kind: SyntaxKind.Constructor; parent?: ClassDeclaration | ClassExpression; body?: FunctionBody; } /** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */ - export interface SemicolonClassElement extends DeclarationBase { + export interface SemicolonClassElement extends ClassElement { kind: SyntaxKind.SemicolonClassElement; parent?: ClassDeclaration | ClassExpression; - name?: PropertyName; } // See the comment on MethodDeclaration for the intuition behind GetAccessorDeclaration being a // ClassElement and an ObjectLiteralElement. - export interface GetAccessorDeclaration extends FunctionLikeDeclaration, ObjectLiteralElement { + export interface GetAccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement { kind: SyntaxKind.GetAccessor; parent?: ClassDeclaration | ClassExpression | ObjectLiteralExpression; name: PropertyName; @@ -920,7 +919,7 @@ namespace ts { // See the comment on MethodDeclaration for the intuition behind SetAccessorDeclaration being a // ClassElement and an ObjectLiteralElement. - export interface SetAccessorDeclaration extends FunctionLikeDeclaration, ObjectLiteralElement { + export interface SetAccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement { kind: SyntaxKind.SetAccessor; parent?: ClassDeclaration | ClassExpression | ObjectLiteralExpression; name: PropertyName; @@ -929,7 +928,7 @@ namespace ts { export type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration; - export interface IndexSignatureDeclaration extends SignatureDeclaration { + export interface IndexSignatureDeclaration extends SignatureDeclaration, ClassElement, TypeElement { kind: SyntaxKind.IndexSignature; parent?: ClassDeclaration | ClassExpression | InterfaceDeclaration | TypeLiteralNode; } @@ -1696,7 +1695,7 @@ namespace ts { kind: SyntaxKind.DebuggerStatement; } - export interface MissingDeclaration extends DeclarationStatement, ObjectLiteralElement { + export interface MissingDeclaration extends DeclarationStatement, ClassElement, ObjectLiteralElement, TypeElement { kind: SyntaxKind.MissingDeclaration; name?: Identifier; } @@ -1864,26 +1863,34 @@ namespace ts { kind: SyntaxKind.ClassExpression; } - export type ClassElement = - | PropertyDeclaration - | MethodDeclaration - | ConstructorDeclaration - | SemicolonClassElement - | GetAccessorDeclaration - | SetAccessorDeclaration - | IndexSignatureDeclaration - | MissingDeclaration; + export interface ClassElement extends DeclarationBase { + kind: + | SyntaxKind.PropertyDeclaration + | SyntaxKind.MethodDeclaration + | SyntaxKind.Constructor + | SyntaxKind.SemicolonClassElement + | SyntaxKind.GetAccessor + | SyntaxKind.SetAccessor + | SyntaxKind.IndexSignature + | SyntaxKind.MissingDeclaration; + _classElementBrand: any; + name?: PropertyName; + } - export type TypeElement = - | CallSignatureDeclaration - | ConstructSignatureDeclaration - | PropertySignature - | MethodSignature - | IndexSignatureDeclaration - | MissingDeclaration - | IndexSignatureDeclaration - | JSDocPropertyTag - | JSDocRecordMember; + export interface TypeElement extends DeclarationBase { + kind: + | SyntaxKind.CallSignature + | SyntaxKind.ConstructSignature + | SyntaxKind.PropertySignature + | SyntaxKind.MethodSignature + | SyntaxKind.IndexSignature + | SyntaxKind.MissingDeclaration + | SyntaxKind.JSDocPropertyTag + | SyntaxKind.JSDocRecordMember; + _typeElementBrand: any; + name?: PropertyName; + questionToken?: QuestionToken; + } export interface InterfaceDeclaration extends DeclarationStatement { kind: SyntaxKind.InterfaceDeclaration; @@ -2217,7 +2224,7 @@ namespace ts { jsDocTypeLiteral?: JSDocTypeLiteral; } - export interface JSDocPropertyTag extends JSDocTag { + export interface JSDocPropertyTag extends JSDocTag, TypeElement { kind: SyntaxKind.JSDocPropertyTag; name: Identifier; typeExpression: JSDocTypeExpression; From e81733b82723dac1f853edec8ea8d8c4c6fc48a5 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 8 May 2017 14:17:11 -0700 Subject: [PATCH 08/11] Revert "Fix lint" This reverts commit b39c319f0c4ee9b460ed51eba77e8c0958896c80. --- src/compiler/types.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 043c8b9a0b1e0..de71fbfdabee7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -711,7 +711,7 @@ namespace ts { | SyntaxKind.SetAccessor | SyntaxKind.Constructor | SyntaxKind.ArrowFunction - | SyntaxKind.FunctionExpression; + | SyntaxKind.FunctionExpression name?: PropertyName; typeParameters?: NodeArray; @@ -814,8 +814,9 @@ namespace ts { } /** - * There aren't any explicit subtypes of VariableLikeDeclaration, + * There aren't any explicit subtypes of VariableLikeDeclaration; * it's just structurally relatable to a number of types. + * (Maybe it should be an intersection of the below types.) */ export interface VariableLikeDeclaration extends DeclarationBase { kind: From acec74b1afc93bba32ac44afc0c6aa8fc12e2807 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 8 May 2017 14:24:45 -0700 Subject: [PATCH 09/11] Revert "Convert `Declaration` to union, not type hierarchy" This reverts commit 573040f0cfa713929bfa1fe84f4fd2a81cc82658. --- src/compiler/binder.ts | 6 +- src/compiler/checker.ts | 20 +-- src/compiler/transformers/es2015.ts | 2 +- src/compiler/types.ts | 184 +++++++--------------------- src/compiler/utilities.ts | 9 +- 5 files changed, 59 insertions(+), 162 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 8506378e216c9..38cb93bff7e57 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -304,7 +304,7 @@ namespace ts { } function getDisplayName(node: Declaration): string { - return (node as DeclarationBase).name ? declarationNameToString((node as DeclarationBase).name) : getDeclarationName(node); + return (node as RealDeclaration).name ? declarationNameToString((node as RealDeclaration).name) : getDeclarationName(node); } /** @@ -367,8 +367,8 @@ namespace ts { symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name)); } else { - if ((node as DeclarationBase).name) { - (node as DeclarationBase).name.parent = node; + if ((node as RealDeclaration).name) { + (node as RealDeclaration).name.parent = node; } // Report errors every position with duplicate declaration diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index aea175ac8b162..f7d7a79f9a07a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3621,7 +3621,7 @@ namespace ts { }); } - function isDeclarationVisible(node: Node): boolean { + function isDeclarationVisible(node: Declaration): boolean { if (node) { const links = getNodeLinks(node); if (links.isVisible === undefined) { @@ -3635,10 +3635,10 @@ namespace ts { function determineIfDeclarationIsVisible() { switch (node.kind) { case SyntaxKind.BindingElement: - return isDeclarationVisible(node.parent.parent); + return isDeclarationVisible(node.parent.parent); case SyntaxKind.VariableDeclaration: - const declaration = node as VariableDeclaration; - if (isBindingPattern(declaration.name) && !declaration.name.elements.length) { + if (isBindingPattern(node.name) && + !(node.name).elements.length) { // If the binding pattern is empty, this variable declaration is not visible return false; } @@ -3661,7 +3661,7 @@ namespace ts { return isGlobalSourceFile(parent); } // Exported members/ambient module elements (exception import declaration) are visible if parent is visible - return isDeclarationVisible(parent); + return isDeclarationVisible(parent); case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: @@ -3691,7 +3691,7 @@ namespace ts { case SyntaxKind.UnionType: case SyntaxKind.IntersectionType: case SyntaxKind.ParenthesizedType: - return isDeclarationVisible(node.parent); + return isDeclarationVisible(node.parent); // Default binding, import specifier and namespace import is visible // only on demand so by default it is not visible @@ -6236,8 +6236,8 @@ namespace ts { case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - return (node).name.kind === SyntaxKind.ComputedPropertyName - && traverse((node).name); + return (node).name.kind === SyntaxKind.ComputedPropertyName + && traverse((node).name); default: return !nodeStartsNewLexicalEnvironment(node) && !isPartOfTypeNode(node) && forEachChild(node, traverse); @@ -21909,7 +21909,7 @@ namespace ts { function isTypeDeclarationName(name: Node): boolean { return name.kind === SyntaxKind.Identifier && isTypeDeclaration(name.parent) && - (name.parent).name === name; + (name.parent).name === name; } function isTypeDeclaration(node: Node): boolean { @@ -22537,7 +22537,7 @@ namespace ts { // Return true if the given node is a declaration of a nested block scoped entity with a name that either hides an // existing name or might hide a name when compiled downlevel - function isDeclarationWithCollidingName(node: Node): boolean { + function isDeclarationWithCollidingName(node: Declaration): boolean { node = getParseTreeNode(node, isDeclaration); if (node) { const symbol = getSymbolOfNode(node); diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 4165b0679e1ef..188da04b36cbb 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -3748,7 +3748,7 @@ namespace ts { case SyntaxKind.ClassDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.VariableDeclaration: - return (parent).name === node + return (parent).name === node && resolver.isDeclarationWithCollidingName(parent); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index de71fbfdabee7..51e9d6717ee28 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -603,75 +603,15 @@ namespace ts { export type DeclarationName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | BindingPattern; - export interface DeclarationBase extends Node { + export interface RealDeclaration extends Node { _declarationBrand: any; name?: DeclarationName; } - export type Declaration = - | ArrowFunction - // Binary expressions can be declarations if they are 'exports.foo = bar' expressions in JS files - | BinaryExpression - | BindingElement - | CallExpression - | CallSignatureDeclaration - | ClassDeclaration - | ClassElement - | ClassExpression - | ClassLikeDeclaration - | ConstructSignatureDeclaration - | ConstructorDeclaration - | ConstructorTypeNode - | EnumDeclaration - | EnumMember - | ExportAssignment - | ExportDeclaration - | ExportSpecifier - | FunctionDeclaration - | FunctionExpression - | FunctionTypeNode - | GetAccessorDeclaration - | ImportClause - | ImportEqualsDeclaration - | ImportSpecifier - | IndexSignatureDeclaration - | InterfaceDeclaration - | JSDocFunctionType - | JSDocNamespaceDeclaration - | JSDocPropertyTag - | JSDocTypedefTag - | JsxAttribute - | JsxAttributes - | JsxSpreadAttribute - | MappedTypeNode - | MethodDeclaration - | MethodSignature - | MissingDeclaration - | ModuleDeclaration - | NamespaceDeclaration - | NamespaceExportDeclaration - | NamespaceImport - | NewExpression - | ObjectLiteralExpression - | ParameterDeclaration - | PropertyAccessExpression - | PropertyAssignment - | PropertyDeclaration - | PropertySignature - | SemicolonClassElement - | SetAccessorDeclaration - | ShorthandPropertyAssignment - | SignatureDeclaration - | SourceFile - | SpreadAssignment - | TypeAliasDeclaration - | TypeElement - | TypeLiteralNode - | TypeParameterDeclaration - | VariableDeclaration - | VariableLikeDeclaration; - - export interface DeclarationStatement extends DeclarationBase, 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; } @@ -685,7 +625,7 @@ namespace ts { expression: LeftHandSideExpression; } - export interface TypeParameterDeclaration extends DeclarationBase { + export interface TypeParameterDeclaration extends RealDeclaration { kind: SyntaxKind.TypeParameter; parent?: DeclarationWithTypeParameters; name: Identifier; @@ -696,23 +636,7 @@ namespace ts { expression?: Expression; } - export interface SignatureDeclaration extends DeclarationBase { - kind: - | SyntaxKind.CallSignature - | SyntaxKind.ConstructSignature - | SyntaxKind.ConstructorType - | SyntaxKind.MethodSignature - | SyntaxKind.IndexSignature - | SyntaxKind.FunctionType - | SyntaxKind.JSDocFunctionType - | SyntaxKind.FunctionDeclaration - | SyntaxKind.MethodDeclaration - | SyntaxKind.GetAccessor - | SyntaxKind.SetAccessor - | SyntaxKind.Constructor - | SyntaxKind.ArrowFunction - | SyntaxKind.FunctionExpression - + export interface SignatureDeclaration extends RealDeclaration { name?: PropertyName; typeParameters?: NodeArray; parameters: NodeArray; @@ -729,7 +653,7 @@ namespace ts { export type BindingName = Identifier | BindingPattern; - export interface VariableDeclaration extends DeclarationBase { + export interface VariableDeclaration extends RealDeclaration { kind: SyntaxKind.VariableDeclaration; parent?: VariableDeclarationList | CatchClause; name: BindingName; // Declared variable name @@ -743,7 +667,7 @@ namespace ts { declarations: NodeArray; } - export interface ParameterDeclaration extends DeclarationBase { + export interface ParameterDeclaration extends RealDeclaration { kind: SyntaxKind.Parameter; parent?: SignatureDeclaration; dotDotDotToken?: DotDotDotToken; // Present on rest parameter @@ -753,7 +677,7 @@ namespace ts { initializer?: Expression; // Optional initializer } - export interface BindingElement extends DeclarationBase { + export interface BindingElement extends RealDeclaration { kind: SyntaxKind.BindingElement; parent?: BindingPattern; propertyName?: PropertyName; // Binding property name (in object binding pattern) @@ -778,7 +702,7 @@ namespace ts { initializer?: Expression; // Optional initializer } - export interface ObjectLiteralElement extends DeclarationBase { + export interface ObjectLiteralElement extends RealDeclaration { _objectLiteralBrandBrand: any; name?: PropertyName; } @@ -813,24 +737,16 @@ namespace ts { expression: Expression; } - /** - * There aren't any explicit subtypes of VariableLikeDeclaration; - * it's just structurally relatable to a number of types. - * (Maybe it should be an intersection of the below types.) - */ - export interface VariableLikeDeclaration extends DeclarationBase { - kind: - | SyntaxKind.VariableDeclaration - | SyntaxKind.Parameter - | SyntaxKind.BindingElement - | SyntaxKind.PropertyAssignment - | SyntaxKind.PropertyDeclaration - | SyntaxKind.PropertySignature - | SyntaxKind.JsxAttribute - | SyntaxKind.ShorthandPropertyAssignment - | SyntaxKind.EnumMember - | SyntaxKind.JSDocPropertyTag - | SyntaxKind.JSDocRecordMember; + // SyntaxKind.VariableDeclaration + // SyntaxKind.Parameter + // SyntaxKind.BindingElement + // SyntaxKind.Property + // SyntaxKind.PropertyAssignment + // SyntaxKind.JsxAttribute + // SyntaxKind.ShorthandPropertyAssignment + // SyntaxKind.EnumMember + // SyntaxKind.JSDocPropertyTag + export interface VariableLikeDeclaration extends RealDeclaration { propertyName?: PropertyName; dotDotDotToken?: DotDotDotToken; name: DeclarationName; @@ -839,6 +755,10 @@ namespace ts { initializer?: Expression; } + export interface PropertyLikeDeclaration extends RealDeclaration { + name: PropertyName; + } + export interface ObjectBindingPattern extends Node { kind: SyntaxKind.ObjectBindingPattern; parent?: VariableDeclaration | ParameterDeclaration | BindingElement; @@ -984,7 +904,7 @@ namespace ts { } // A TypeLiteral is the declaration node for an anonymous symbol. - export interface TypeLiteralNode extends TypeNode, DeclarationBase { + export interface TypeLiteralNode extends TypeNode, RealDeclaration { kind: SyntaxKind.TypeLiteral; members: NodeArray; } @@ -1028,7 +948,7 @@ namespace ts { indexType: TypeNode; } - export interface MappedTypeNode extends TypeNode, DeclarationBase { + export interface MappedTypeNode extends TypeNode, RealDeclaration { kind: SyntaxKind.MappedType; parent?: TypeAliasDeclaration; readonlyToken?: ReadonlyToken; @@ -1485,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 extends PrimaryExpression, DeclarationBase { + export interface ObjectLiteralExpressionBase extends PrimaryExpression, RealDeclaration { properties: NodeArray; } @@ -1499,7 +1419,7 @@ namespace ts { export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression | ParenthesizedExpression; export type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression; - export interface PropertyAccessExpression extends MemberExpression, DeclarationBase { + export interface PropertyAccessExpression extends MemberExpression, RealDeclaration { kind: SyntaxKind.PropertyAccessExpression; expression: LeftHandSideExpression; name: Identifier; @@ -1531,7 +1451,7 @@ namespace ts { | SuperElementAccessExpression ; - export interface CallExpression extends LeftHandSideExpression, DeclarationBase { + export interface CallExpression extends LeftHandSideExpression, RealDeclaration { kind: SyntaxKind.CallExpression; expression: LeftHandSideExpression; typeArguments?: NodeArray; @@ -1550,7 +1470,7 @@ namespace ts { typeArguments?: NodeArray; } - export interface NewExpression extends PrimaryExpression, DeclarationBase { + export interface NewExpression extends PrimaryExpression, RealDeclaration { kind: SyntaxKind.NewExpression; expression: LeftHandSideExpression; typeArguments?: NodeArray; @@ -1608,7 +1528,6 @@ namespace ts { export type JsxTagNameExpression = PrimaryExpression | PropertyAccessExpression; export interface JsxAttributes extends ObjectLiteralExpressionBase { - kind: SyntaxKind.JsxAttributes; parent?: JsxOpeningLikeElement; } @@ -1845,10 +1764,7 @@ namespace ts { export type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration; - export interface ClassLikeDeclaration extends DeclarationBase { - kind: - | SyntaxKind.ClassDeclaration - | SyntaxKind.ClassExpression; + export interface ClassLikeDeclaration extends RealDeclaration { name?: Identifier; typeParameters?: NodeArray; heritageClauses?: NodeArray; @@ -1864,30 +1780,12 @@ namespace ts { kind: SyntaxKind.ClassExpression; } - export interface ClassElement extends DeclarationBase { - kind: - | SyntaxKind.PropertyDeclaration - | SyntaxKind.MethodDeclaration - | SyntaxKind.Constructor - | SyntaxKind.SemicolonClassElement - | SyntaxKind.GetAccessor - | SyntaxKind.SetAccessor - | SyntaxKind.IndexSignature - | SyntaxKind.MissingDeclaration; + export interface ClassElement extends RealDeclaration { _classElementBrand: any; name?: PropertyName; } - export interface TypeElement extends DeclarationBase { - kind: - | SyntaxKind.CallSignature - | SyntaxKind.ConstructSignature - | SyntaxKind.PropertySignature - | SyntaxKind.MethodSignature - | SyntaxKind.IndexSignature - | SyntaxKind.MissingDeclaration - | SyntaxKind.JSDocPropertyTag - | SyntaxKind.JSDocRecordMember; + export interface TypeElement extends RealDeclaration { _typeElementBrand: any; name?: PropertyName; questionToken?: QuestionToken; @@ -1915,7 +1813,7 @@ namespace ts { type: TypeNode; } - export interface EnumMember extends DeclarationBase { + export interface EnumMember extends RealDeclaration { kind: SyntaxKind.EnumMember; parent?: EnumDeclaration; // This does include ComputedPropertyName, but the parser will give an error @@ -2004,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 DeclarationBase { + export interface ImportClause extends RealDeclaration { kind: SyntaxKind.ImportClause; parent?: ImportDeclaration; name?: Identifier; // Default binding namedBindings?: NamedImportBindings; } - export interface NamespaceImport extends DeclarationBase { + export interface NamespaceImport extends RealDeclaration { kind: SyntaxKind.NamespaceImport; parent?: ImportClause; name: Identifier; @@ -2044,14 +1942,14 @@ namespace ts { export type NamedImportsOrExports = NamedImports | NamedExports; - export interface ImportSpecifier extends DeclarationBase { + 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 DeclarationBase { + export interface ExportSpecifier extends RealDeclaration { kind: SyntaxKind.ExportSpecifier; parent?: NamedExports; propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent) @@ -2217,7 +2115,7 @@ namespace ts { typeExpression: JSDocTypeExpression; } - export interface JSDocTypedefTag extends JSDocTag, DeclarationBase { + export interface JSDocTypedefTag extends JSDocTag, RealDeclaration { kind: SyntaxKind.JSDocTypedefTag; fullName?: JSDocNamespaceDeclaration | Identifier; name?: Identifier; @@ -2351,7 +2249,7 @@ namespace ts { // Source files are declarations when they are external modules. - export interface SourceFile extends DeclarationBase { + export interface SourceFile extends RealDeclaration { kind: SyntaxKind.SourceFile; statements: NodeArray; endOfFileToken: Token; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 7b92dbf68b5c3..a3525ee0a705a 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -566,7 +566,7 @@ namespace ts { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: case SyntaxKind.TypeAliasDeclaration: - errorNode = (node).name; + errorNode = (node).name; break; case SyntaxKind.ArrowFunction: return getErrorSpanForArrowFunction(sourceFile, node); @@ -1781,7 +1781,7 @@ namespace ts { return undefined; } if (declaration.kind === SyntaxKind.BinaryExpression) { - const kind = getSpecialPropertyAssignmentKind(declaration); + const kind = getSpecialPropertyAssignmentKind(declaration as BinaryExpression); const lhs = (declaration as BinaryExpression).left; switch (kind) { case SpecialPropertyAssignmentKind.None: @@ -1806,7 +1806,6 @@ namespace ts { } } - export function isLiteralComputedPropertyDeclarationName(node: Node) { return (node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NumericLiteral) && node.parent.kind === SyntaxKind.ComputedPropertyName && @@ -1827,7 +1826,7 @@ namespace ts { case SyntaxKind.PropertyAssignment: case SyntaxKind.PropertyAccessExpression: // Name in member declaration or property name in property access - return (parent).name === node; + return (parent).name === node; case SyntaxKind.QualifiedName: // Name on right hand side of dot in a type query if ((parent).right === node) { @@ -4103,7 +4102,7 @@ namespace ts { || kind === SyntaxKind.MergeDeclarationMarker; } - export function isDeclaration(node: Node): node is DeclarationBase { + export function isDeclaration(node: Node): node is RealDeclaration { return isDeclarationKind(node.kind); } From 9392342f7807c28738199ce82c73e52ac3bc73ef Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 8 May 2017 15:07:50 -0700 Subject: [PATCH 10/11] Switch to Declaration/NamedDeclaration hierarchy --- src/compiler/binder.ts | 12 +++--- src/compiler/checker.ts | 12 +++--- src/compiler/transformers/es2015.ts | 2 +- src/compiler/types.ts | 60 ++++++++++++++--------------- src/compiler/utilities.ts | 10 ++--- src/services/completions.ts | 2 +- src/services/navigateTo.ts | 2 +- 7 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 38cb93bff7e57..b6074162fff3a 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -304,7 +304,7 @@ namespace ts { } function getDisplayName(node: Declaration): string { - return (node as RealDeclaration).name ? declarationNameToString((node as RealDeclaration).name) : getDeclarationName(node); + return (node as NamedDeclaration).name ? declarationNameToString((node as NamedDeclaration).name) : getDeclarationName(node); } /** @@ -367,8 +367,8 @@ namespace ts { symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name)); } else { - if ((node as RealDeclaration).name) { - (node as RealDeclaration).name.parent = node; + if ((node as NamedDeclaration).name) { + (node as NamedDeclaration).name.parent = node; } // Report errors every position with duplicate declaration @@ -440,9 +440,9 @@ namespace ts { // and this case is specially handled. Module augmentations should only be merged with original module definition // and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed. const isJSDocTypedefInJSDocNamespace = node.kind === SyntaxKind.JSDocTypedefTag && - node.name && - node.name.kind === SyntaxKind.Identifier && - (node.name).isInJSDocNamespace; + (node as JSDocTypedefTag).name && + (node as JSDocTypedefTag).name.kind === SyntaxKind.Identifier && + ((node as JSDocTypedefTag).name as Identifier).isInJSDocNamespace; if ((!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) || isJSDocTypedefInJSDocNamespace) { const exportKind = (symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0) | diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f7d7a79f9a07a..76a1616ce3d05 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3637,8 +3637,8 @@ namespace ts { case SyntaxKind.BindingElement: return isDeclarationVisible(node.parent.parent); case SyntaxKind.VariableDeclaration: - if (isBindingPattern(node.name) && - !(node.name).elements.length) { + if (isBindingPattern((node as VariableDeclaration).name) && + !((node as VariableDeclaration).name as BindingPattern).elements.length) { // If the binding pattern is empty, this variable declaration is not visible return false; } @@ -6236,8 +6236,8 @@ namespace ts { case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - return (node).name.kind === SyntaxKind.ComputedPropertyName - && traverse((node).name); + return (node).name.kind === SyntaxKind.ComputedPropertyName + && traverse((node).name); default: return !nodeStartsNewLexicalEnvironment(node) && !isPartOfTypeNode(node) && forEachChild(node, traverse); @@ -9925,7 +9925,7 @@ namespace ts { case SyntaxKind.SetAccessor: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: - if (!declaration.name) { + if (!(declaration as NamedDeclaration).name) { error(declaration, Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString); return; } @@ -21909,7 +21909,7 @@ namespace ts { function isTypeDeclarationName(name: Node): boolean { return name.kind === SyntaxKind.Identifier && isTypeDeclaration(name.parent) && - (name.parent).name === name; + (name.parent).name === name; } function isTypeDeclaration(node: Node): boolean { diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 188da04b36cbb..cd3f131010078 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -3748,7 +3748,7 @@ namespace ts { case SyntaxKind.ClassDeclaration: case SyntaxKind.EnumDeclaration: case SyntaxKind.VariableDeclaration: - return (parent).name === node + return (parent).name === node && resolver.isDeclarationWithCollidingName(parent); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 51e9d6717ee28..63879d76ffabd 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -603,15 +603,15 @@ namespace ts { export type DeclarationName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | BindingPattern; - export interface RealDeclaration extends Node { + export interface Declaration extends Node { _declarationBrand: any; - name?: DeclarationName; } - // Binary expressions can be declarations if they are 'exports.foo = bar' expressions in JS files - export type Declaration = RealDeclaration | BinaryExpression; + export interface NamedDeclaration extends Declaration { + name?: DeclarationName; + } - export interface DeclarationStatement extends RealDeclaration, Statement { + export interface DeclarationStatement extends NamedDeclaration, Statement { name?: Identifier | StringLiteral | NumericLiteral; } @@ -625,7 +625,7 @@ namespace ts { expression: LeftHandSideExpression; } - export interface TypeParameterDeclaration extends RealDeclaration { + export interface TypeParameterDeclaration extends NamedDeclaration { kind: SyntaxKind.TypeParameter; parent?: DeclarationWithTypeParameters; name: Identifier; @@ -636,7 +636,7 @@ namespace ts { expression?: Expression; } - export interface SignatureDeclaration extends RealDeclaration { + export interface SignatureDeclaration extends NamedDeclaration { name?: PropertyName; typeParameters?: NodeArray; parameters: NodeArray; @@ -653,7 +653,7 @@ namespace ts { export type BindingName = Identifier | BindingPattern; - export interface VariableDeclaration extends RealDeclaration { + export interface VariableDeclaration extends NamedDeclaration { kind: SyntaxKind.VariableDeclaration; parent?: VariableDeclarationList | CatchClause; name: BindingName; // Declared variable name @@ -667,7 +667,7 @@ namespace ts { declarations: NodeArray; } - export interface ParameterDeclaration extends RealDeclaration { + export interface ParameterDeclaration extends NamedDeclaration { kind: SyntaxKind.Parameter; parent?: SignatureDeclaration; dotDotDotToken?: DotDotDotToken; // Present on rest parameter @@ -677,7 +677,7 @@ namespace ts { initializer?: Expression; // Optional initializer } - export interface BindingElement extends RealDeclaration { + export interface BindingElement extends NamedDeclaration { kind: SyntaxKind.BindingElement; parent?: BindingPattern; propertyName?: PropertyName; // Binding property name (in object binding pattern) @@ -702,7 +702,7 @@ namespace ts { initializer?: Expression; // Optional initializer } - export interface ObjectLiteralElement extends RealDeclaration { + export interface ObjectLiteralElement extends NamedDeclaration { _objectLiteralBrandBrand: any; name?: PropertyName; } @@ -746,7 +746,7 @@ namespace ts { // SyntaxKind.ShorthandPropertyAssignment // SyntaxKind.EnumMember // SyntaxKind.JSDocPropertyTag - export interface VariableLikeDeclaration extends RealDeclaration { + export interface VariableLikeDeclaration extends NamedDeclaration { propertyName?: PropertyName; dotDotDotToken?: DotDotDotToken; name: DeclarationName; @@ -755,7 +755,7 @@ namespace ts { initializer?: Expression; } - export interface PropertyLikeDeclaration extends RealDeclaration { + export interface PropertyLikeDeclaration extends NamedDeclaration { name: PropertyName; } @@ -904,7 +904,7 @@ namespace ts { } // A TypeLiteral is the declaration node for an anonymous symbol. - export interface TypeLiteralNode extends TypeNode, RealDeclaration { + export interface TypeLiteralNode extends TypeNode, NamedDeclaration { kind: SyntaxKind.TypeLiteral; members: NodeArray; } @@ -948,7 +948,7 @@ namespace ts { indexType: TypeNode; } - export interface MappedTypeNode extends TypeNode, RealDeclaration { + export interface MappedTypeNode extends TypeNode, NamedDeclaration { kind: SyntaxKind.MappedType; parent?: TypeAliasDeclaration; readonlyToken?: ReadonlyToken; @@ -1219,7 +1219,7 @@ namespace ts { export type BinaryOperatorToken = Token; - export interface BinaryExpression extends Expression { + export interface BinaryExpression extends Expression, Declaration { kind: SyntaxKind.BinaryExpression; left: Expression; operatorToken: BinaryOperatorToken; @@ -1405,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 extends PrimaryExpression, RealDeclaration { + export interface ObjectLiteralExpressionBase extends PrimaryExpression, NamedDeclaration { properties: NodeArray; } @@ -1419,7 +1419,7 @@ namespace ts { export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression | ParenthesizedExpression; export type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression; - export interface PropertyAccessExpression extends MemberExpression, RealDeclaration { + export interface PropertyAccessExpression extends MemberExpression, NamedDeclaration { kind: SyntaxKind.PropertyAccessExpression; expression: LeftHandSideExpression; name: Identifier; @@ -1451,7 +1451,7 @@ namespace ts { | SuperElementAccessExpression ; - export interface CallExpression extends LeftHandSideExpression, RealDeclaration { + export interface CallExpression extends LeftHandSideExpression, NamedDeclaration { kind: SyntaxKind.CallExpression; expression: LeftHandSideExpression; typeArguments?: NodeArray; @@ -1470,7 +1470,7 @@ namespace ts { typeArguments?: NodeArray; } - export interface NewExpression extends PrimaryExpression, RealDeclaration { + export interface NewExpression extends PrimaryExpression, NamedDeclaration { kind: SyntaxKind.NewExpression; expression: LeftHandSideExpression; typeArguments?: NodeArray; @@ -1764,7 +1764,7 @@ namespace ts { export type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration; - export interface ClassLikeDeclaration extends RealDeclaration { + export interface ClassLikeDeclaration extends NamedDeclaration { name?: Identifier; typeParameters?: NodeArray; heritageClauses?: NodeArray; @@ -1780,12 +1780,12 @@ namespace ts { kind: SyntaxKind.ClassExpression; } - export interface ClassElement extends RealDeclaration { + export interface ClassElement extends NamedDeclaration { _classElementBrand: any; name?: PropertyName; } - export interface TypeElement extends RealDeclaration { + export interface TypeElement extends NamedDeclaration { _typeElementBrand: any; name?: PropertyName; questionToken?: QuestionToken; @@ -1813,7 +1813,7 @@ namespace ts { type: TypeNode; } - export interface EnumMember extends RealDeclaration { + export interface EnumMember extends NamedDeclaration { kind: SyntaxKind.EnumMember; parent?: EnumDeclaration; // This does include ComputedPropertyName, but the parser will give an error @@ -1902,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 RealDeclaration { + export interface ImportClause extends NamedDeclaration { kind: SyntaxKind.ImportClause; parent?: ImportDeclaration; name?: Identifier; // Default binding namedBindings?: NamedImportBindings; } - export interface NamespaceImport extends RealDeclaration { + export interface NamespaceImport extends NamedDeclaration { kind: SyntaxKind.NamespaceImport; parent?: ImportClause; name: Identifier; @@ -1942,14 +1942,14 @@ namespace ts { export type NamedImportsOrExports = NamedImports | NamedExports; - export interface ImportSpecifier extends RealDeclaration { + export interface ImportSpecifier extends NamedDeclaration { 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 RealDeclaration { + export interface ExportSpecifier extends NamedDeclaration { kind: SyntaxKind.ExportSpecifier; parent?: NamedExports; propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent) @@ -2115,7 +2115,7 @@ namespace ts { typeExpression: JSDocTypeExpression; } - export interface JSDocTypedefTag extends JSDocTag, RealDeclaration { + export interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { kind: SyntaxKind.JSDocTypedefTag; fullName?: JSDocNamespaceDeclaration | Identifier; name?: Identifier; @@ -2249,7 +2249,7 @@ namespace ts { // Source files are declarations when they are external modules. - export interface SourceFile extends RealDeclaration { + export interface SourceFile extends NamedDeclaration { kind: SyntaxKind.SourceFile; statements: NodeArray; endOfFileToken: Token; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index a3525ee0a705a..0dc6c92ed2cf8 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -566,7 +566,7 @@ namespace ts { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: case SyntaxKind.TypeAliasDeclaration: - errorNode = (node).name; + errorNode = (node).name; break; case SyntaxKind.ArrowFunction: return getErrorSpanForArrowFunction(sourceFile, node); @@ -1802,7 +1802,7 @@ namespace ts { } } else { - return declaration.name; + return (declaration as NamedDeclaration).name; } } @@ -1826,7 +1826,7 @@ namespace ts { case SyntaxKind.PropertyAssignment: case SyntaxKind.PropertyAccessExpression: // Name in member declaration or property name in property access - return (parent).name === node; + return (parent).name === node; case SyntaxKind.QualifiedName: // Name on right hand side of dot in a type query if ((parent).right === node) { @@ -2790,7 +2790,7 @@ namespace ts { forEach(declarations, (member: Declaration) => { if ((member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor) && hasModifier(member, ModifierFlags.Static) === hasModifier(accessor, ModifierFlags.Static)) { - const memberName = getPropertyNameForPropertyNameNode(member.name); + const memberName = getPropertyNameForPropertyNameNode((member as NamedDeclaration).name); const accessorName = getPropertyNameForPropertyNameNode(accessor.name); if (memberName === accessorName) { if (!firstAccessor) { @@ -4102,7 +4102,7 @@ namespace ts { || kind === SyntaxKind.MergeDeclarationMarker; } - export function isDeclaration(node: Node): node is RealDeclaration { + export function isDeclaration(node: Node): node is NamedDeclaration { return isDeclarationKind(node.kind); } diff --git a/src/services/completions.ts b/src/services/completions.ts index 6ac3762b4c749..b9d62df751e1f 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1214,7 +1214,7 @@ namespace ts.Completions { // TODO(jfreeman): Account for computed property name // NOTE: if one only performs this step when m.name is an identifier, // things like '__proto__' are not filtered out. - existingName = (m.name).text; + existingName = (getNameOfDeclaration(m) as Identifier).text; } existingMemberNames.set(existingName, true); diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index c29b29143c57f..2fdc567b9bbcf 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -52,7 +52,7 @@ namespace ts.NavigateTo { rawItems = filter(rawItems, item => { const decl = item.declaration; if (decl.kind === SyntaxKind.ImportClause || decl.kind === SyntaxKind.ImportSpecifier || decl.kind === SyntaxKind.ImportEqualsDeclaration) { - const importer = checker.getSymbolAtLocation(decl.name); + const importer = checker.getSymbolAtLocation((decl as NamedDeclaration).name); const imported = checker.getAliasedSymbol(importer); return importer.name !== imported.name; } From 157b777660b7e65d8e2d9cf871bd7f9c1aba5bbe Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 9 May 2017 10:46:47 -0700 Subject: [PATCH 11/11] Unnamed nodes now extend Declaration, not NamedDeclaration --- src/compiler/types.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a6c046166523c..4bd44a89f4df2 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -904,7 +904,7 @@ namespace ts { } // A TypeLiteral is the declaration node for an anonymous symbol. - export interface TypeLiteralNode extends TypeNode, NamedDeclaration { + export interface TypeLiteralNode extends TypeNode, Declaration { kind: SyntaxKind.TypeLiteral; members: NodeArray; } @@ -948,7 +948,7 @@ namespace ts { indexType: TypeNode; } - export interface MappedTypeNode extends TypeNode, NamedDeclaration { + export interface MappedTypeNode extends TypeNode, Declaration { kind: SyntaxKind.MappedType; parent?: TypeAliasDeclaration; readonlyToken?: ReadonlyToken; @@ -1405,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 extends PrimaryExpression, NamedDeclaration { + export interface ObjectLiteralExpressionBase extends PrimaryExpression, Declaration { properties: NodeArray; } @@ -1451,7 +1451,7 @@ namespace ts { | SuperElementAccessExpression ; - export interface CallExpression extends LeftHandSideExpression, NamedDeclaration { + export interface CallExpression extends LeftHandSideExpression, Declaration { kind: SyntaxKind.CallExpression; expression: LeftHandSideExpression; typeArguments?: NodeArray; @@ -1470,7 +1470,7 @@ namespace ts { typeArguments?: NodeArray; } - export interface NewExpression extends PrimaryExpression, NamedDeclaration { + export interface NewExpression extends PrimaryExpression, Declaration { kind: SyntaxKind.NewExpression; expression: LeftHandSideExpression; typeArguments?: NodeArray; @@ -2249,7 +2249,7 @@ namespace ts { // Source files are declarations when they are external modules. - export interface SourceFile extends NamedDeclaration { + export interface SourceFile extends Declaration { kind: SyntaxKind.SourceFile; statements: NodeArray; endOfFileToken: Token;