diff --git a/eslint/babel-eslint-parser/acorn-to-esprima.js b/eslint/babel-eslint-parser/acorn-to-esprima.js index da698ddb66..f6e5817440 100644 --- a/eslint/babel-eslint-parser/acorn-to-esprima.js +++ b/eslint/babel-eslint-parser/acorn-to-esprima.js @@ -1,17 +1,22 @@ -var tokTypes = require("babel").acorn.tokTypes; -var traverse = require("babel").traverse; -var t = require("babel").types; +var tokTypes = require("babel-core").acorn.tokTypes; +var traverse = require("babel-core").traverse; +var t = require("babel-core").types; exports.toToken = function (token) { var type = token.type; if (type === tokTypes.name) { token.type = "Identifier"; - } else if (type === tokTypes.semi || type === tokTypes.comma || type === tokTypes.parenL || type === tokTypes.parenR || type === tokTypes.braceL || type === tokTypes.braceR || type === tokTypes.slash || type === tokTypes.dot || type.isAssign) { + } else if (type === tokTypes.semi || type === tokTypes.comma || + type === tokTypes.parenL || type === tokTypes.parenR || + type === tokTypes.braceL || type === tokTypes.braceR || + type === tokTypes.slash || type === tokTypes.dot || + type === tokTypes.bracketL || type === tokTypes.bracketR || + type === tokTypes.ellipsis || type === tokTypes.arrow || + type === tokTypes.star || + type.isAssign) { token.type = "Punctuator"; - if (!token.value) { - token.value = type.type; - } + if (!token.value) token.value = type.type; } else if (type === tokTypes.jsxTagStart) { token.type = "Punctuator"; token.value = "<"; @@ -25,6 +30,9 @@ exports.toToken = function (token) { } else if (type === tokTypes.num) { token.type = "Numeric"; token.value = String(token.value); + } else if (type === tokTypes.string) { + token.type = "String"; + token.value = JSON.stringify(token.value); } return token; @@ -40,7 +48,7 @@ function isCompatTag(tagName) { var astTransformVisitor = { noScope: true, - enter: function (node, parent) { + exit: function (node, parent) { if (t.isSpreadProperty(node)) { node.type = "Property"; node.kind = "init"; @@ -53,15 +61,56 @@ var astTransformVisitor = { return node.argument; } - if (t.isImportBatchSpecifier(node)) { - // ImportBatchSpecifier => ImportNamespaceSpecifier - node.type = "ImportNamespaceSpecifier"; - node.id = node.name; + // modules + + if (t.isImportDeclaration(node)) { + delete node.isType; + } + + if (t.isExportDeclaration(node)) { + if (node.default) { + delete node.specifiers; + delete node.source; + node.type = "ExportDefaultDeclaration"; + if (node.declaration.type === "FunctionExpression") { + node.declaration.type = "FunctionDeclaration"; + } else if (node.declaration.type === "ClassExpression") { + node.declaration.type = "ClassDeclaration"; + } + } else if (t.isExportBatchSpecifier(node.specifiers[0])) { + node.type = "ExportAllDeclaration"; + delete node.specifiers; + delete node.declaration; + } else { + node.type = "ExportNamedDeclaration"; + } + delete node.default; + } + + if (t.isExportSpecifier(node)) { + node.local = node.id; + node.exported = node.name || node.id; + delete node.id; delete node.name; } - if (t.isAwaitExpression(node)) { - node.type = "YieldExpression"; + if (t.isImportSpecifier(node)) { + node.local = node.id || node.name; + if (node.default) { + node.type = "ImportDefaultSpecifier"; + } else { + node.imported = node.name || node.id; + } + delete node.id; + delete node.name; + delete node.default; + } + + if (t.isImportBatchSpecifier(node)) { + // ImportBatchSpecifier => ImportNamespaceSpecifier + node.type = "ImportNamespaceSpecifier"; + node.local = node.name; + delete node.name; } // classes @@ -76,10 +125,28 @@ var astTransformVisitor = { } // functions + + if (t.isFunction(node)) { + node.defaults = []; + node.params = node.params.map(function (param) { + if (t.isAssignmentPattern(param)) { + node.defaults.push(param.right); + return param.left; + } else { + node.defaults.push(null); + return param; + } + }); - if (t.isFunction(node) && node.async) { - node.generator = true; - node.async - false; + node.rest = null; + if (node.async) node.generator = true; + delete node.async; + } + + if (t.isAwaitExpression(node)) { + node.type = "YieldExpression"; + node.delegate = node.all; + delete node.all; } } }; diff --git a/eslint/babel-eslint-parser/index.js b/eslint/babel-eslint-parser/index.js index 3def57ec38..6a40a13643 100644 --- a/eslint/babel-eslint-parser/index.js +++ b/eslint/babel-eslint-parser/index.js @@ -1,10 +1,10 @@ var acornToEsprima = require("./acorn-to-esprima"); -var traverse = require("babel").traverse; +var traverse = require("babel-core").traverse; var assign = require("lodash.assign"); var Module = require("module"); -var acorn = require("babel").acorn; +var acorn = require("babel-core").acorn; var path = require("path"); -var t = require("babel").types; +var t = require("babel-core").types; var hasPatched = false; @@ -43,17 +43,6 @@ function monkeypatch() { opts.sourceType = "module"; return analyze.call(this, ast, opts) }; - - var eslint = require(eslintLoc); - var getScope = eslint.linter.getScope; - eslint.linter.getScope = function () { - var scope = getScope.apply(this, arguments); - if (scope.type === "global" && !scope.__patchedWithModuleVariables) { - scope.__patchedWithModuleVariables = true; - scope.variables.push.apply(scope.variables, scope.childScopes[0].variables); - } - return scope; - }; } exports.parse = function (code) { diff --git a/eslint/babel-eslint-parser/package.json b/eslint/babel-eslint-parser/package.json index e5f789bc2c..521d9cb7da 100644 --- a/eslint/babel-eslint-parser/package.json +++ b/eslint/babel-eslint-parser/package.json @@ -8,7 +8,7 @@ "url": "https://github.com/babel/babel-eslint.git" }, "dependencies": { - "babel": "^4.6.0", + "babel-core": "^4.6.0", "lodash.assign": "^3.0.0" }, "scripts": { diff --git a/eslint/babel-eslint-parser/test/babel-eslint.js b/eslint/babel-eslint-parser/test/babel-eslint.js index f8365c1844..ae9b5c5205 100644 --- a/eslint/babel-eslint-parser/test/babel-eslint.js +++ b/eslint/babel-eslint-parser/test/babel-eslint.js @@ -1,7 +1,6 @@ -var util = require("util"); -var espree = require("espree"); var babelEslint = require(".."); - +var espree = require("espree"); +var util = require("util"); function assertSameAST(a, b, path) { if (!path) { @@ -23,17 +22,19 @@ function assertSameAST(a, b, path) { keysB.sort(); while (true) { var keyA = keysA.shift(); + if (keyA && keyA[0] === "_") continue; // Exception: ignore "end" and "start" outside "loc" properties if ((keyA === "end" || keyA === "start") && path[path.length - 1] !== "loc") continue; + // Exception: ignore root "comments" property if (keyA === "comments" && path.length === 0) continue; var keyB = keysB.shift(); if (keyA === undefined && keyB === undefined) break; - if (keyA === undefined || keyA > keyB) error("first does not have key \"" + keyB + "\""); - if (keyB === undefined || keyA < keyB) error("second does not have key \"" + keyA + "\""); + if (keyA === undefined || keyA > keyB) error('first does not have key "' + keyB + '"'); + if (keyB === undefined || keyA < keyB) error('second does not have key "' + keyA + '"'); path.push(keyA); assertSameAST(a[keyA], b[keyB], path); path.pop(); @@ -44,21 +45,21 @@ function assertSameAST(a, b, path) { } function parseAndAssertSame(code) { - var esAST = espree.parse(code, { - ecmaFeatures: { - classes: true, - jsx: true - }, - tokens: true, - loc: true, - range: true - }); - var acornAST = babelEslint.parse(code); - assertSameAST(acornAST, esAST); + var esAST = espree.parse(code, { + ecmaFeatures: { + modules: true, + classes: true, + jsx: true + }, + tokens: true, + loc: true, + range: true + }); + var acornAST = babelEslint.parse(code); + assertSameAST(acornAST, esAST); } describe("acorn-to-esprima", function () { - it("simple expression", function () { parseAndAssertSame("a = 1"); }); @@ -87,4 +88,47 @@ describe("acorn-to-esprima", function () { parseAndAssertSame(""); }); + it("default import", function () { + parseAndAssertSame('import foo from "foo";'); + }); + + it("import specifier", function () { + parseAndAssertSame('import { foo } from "foo";'); + }); + + it("import specifier with name", function () { + parseAndAssertSame('import { foo as bar } from "foo";'); + }); + + it("import bare", function () { + parseAndAssertSame('import "foo";'); + }); + + it("export default class declaration", function () { + parseAndAssertSame("export default class Foo {}"); + }); + + it("export default class expression", function () { + parseAndAssertSame("export default class {};"); + }); + + it("export default function declaration", function () { + parseAndAssertSame("export default function Foo() {}"); + }); + + it("export default function expression", function () { + parseAndAssertSame("export default function () {};"); + }); + + it("export all", function () { + parseAndAssertSame('export * from "foo";'); + }); + + it("export named", function () { + parseAndAssertSame("export { foo };"); + }); + + it("export named alias", function () { + parseAndAssertSame("export { foo as bar };"); + }); });