diff --git a/eslint/babel-eslint-parser/acorn-to-esprima.js b/eslint/babel-eslint-parser/acorn-to-esprima.js deleted file mode 100644 index 729e47ed7f..0000000000 --- a/eslint/babel-eslint-parser/acorn-to-esprima.js +++ /dev/null @@ -1,258 +0,0 @@ -var traverse = require("babel-core").traverse; -var tt = require("babel-core").acorn.tokTypes; -var t = require("babel-core").types; - -exports.toToken = function (token) { - var type = token.type; - token.range = [token.start, token.end]; - - if (type === tt.name) { - token.type = "Identifier"; - } else if (type === tt.semi || type === tt.comma || - type === tt.parenL || type === tt.parenR || - type === tt.braceL || type === tt.braceR || - type === tt.slash || type === tt.dot || - type === tt.bracketL || type === tt.bracketR || - type === tt.ellipsis || type === tt.arrow || - type === tt.star || type === tt.incDec || - type === tt.colon || type === tt.question || - type === tt.template || type === tt.backQuote || - type === tt.dollarBraceL || type === tt.at || - type === tt.logicalOR || type === tt.logicalAND || - type === tt.bitwiseOR || type === tt.bitwiseXOR || - type === tt.bitwiseAND || type === tt.equality || - type === tt.relational || type === tt.bitShift || - type === tt.plusMin || type === tt.modulo || - type === tt.exponent || type === tt.prefix || - type === tt.doubleColon || - type.isAssign) { - token.type = "Punctuator"; - if (!token.value) token.value = type.label; - } else if (type === tt.jsxTagStart) { - token.type = "Punctuator"; - token.value = "<"; - } else if (type === tt.jsxTagEnd) { - token.type = "Punctuator"; - token.value = ">"; - } else if (type === tt.jsxName) { - token.type = "JSXIdentifier"; - } else if (type === tt.jsxText) { - token.type = "JSXText"; - } else if (type.keyword === "null") { - token.type = "Null"; - } else if (type.keyword === "false" || type.keyword === "true") { - token.type = "Boolean"; - } else if (type.keyword) { - token.type = "Keyword"; - } else if (type === tt.num) { - token.type = "Numeric"; - token.value = String(token.value); - } else if (type === tt.string) { - token.type = "String"; - token.value = JSON.stringify(token.value); - } else if (type === tt.regexp) { - token.type = "RegularExpression"; - token.regex = { - pattern: token.value.pattern, - flags: token.value.flags - }; - token.value = String(token.value.value); - } - - return token; -}; - -exports.toAST = function (ast) { - ast.sourceType = "module"; - ast.range = [ast.start, ast.end]; - traverse(ast, astTransformVisitor); -}; - -exports.toTokens = function (tokens) { - // transform tokens to type "Template" - convertTemplateType(tokens); - - return tokens.filter(function (token) { - return token.type !== "CommentLine" && token.type !== "CommentBlock"; - }).map(exports.toToken); -}; - -function convertTemplateType(tokens) { - var startingToken = 0; - var currentToken = 0; - // track use of {} - var numBraces = 0; - // track number of nested templates - var numBackQuotes = 0; - - function isBackQuote(token) { - return tokens[token].type === tt.backQuote; - } - - function isTemplateStarter(token) { - return isBackQuote(token) || - // only can be a template starter when in a template already - tokens[token].type === tt.braceR && numBackQuotes > 0; - } - - function isTemplateEnder(token) { - return isBackQuote(token) || - tokens[token].type === tt.dollarBraceL; - } - - // append the values between start and end - function createTemplateValue(start, end) { - var value = ""; - while (start <= end) { - if (tokens[start].value) { - value += tokens[start].value; - } else if (tokens[start].type !== tt.template) { - value += tokens[start].type.label; - } - start++; - } - return value; - } - - // create Template token - function replaceWithTemplateType(start, end) { - var templateToken = { - type: "Template", - value: createTemplateValue(start, end), - start: tokens[start].start, - end: tokens[end].end, - loc: { - start: tokens[start].loc.start, - end: tokens[end].loc.end - } - }; - - // put new token in place of old tokens - tokens.splice(start, end - start + 1, templateToken); - } - - function trackNumBraces(token) { - if (tokens[token].type === tt.braceL) { - numBraces++; - } else if (tokens[token].type === tt.braceR) { - numBraces--; - } - } - - while (startingToken < tokens.length) { - // template start: check if ` or } - if (isTemplateStarter(startingToken) && numBraces === 0) { - if (isBackQuote(startingToken)) { - numBackQuotes++; - } - - currentToken = startingToken + 1; - - // check if token after template start is "template" - if (currentToken >= tokens.length - 1 || tokens[currentToken].type !== tt.template) { - break; - } - - // template end: find ` or ${ - while (!isTemplateEnder(currentToken)) { - if (currentToken >= tokens.length - 1) { - break; - } - currentToken++; - } - - if (isBackQuote(currentToken)) { - numBackQuotes--; - } - // template start and end found: create new token - replaceWithTemplateType(startingToken, currentToken); - } else if (numBackQuotes > 0) { - trackNumBraces(startingToken); - } - startingToken++; - } -} - -var astTransformVisitor = { - noScope: true, - enter: function (node) { - node.range = [node.start, node.end]; - - // private var to track original node type - node._babelType = node.type; - }, - exit: function (node) { /* parent */ - if (this.isSpreadProperty()) { - node.type = "SpreadProperty"; - node.key = node.value = node.argument; - } - - // flow: prevent "no-undef" - // for "Component" in: "let x: React.Component" - if (this.isQualifiedTypeIdentifier()) { - delete node.id; - } - // for "b" in: "var a: { b: Foo }" - if (this.isObjectTypeProperty()) { - delete node.key; - } - // for "indexer" in: "var a: {[indexer: string]: number}" - if (this.isObjectTypeIndexer()) { - delete node.id; - } - // for "param" in: "var a: { func(param: Foo): Bar };" - if (this.isFunctionTypeParam()) { - delete node.name; - } - - // modules - - if (this.isImportDeclaration()) { - delete node.isType; - } - - if (this.isExportDeclaration()) { - var declar = this.get("declaration"); - if (declar.isClassExpression()) { - node.declaration.type = "ClassDeclaration"; - } else if (declar.isFunctionExpression()) { - node.declaration.type = "FunctionDeclaration"; - } - } - - // remove class property keys (or patch in escope) - if (this.isClassProperty()) { - delete node.key; - } - - // async function as generator - if (this.isFunction()) { - if (node.async) node.generator = true; - } - - // await transform to yield - if (this.isAwaitExpression()) { - node.type = "YieldExpression"; - node.delegate = node.all; - delete node.all; - } - - // template string range fixes - if (this.isTemplateLiteral()) { - node.quasis.forEach(function (q) { - q.range[0] -= 1; - if (q.tail) { - q.range[1] += 1; - } else { - q.range[1] += 2; - } - q.loc.start.column -= 1; - if (q.tail) { - q.loc.end.column += 1; - } else { - q.loc.end.column += 2; - } - }); - } - } -}; diff --git a/eslint/babel-eslint-parser/index.js b/eslint/babel-eslint-parser/index.js index fad1f83b7a..279fd25eb4 100644 --- a/eslint/babel-eslint-parser/index.js +++ b/eslint/babel-eslint-parser/index.js @@ -1,10 +1,12 @@ -var acornToEsprima = require("./acorn-to-esprima"); +var acornToEsprima = require("acorn-to-esprima"); var assign = require("lodash.assign"); var pick = require("lodash.pick"); var Module = require("module"); -var parse = require("babel-core").parse; var path = require("path"); +var parse = require("babel-core").parse; var t = require("babel-core").types; +var tt = require("babel-core").acorn.tokTypes; +var traverse = require("babel-core").traverse; var estraverse; var hasPatched = false; @@ -362,49 +364,6 @@ function monkeypatch() { }; } -exports.attachComments = function (ast, comments, tokens) { - if (comments.length) { - var firstComment = comments[0]; - var lastComment = comments[comments.length - 1]; - // fixup program start - if (!tokens.length) { - // if no tokens, the program starts at the end of the last comment - ast.start = lastComment.end; - ast.loc.start.line = lastComment.loc.end.line; - ast.loc.start.column = lastComment.loc.end.column; - } else if (firstComment.start < tokens[0].start) { - // if there are comments before the first token, the program starts at the first token - var token = tokens[0]; - ast.start = token.start; - ast.loc.start.line = token.loc.start.line; - ast.loc.start.column = token.loc.start.column; - - // estraverse do not put leading comments on first node when the comment - // appear before the first token - if (ast.body.length) { - var node = ast.body[0]; - node.leadingComments = []; - var firstTokenStart = token.start; - var len = comments.length; - for (var i = 0; i < len && comments[i].start < firstTokenStart; i++) { - node.leadingComments.push(comments[i]); - } - } - } - // fixup program end - if (tokens.length) { - var lastToken = tokens[tokens.length - 1]; - if (lastComment.end > lastToken.end) { - // If there is a comment after the last token, the program ends at the - // last token and not the comment - ast.end = lastToken.end; - ast.loc.end.line = lastToken.loc.end.line; - ast.loc.end.column = lastToken.loc.end.column; - } - } - } -}; - exports.parse = function (code) { try { monkeypatch(); @@ -413,6 +372,10 @@ exports.parse = function (code) { process.exit(1); } + return exports.parseNoPatch(code); +} + +exports.parseNoPatch = function (code) { var opts = { locations: true, ranges: true @@ -442,22 +405,15 @@ exports.parse = function (code) { tokens.pop(); // convert tokens - ast.tokens = acornToEsprima.toTokens(tokens); + ast.tokens = acornToEsprima.toTokens(tokens, tt); // add comments - for (var i = 0; i < comments.length; i++) { - var comment = comments[i]; - if (comment.type === "CommentBlock") { - comment.type = "Block"; - } else if (comment.type === "CommentLine") { - comment.type = "Line"; - } - } + acornToEsprima.convertComments(comments); ast.comments = comments; - exports.attachComments(ast, comments, ast.tokens); + acornToEsprima.attachComments(ast, comments, ast.tokens); // transform esprima and acorn divergent nodes - acornToEsprima.toAST(ast); + acornToEsprima.toAST(ast, traverse); return ast; -}; +} \ No newline at end of file diff --git a/eslint/babel-eslint-parser/package.json b/eslint/babel-eslint-parser/package.json index 57c13dead3..d477eb2529 100644 --- a/eslint/babel-eslint-parser/package.json +++ b/eslint/babel-eslint-parser/package.json @@ -10,7 +10,8 @@ "dependencies": { "babel-core": "^5.6.9", "lodash.assign": "^3.0.0", - "lodash.pick": "^3.1.0" + "lodash.pick": "^3.1.0", + "acorn-to-esprima": "^1.0.1" }, "scripts": { "bootstrap": "git submodule update --init && cd eslint && npm install",