Convert Declaration to union, not type hierarchy

This commit is contained in:
Nathan Shively-Sanders 2017-05-05 13:47:28 -07:00
parent 1bdea3910f
commit 949bb27ff1
5 changed files with 190 additions and 87 deletions

View File

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

View File

@ -3617,7 +3617,7 @@ namespace ts {
});
}
function isDeclarationVisible(node: Declaration): boolean {
function isDeclarationVisible(node: Node): boolean {
if (node) {
const links = getNodeLinks(node);
if (links.isVisible === undefined) {
@ -3631,10 +3631,10 @@ namespace ts {
function determineIfDeclarationIsVisible() {
switch (node.kind) {
case SyntaxKind.BindingElement:
return isDeclarationVisible(<Declaration>node.parent.parent);
return isDeclarationVisible(node.parent.parent);
case SyntaxKind.VariableDeclaration:
if (isBindingPattern(node.name) &&
!(<BindingPattern>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;
}
@ -3657,7 +3657,7 @@ namespace ts {
return isGlobalSourceFile(parent);
}
// Exported members/ambient module elements (exception import declaration) are visible if parent is visible
return isDeclarationVisible(<Declaration>parent);
return isDeclarationVisible(parent);
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
@ -3687,7 +3687,7 @@ namespace ts {
case SyntaxKind.UnionType:
case SyntaxKind.IntersectionType:
case SyntaxKind.ParenthesizedType:
return isDeclarationVisible(<Declaration>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
@ -6235,8 +6235,8 @@ namespace ts {
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return (<RealDeclaration>node).name.kind === SyntaxKind.ComputedPropertyName
&& traverse((<RealDeclaration>node).name);
return (<DeclarationBase>node).name.kind === SyntaxKind.ComputedPropertyName
&& traverse((<DeclarationBase>node).name);
default:
return !nodeStartsNewLexicalEnvironment(node) && !isPartOfTypeNode(node) && forEachChild(node, traverse);
@ -21841,7 +21841,7 @@ namespace ts {
function isTypeDeclarationName(name: Node): boolean {
return name.kind === SyntaxKind.Identifier &&
isTypeDeclaration(name.parent) &&
(<RealDeclaration>name.parent).name === name;
(<TypeElement>name.parent).name === name;
}
function isTypeDeclaration(node: Node): boolean {
@ -22469,7 +22469,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);

View File

@ -3748,7 +3748,7 @@ namespace ts {
case SyntaxKind.ClassDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.VariableDeclaration:
return (<RealDeclaration>parent).name === node
return (<DeclarationBase>parent).name === node
&& resolver.isDeclarationWithCollidingName(<Declaration>parent);
}

View File

@ -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 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 RealDeclaration, Statement {
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<TypeParameterDeclaration>;
parameters: NodeArray<ParameterDeclaration>;
@ -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<VariableDeclaration>;
}
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<TypeElement>;
}
@ -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<T extends ObjectLiteralElement> extends PrimaryExpression, RealDeclaration {
export interface ObjectLiteralExpressionBase<T extends ObjectLiteralElement> extends PrimaryExpression, DeclarationBase {
properties: NodeArray<T>;
}
@ -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<TypeNode>;
@ -1470,7 +1550,7 @@ namespace ts {
typeArguments?: NodeArray<TypeNode>;
}
export interface NewExpression extends PrimaryExpression, RealDeclaration {
export interface NewExpression extends PrimaryExpression, DeclarationBase {
kind: SyntaxKind.NewExpression;
expression: LeftHandSideExpression;
typeArguments?: NodeArray<TypeNode>;
@ -1528,6 +1608,7 @@ namespace ts {
export type JsxTagNameExpression = PrimaryExpression | PropertyAccessExpression;
export interface JsxAttributes extends ObjectLiteralExpressionBase<JsxAttributeLike> {
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<TypeParameterDeclaration>;
heritageClauses?: NodeArray<HeritageClause>;
@ -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<Statement>;
endOfFileToken: Token<SyntaxKind.EndOfFileToken>;

View File

@ -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) {
@ -597,7 +567,7 @@ namespace ts {
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.TypeAliasDeclaration:
errorNode = (<RealDeclaration>node).name;
errorNode = (<DeclarationBase>node).name;
break;
case SyntaxKind.ArrowFunction:
return getErrorSpanForArrowFunction(sourceFile, <ArrowFunction>node);
@ -1803,6 +1773,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 &&
@ -1823,7 +1824,7 @@ namespace ts {
case SyntaxKind.PropertyAssignment:
case SyntaxKind.PropertyAccessExpression:
// Name in member declaration or property name in property access
return (<RealDeclaration | PropertyAccessExpression>parent).name === node;
return (<DeclarationBase | PropertyAccessExpression>parent).name === node;
case SyntaxKind.QualifiedName:
// Name on right hand side of dot in a type query
if ((<QualifiedName>parent).right === node) {
@ -4102,7 +4103,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);
}