// @flow import type { Token } from "./tokenizer"; import type { SourceLocation } from "./util/location"; /* * If making any changes to the AST, update: * - This repository: * - This file * - `ast` directory * - Babel repository: * - packages/babel-types/src/definitions * - packages/babel-generators/src/generators */ export type Comment = { type: "CommentBlock" | "CommentLine"; value: string; start: number; end: number; loc: SourceLocation; }; export interface NodeBase { start: number; end: number; loc: SourceLocation; range: [number, number]; leadingComments?: ?Array; trailingComments?: ?Array; innerComments?: ?Array; extra: { [key: string]: any }; } // Using a union type for `Node` makes type-checking too slow. // Instead, add an index signature to allow a Node to be treated as anything. export type Node = NodeBase & { [key: string]: any }; export type Expression = Node; export type Statement = Node; export type Pattern = | Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern; export type Declaration = | VariableDeclaration | ClassDeclaration | FunctionDeclaration; export type DeclarationBase = NodeBase; // TODO: Not in spec export type HasDecorators = NodeBase & { decorators?: $ReadOnlyArray; }; export type Identifier = PatternBase & { type: "Identifier"; name: string; __clone(): Identifier; }; export type PrivateName = NodeBase & { type: "PrivateName"; name: string; }; // Literals export type Literal = RegExpLiteral | NullLiteral | StringLiteral | BooleanLiteral | NumericLiteral; export type RegExpLiteral = NodeBase & { type: "RegExpLiteral"; pattern: string; flags: RegExp$flags; }; export type NullLiteral = NodeBase & { type: "NullLiteral"; } export type StringLiteral = NodeBase & { type: "StringLiteral"; value: string; }; export type BooleanLiteral = NodeBase & { type: "BooleanLiteral"; value: boolean; }; export type NumericLiteral = NodeBase & { type: "NumericLiteral"; value: number; }; // Programs export type BlockStatementLike = Program | BlockStatement; export type File = NodeBase & { type: "File"; program: Program; comments: $ReadOnlyArray; tokens: $ReadOnlyArray; }; export type Program = NodeBase & { type: "Program"; sourceType: "script" | "module"; body: Array; // TODO: $ReadOnlyArray directives: $ReadOnlyArray; // TODO: Not in spec }; // Functions export type Function = NormalFunction | ArrowFunctionExpression | ObjectMethod | ClassMethod; export type NormalFunction = FunctionDeclaration | FunctionExpression; export type FunctionBase = HasDecorators & { id: ?Identifier; params: $ReadOnlyArray; body: BlockStatement; generator: boolean; async: boolean; expression: boolean; // TODO: Not in spec typeParameters?: ?FlowTypeParameterDeclaration; // TODO: Not in spec returnType?: ?FlowTypeAnnotation; // TODO: Not in spec }; // Statements export type ExpressionStatement = NodeBase & { type: "ExpressionStatement"; expression: Expression; }; export type BlockStatement = NodeBase & { type: "BlockStatement"; body: Array; // TODO: $ReadOnlyArray directives: $ReadOnlyArray; }; export type EmptyStatement = NodeBase & { type: "EmptyStatement" }; export type DebuggerStatement = NodeBase & { type: "DebuggerStatement" }; export type WithStatement = NodeBase & { type: "WithStatement"; object: Expression; body: Statement; }; export type ReturnStatement = NodeBase & { type: "ReturnStatement"; argument: ?Expression; }; export type LabeledStatement = NodeBase & { type: "LabeledStatement"; label: Identifier; body: Statement; }; export type BreakStatement = NodeBase & { type: "BreakStatement"; label: ?Identifier; }; export type ContinueStatement = NodeBase & { type: "ContinueStatement"; label: ?Identifier; }; // Choice export type IfStatement = NodeBase & { type: "IfStatement"; test: Expression; consequent: Statement; alternate: ?Statement; }; export type SwitchStatement = NodeBase & { type: "SwitchStatement"; discriminant: Expression; cases: $ReadOnlyArray; }; export type SwitchCase = NodeBase & { type: "SwitchCase"; test: ?Expression; consequent: $ReadOnlyArray; }; // Exceptions export type ThrowStatement = NodeBase & { type: "ThrowStatement"; argument: Expression; }; export type TryStatement = NodeBase & { type: "TryStatement"; block: BlockStatement; handler: CatchClause | null; finalizer: BlockStatement | null; guardedHandlers: $ReadOnlyArray; // TODO: Not in spec }; export type CatchClause = NodeBase & { type: "CatchClause"; param: Pattern; body: BlockStatement; }; // Loops export type WhileStatement = NodeBase & { type: "WhileStatement"; test: Expression; body: Statement; }; export type DoWhileStatement = NodeBase & { type: "DoWhileStatement"; body: Statement; test: Expression; }; export type ForLike = ForStatement | ForInOf; export type ForStatement = NodeBase & { type: "ForStatement"; init: ?(VariableDeclaration | Expression); test: ?Expression; update: ?Expression; body: Statement; }; export type ForInOf = ForInStatement | ForOfStatement; export type ForInOfBase = NodeBase & { type: "ForInStatement"; left: VariableDeclaration | Expression; right: Expression; body: Statement; }; export type ForInStatement = ForInOfBase & { type: "ForInStatement"; // TODO: Shouldn't be here, but have to declare it because it's assigned to a ForInOf unconditionally. await: boolean; }; export type ForOfStatement = ForInOfBase & { type: "ForOfStatement"; await: boolean; }; // Declarations export type OptFunctionDeclaration = FunctionBase & DeclarationBase & HasDecorators & { type: "FunctionDeclaration"; }; export type FunctionDeclaration = OptFunctionDeclaration & { id: Identifier; } export type VariableDeclaration = DeclarationBase & HasDecorators & { type: "VariableDeclaration"; declarations: $ReadOnlyArray; kind: "var" | "let" | "const"; }; export type VariableDeclarator = NodeBase & { type: "VariableDeclarator"; id: Pattern; init: ?Expression; }; // Misc export type Decorator = NodeBase & { type: "Decorator"; expression: Expression; }; export type Directive = NodeBase & { type: "Directive"; value: DirectiveLiteral; }; export type DirectiveLiteral = StringLiteral & { type: "DirectiveLiteral" }; // Expressions export type Super = NodeBase & { type: "Super" }; export type Import = NodeBase & { type: "Import" }; export type ThisExpression = NodeBase & { type: "ThisExpression" }; export type ArrowFunctionExpression = FunctionBase & { type: "ArrowFunctionExpression"; body: BlockStatement | Expression; }; export type YieldExpression = NodeBase & { type: "YieldExpression"; argument: ?Expression; delegate: boolean; }; export type AwaitExpression = NodeBase & { type: "AwaitExpression"; argument: ?Expression; }; export type ArrayExpression = NodeBase & { type: "ArrayExpression"; elements: $ReadOnlyArray; }; export type ObjectExpression = NodeBase & { type: "ObjectExpression"; properties: $ReadOnlyArray; }; export type ObjectOrClassMember = ClassMethod | ClassProperty | ClassPrivateProperty | ObjectMember; export type ObjectMember = ObjectProperty | ObjectMethod; export type ObjectMemberBase = NodeBase & { key: Expression; computed: boolean; value: Expression; decorators: $ReadOnlyArray; kind?: "get" | "set" | "method"; method: boolean; // TODO: Not in spec variance?: ?FlowVariance; // TODO: Not in spec }; export type ObjectProperty = ObjectMemberBase & { type: "ObjectProperty"; shorthand: boolean; }; export type ObjectMethod = ObjectMemberBase & MethodBase & { type: "ObjectMethod"; kind: "get" | "set" | "method"; // Never "constructor" }; export type FunctionExpression = MethodBase & { kind?: void; // never set type: "FunctionExpression"; }; // Unary operations export type UnaryExpression = NodeBase & { type: "UnaryExpression"; operator: UnaryOperator; prefix: boolean; argument: Expression; }; export type UnaryOperator = "-" | "+" | "!" | "~" | "typeof" | "void" | "delete"; export type UpdateExpression = NodeBase & { type: "UpdateExpression"; operator: UpdateOperator; argument: Expression; prefix: boolean; }; export type UpdateOperator = "++" | "--"; // Binary operations export type BinaryExpression = NodeBase & { type: "BinaryExpression"; operator: BinaryOperator; left: Expression; right: Expression; }; export type BinaryOperator = | "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "|" | "^" | "&" | "in" | "instanceof"; export type AssignmentExpression = NodeBase & { type: "AssignmentExpression"; operator: AssignmentOperator; left: Pattern | Expression; right: Expression; }; export type AssignmentOperator = | "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "<<=" | ">>=" | ">>>=" | "|=" | "^=" | "&="; export type LogicalExpression = NodeBase & { type: "LogicalExpression"; operator: LogicalOperator; left: Expression; right: Expression; }; export type LogicalOperator = "||" | "&&"; export type SpreadElement = NodeBase & { type: "SpreadElement"; argument: Expression; }; export type MemberExpression = NodeBase & { type: "MemberExpression"; object: Expression | Super; property: Expression; computed: boolean; } export type BindExpression = NodeBase & { type: "BindExpression"; object: $ReadOnlyArray; callee: $ReadOnlyArray; }; export type ConditionalExpression = NodeBase & { type: "ConditionalExpression"; test: Expression; alternate: Expression; consequent: Expression; }; export type CallOrNewBase = NodeBase & { callee: Expression | Super | Import; arguments: Array; // TODO: $ReadOnlyArray }; export type CallExpression = CallOrNewBase & { type: "CallExpression"; }; export type NewExpression = CallOrNewBase & { type: "NewExpression"; }; export type SequenceExpression = NodeBase & { type: "SequenceExpression"; expressions: $ReadOnlyArray; }; // Template Literals export type TemplateLiteral = NodeBase & { type: "TemplateLiteral"; quasis: $ReadOnlyArray; expressions: $ReadOnlyArray; }; export type TaggedTmplateExpression = NodeBase & { type: "TaggedTemplateExpression"; tag: Expression; quasi: TemplateLiteral; }; export type TemplateElement = NodeBase & { type: "TemplateElement"; tail: boolean; value: { cooked: string; raw: string; } }; // Patterns export type PatternBase = HasDecorators & { // Flow only: optional?: true; typeAnnotation?: ?FlowTypeAnnotation; }; export type AssignmentProperty = ObjectProperty & { value: Pattern; }; export type ObjectPattern = PatternBase & { type: "ObjectPattern"; properties: $ReadOnlyArray; }; export type ArrayPattern = PatternBase & { type: "ArrayPattern"; elements: $ReadOnlyArray; }; export type RestElement = PatternBase & { type: "RestElement"; argument: Pattern; }; export type AssignmentPattern = PatternBase & { type: "AssignmentPattern"; left: Pattern; right: Expression; }; // Classes export type Class = ClassDeclaration | ClassExpression; export type ClassBase = HasDecorators & { id: ?Identifier; superClass: ?Expression; body: ClassBody; decorators: $ReadOnlyArray; typeParameters?: ?FlowTypeParameterDeclaration; // TODO: Not in spec superTypeParameters?: ?FlowTypeParameterInstantiation; // TODO: Not in spec implements?: $ReadOnlyArray; }; export type ClassBody = NodeBase & { type: "ClassBody"; body: Array; // TODO: $ReadOnlyArray }; export type ClassMemberBase = NodeBase & HasDecorators & { static: boolean; computed: boolean; // TypeScript only: access?: ?Accessibility; abstract?: ?true; optional?: ?true; } export type Accessibility = "public" | "protected" | "private"; export type ClassMember = ClassMethod | ClassProperty | ClassPrivateProperty; export type MethodLike = ObjectMethod | FunctionExpression | ClassMethod; export type MethodBase = FunctionBase & { +kind?: MethodKind; }; export type MethodKind = "constructor" | "method" | "get" | "set"; export type ClassMethod = MethodBase & ClassMemberBase & { type: "ClassMethod"; key: Expression; kind: MethodKind; static: boolean; decorators: $ReadOnlyArray; variance?: ?FlowVariance; // TODO: Not in spec }; export type ClassProperty = ClassMemberBase & { type: "ClassProperty"; key: Identifier; value: ?Expression; // TODO: Not in spec that this is nullable. typeAnnotation?: ?FlowTypeAnnotation; // TODO: Not in spec variance?: ?FlowVariance; // TODO: Not in spec // TypeScript only: (TODO: Not in spec) readonly?: true; }; export type ClassPrivateProperty = NodeBase & { type: "ClassPrivateProperty"; key: Identifier; value: ?Expression; // TODO: Not in spec that this is nullable. }; export type OptClassDeclaration = ClassBase & DeclarationBase & HasDecorators & { type: "ClassDeclaration"; // TypeScript only abstract?: ?true; }; export type ClassDeclaration = OptClassDeclaration & { id: Identifier; }; export type ClassExpression = ClassBase & { type: "ClassExpression" }; export type MetaProperty = NodeBase & { type: "MetaProperty"; meta: Identifier; property: Identifier; }; // Modules export type ModuleDeclaration = AnyImport | AnyExport; export type AnyImport = ImportDeclaration; export type AnyExport = | ExportNamedDeclaration | ExportDefaultDeclaration | ExportAllDeclaration; export type ModuleSpecifier = NodeBase & { local: Identifier; }; // Imports export type ImportDeclaration = NodeBase & { type: "ImportDeclaration"; // TODO: $ReadOnlyArray specifiers: Array; source: Literal; importKind?: "type" | "typeof" | "value"; // TODO: Not in spec }; export type ImportSpecifier = ModuleSpecifier & { type: "ImportSpecifier"; imported: Identifier; }; export type ImportDefaultSpecifier = ModuleSpecifier & { type: "ImportDefaultSpecifier" }; export type ImportNamespaceSpecifier = ModuleSpecifier & { type: "ImportNamespaceSpecifier" }; // Exports export type ExportNamedDeclaration = NodeBase & { type: "ExportNamedDeclaration"; declaration: ?Declaration; specifiers: $ReadOnlyArray; source: ?Literal; exportKind?: "type" | "value"; // TODO: Not in spec }; export type ExportSpecifier = NodeBase & { type: "ExportSpecifier"; exported: Identifier; }; export type ExportDefaultDeclaration = NodeBase & { type: "ExportDefaultDeclaration"; declaration: OptFunctionDeclaration | OptClassDeclaration | Expression; }; export type ExportAllDeclaration = NodeBase & { type: "ExportAllDeclaration"; source: Literal; }; // JSX (TODO: Not in spec) export type JSXIdentifier = Node; export type JSXNamespacedName = Node; export type JSXMemberExpression = Node; export type JSXEmptyExpression = Node; export type JSXSpreadChild = Node; export type JSXExpressionContainer = Node; export type JSXAttribute = Node; export type JSXOpeningElement = Node; export type JSXClosingElement = Node; export type JSXElement = Node; // Flow (TODO: Not in spec) export type FlowType = Node; export type FlowPredicate = Node; export type FlowDeclare = Node; export type FlowDeclareClass = Node; export type FlowDeclareExportDeclaration = Node; export type FlowDeclareFunction = Node; export type FlowDeclareVariable = Node; export type FlowDeclareModule = Node; export type FlowDeclareModuleExports = Node; export type FlowDeclareTypeAlias = Node; export type FlowDeclareInterface = Node; export type FlowInterface = Node; export type FlowInterfaceExtends = Node; export type FlowTypeAlias = Node; export type FlowTypeParameter = Node; export type FlowTypeParameterDeclaration = Node; export type FlowTypeParameterInstantiation = Node; export type FlowObjectTypeIndexer = Node; export type FlowFunctionTypeAnnotation = Node; export type FlowObjectTypeProperty = Node; export type FlowObjectTypeSpreadProperty = Node; export type FlowObjectTypeCallProperty = Node; export type FlowObjectTypeAnnotation = Node; export type FlowQualifiedTypeIdentifier = Node; export type FlowGenericTypeAnnotation = Node; export type FlowTypeofTypeAnnotation = Node; export type FlowTupleTypeAnnotation = Node; export type FlowFunctionTypeParam = Node; export type FlowTypeAnnotation = Node; export type FlowVariance = Node; export type FlowClassImplements = Node;