diff --git a/src/plugins/estree.js b/src/plugins/estree.js index 3d9f9477a7..e4b7041774 100644 --- a/src/plugins/estree.js +++ b/src/plugins/estree.js @@ -1,14 +1,18 @@ +// @flow + import { types as tt } from "../tokenizer/types"; +import type Parser from "../parser"; +import * as N from "../types"; -function isSimpleProperty(node) { - return node && +function isSimpleProperty(node: N.Node): boolean { + return node != null && node.type === "Property" && node.kind === "init" && node.method === false; } -export default (superClass) => class extends superClass { - estreeParseRegExpLiteral({ pattern, flags }) { +export default (superClass: Class): Class => class extends superClass { + estreeParseRegExpLiteral({ pattern, flags }: N.RegExpLiteral): N.Node { let regex = null; try { regex = new RegExp(pattern, flags); @@ -22,11 +26,11 @@ export default (superClass) => class extends superClass { return node; } - estreeParseLiteral(value) { + estreeParseLiteral(value: any): N.Node { return this.parseLiteral(value, "Literal"); } - directiveToStmt(directive) { + directiveToStmt(directive: N.Directive): N.ExpressionStatement { const directiveLiteral = directive.value; const stmt = this.startNodeAt(directive.start, directive.loc.start); @@ -46,15 +50,16 @@ export default (superClass) => class extends superClass { // Overrides // ================================== - checkDeclaration(node) { + checkDeclaration(node: N.Pattern): void { if (isSimpleProperty(node)) { + // $FlowFixMe this.checkDeclaration(node.value); } else { super.checkDeclaration(node); } } - checkGetterSetterParamCount(prop) { + checkGetterSetterParamCount(prop: N.ObjectMethod): void { const paramCount = prop.kind === "get" ? 0 : 1; if (prop.value.params.length !== paramCount) { const start = prop.start; @@ -66,7 +71,8 @@ export default (superClass) => class extends superClass { } } - checkLVal(expr, isBinding, checkClashes, ...args) { + checkLVal( + expr: N.Expression, isBinding: ?boolean, checkClashes: ?{ [key: string]: boolean }, ...args): void { switch (expr.type) { case "ObjectPattern": expr.properties.forEach((prop) => { @@ -83,7 +89,7 @@ export default (superClass) => class extends superClass { } } - checkPropClash(prop, propHash) { + checkPropClash(prop: N.ObjectMember, propHash: { [key: string]: boolean }): void { if (prop.computed || !isSimpleProperty(prop)) return; const key = prop.key; @@ -96,9 +102,9 @@ export default (superClass) => class extends superClass { } } - isStrictBody(node, isExpression) { + isStrictBody(node: { body: N.BlockStatement }, isExpression?: boolean): boolean { if (!isExpression && node.body.body.length > 0) { - for (const directive of (node.body.body: Array)) { + for (const directive of node.body.body) { if (directive.type === "ExpressionStatement" && directive.expression.type === "Literal") { if (directive.expression.value === "use strict") return true; } else { @@ -111,19 +117,18 @@ export default (superClass) => class extends superClass { return false; } - isValidDirective(stmt) { + isValidDirective(stmt: N.Statement): boolean { return stmt.type === "ExpressionStatement" && stmt.expression.type === "Literal" && typeof stmt.expression.value === "string" && (!stmt.expression.extra || !stmt.expression.extra.parenthesized); } - parseBlockBody(node, ...args) { + parseBlockBody(node: N.BlockStatementLike, ...args): void { super.parseBlockBody(node, ...args); - node.directives.reverse().forEach((directive) => { - node.body.unshift(this.directiveToStmt(directive)); - }); + const directiveStatements = node.directives.map((d) => this.directiveToStmt(d)); + node.body = directiveStatements.concat(node.body); delete node.directives; } @@ -134,7 +139,7 @@ export default (superClass) => class extends superClass { body[body.length - 1].type = "MethodDefinition"; } - parseExprAtom(...args) { + parseExprAtom(...args): N.Expression { switch (this.state.type) { case tt.regexp: return this.estreeParseRegExpLiteral(this.state.value); @@ -157,7 +162,7 @@ export default (superClass) => class extends superClass { } } - parseLiteral(...args) { + parseLiteral(...args): T { const node = super.parseLiteral(...args); node.raw = node.extra.raw; delete node.extra; @@ -165,17 +170,18 @@ export default (superClass) => class extends superClass { return node; } - parseMethod(node, ...args) { + parseMethod(node: N.MethodLike, ...args): N.MethodLike { let funcNode = this.startNode(); funcNode.kind = node.kind; // provide kind, so super method correctly sets state funcNode = super.parseMethod(funcNode, ...args); delete funcNode.kind; + // $FlowIgnore node.value = this.finishNode(funcNode, "FunctionExpression"); return node; } - parseObjectMethod(...args) { + parseObjectMethod(...args): ?N.ObjectMethod { const node = super.parseObjectMethod(...args); if (node) { @@ -186,7 +192,7 @@ export default (superClass) => class extends superClass { return node; } - parseObjectProperty(...args) { + parseObjectProperty(...args): ?N.ObjectProperty { const node = super.parseObjectProperty(...args); if (node) { @@ -197,14 +203,14 @@ export default (superClass) => class extends superClass { return node; } - toAssignable(node, isBinding, ...args) { + toAssignable(node: N.Node, isBinding: ?boolean, ...args): N.Node { if (isSimpleProperty(node)) { this.toAssignable(node.value, isBinding, ...args); return node; } else if (node.type === "ObjectExpression") { node.type = "ObjectPattern"; - for (const prop of (node.properties: Array)) { + for (const prop of node.properties) { if (prop.kind === "get" || prop.kind === "set") { this.raise(prop.key.start, "Object pattern can't contain getter or setter"); } else if (prop.method) {