Merge pull request babel/babel-eslint#177 from hzoo/use-acorn-to-esprima
use `acorn-to-esprima` package
This commit is contained in:
parent
b2405a9924
commit
4cdf59532d
@ -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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,10 +1,12 @@
|
|||||||
var acornToEsprima = require("./acorn-to-esprima");
|
var acornToEsprima = require("acorn-to-esprima");
|
||||||
var assign = require("lodash.assign");
|
var assign = require("lodash.assign");
|
||||||
var pick = require("lodash.pick");
|
var pick = require("lodash.pick");
|
||||||
var Module = require("module");
|
var Module = require("module");
|
||||||
var parse = require("babel-core").parse;
|
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
|
var parse = require("babel-core").parse;
|
||||||
var t = require("babel-core").types;
|
var t = require("babel-core").types;
|
||||||
|
var tt = require("babel-core").acorn.tokTypes;
|
||||||
|
var traverse = require("babel-core").traverse;
|
||||||
|
|
||||||
var estraverse;
|
var estraverse;
|
||||||
var hasPatched = false;
|
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) {
|
exports.parse = function (code) {
|
||||||
try {
|
try {
|
||||||
monkeypatch();
|
monkeypatch();
|
||||||
@ -413,6 +372,10 @@ exports.parse = function (code) {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return exports.parseNoPatch(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.parseNoPatch = function (code) {
|
||||||
var opts = {
|
var opts = {
|
||||||
locations: true,
|
locations: true,
|
||||||
ranges: true
|
ranges: true
|
||||||
@ -442,22 +405,15 @@ exports.parse = function (code) {
|
|||||||
tokens.pop();
|
tokens.pop();
|
||||||
|
|
||||||
// convert tokens
|
// convert tokens
|
||||||
ast.tokens = acornToEsprima.toTokens(tokens);
|
ast.tokens = acornToEsprima.toTokens(tokens, tt);
|
||||||
|
|
||||||
// add comments
|
// add comments
|
||||||
for (var i = 0; i < comments.length; i++) {
|
acornToEsprima.convertComments(comments);
|
||||||
var comment = comments[i];
|
|
||||||
if (comment.type === "CommentBlock") {
|
|
||||||
comment.type = "Block";
|
|
||||||
} else if (comment.type === "CommentLine") {
|
|
||||||
comment.type = "Line";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ast.comments = comments;
|
ast.comments = comments;
|
||||||
exports.attachComments(ast, comments, ast.tokens);
|
acornToEsprima.attachComments(ast, comments, ast.tokens);
|
||||||
|
|
||||||
// transform esprima and acorn divergent nodes
|
// transform esprima and acorn divergent nodes
|
||||||
acornToEsprima.toAST(ast);
|
acornToEsprima.toAST(ast, traverse);
|
||||||
|
|
||||||
return ast;
|
return ast;
|
||||||
};
|
}
|
||||||
@ -10,7 +10,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"babel-core": "^5.6.9",
|
"babel-core": "^5.6.9",
|
||||||
"lodash.assign": "^3.0.0",
|
"lodash.assign": "^3.0.0",
|
||||||
"lodash.pick": "^3.1.0"
|
"lodash.pick": "^3.1.0",
|
||||||
|
"acorn-to-esprima": "^1.0.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"bootstrap": "git submodule update --init && cd eslint && npm install",
|
"bootstrap": "git submodule update --init && cd eslint && npm install",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user