parent
dce22ce5f6
commit
511862c4ee
@ -0,0 +1,57 @@
|
||||
// comment fixes
|
||||
module.exports = 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;
|
||||
|
||||
if (ast.leadingComments === null && ast.innerComments.length) {
|
||||
ast.leadingComments = ast.innerComments;
|
||||
}
|
||||
} 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.range[1] = lastToken.end;
|
||||
ast.loc.end.line = lastToken.loc.end.line;
|
||||
ast.loc.end.column = lastToken.loc.end.column;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!tokens.length) {
|
||||
ast.loc.start.line = 1;
|
||||
ast.loc.end.line = 1;
|
||||
}
|
||||
}
|
||||
if (ast.body && ast.body.length > 0) {
|
||||
ast.loc.start.line = ast.body[0].loc.start.line;
|
||||
ast.range[0] = ast.body[0].start;
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,93 @@
|
||||
module.exports = function (tokens, tt) {
|
||||
var startingToken = 0;
|
||||
var currentToken = 0;
|
||||
var numBraces = 0; // track use of {}
|
||||
var numBackQuotes = 0; // track number of nested templates
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
20
eslint/babel-eslint-parser/babylon-to-espree/index.js
Normal file
20
eslint/babel-eslint-parser/babylon-to-espree/index.js
Normal file
@ -0,0 +1,20 @@
|
||||
exports.attachComments = require("./attachComments");
|
||||
|
||||
exports.toTokens = require("./toTokens");
|
||||
exports.toAST = require("./toAST");
|
||||
|
||||
exports.convertComments = function (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";
|
||||
}
|
||||
// sometimes comments don't get ranges computed,
|
||||
// even with options.ranges === true
|
||||
if (!comment.range) {
|
||||
comment.range = [comment.start, comment.end];
|
||||
}
|
||||
}
|
||||
}
|
||||
272
eslint/babel-eslint-parser/babylon-to-espree/toAST.js
Normal file
272
eslint/babel-eslint-parser/babylon-to-espree/toAST.js
Normal file
@ -0,0 +1,272 @@
|
||||
var source;
|
||||
|
||||
module.exports = function (ast, traverse, code) {
|
||||
source = code;
|
||||
ast.range = [ast.start, ast.end];
|
||||
traverse(ast, astTransformVisitor);
|
||||
};
|
||||
|
||||
function changeToLiteral(node) {
|
||||
node.type = "Literal";
|
||||
if (!node.raw) {
|
||||
if (node.extra && node.extra.raw) {
|
||||
node.raw = node.extra.raw;
|
||||
} else {
|
||||
node.raw = source.slice(node.start, node.end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var astTransformVisitor = {
|
||||
noScope: true,
|
||||
enter: function (path) {
|
||||
var node = path.node;
|
||||
|
||||
node.range = [node.start, node.end];
|
||||
|
||||
// private var to track original node type
|
||||
node._babelType = node.type;
|
||||
|
||||
if (node.innerComments) {
|
||||
node.trailingComments = node.innerComments;
|
||||
delete node.innerComments;
|
||||
}
|
||||
|
||||
if (node.trailingComments) {
|
||||
for (var i = 0; i < node.trailingComments.length; i++) {
|
||||
var comment = node.trailingComments[i];
|
||||
if (comment.type === "CommentLine") {
|
||||
comment.type = "Line";
|
||||
} else if (comment.type === "CommentBlock") {
|
||||
comment.type = "Block";
|
||||
}
|
||||
comment.range = [comment.start, comment.end];
|
||||
}
|
||||
}
|
||||
|
||||
if (node.leadingComments) {
|
||||
for (var i = 0; i < node.leadingComments.length; i++) {
|
||||
var comment = node.leadingComments[i];
|
||||
if (comment.type === "CommentLine") {
|
||||
comment.type = "Line";
|
||||
} else if (comment.type === "CommentBlock") {
|
||||
comment.type = "Block";
|
||||
}
|
||||
comment.range = [comment.start, comment.end];
|
||||
}
|
||||
}
|
||||
|
||||
// make '_paths' non-enumerable (babel-eslint #200)
|
||||
Object.defineProperty(node, "_paths", { value: node._paths, writable: true });
|
||||
},
|
||||
exit: function (path) {
|
||||
var node = path.node;
|
||||
|
||||
[
|
||||
fixDirectives,
|
||||
].forEach(function (fixer) {
|
||||
fixer(path);
|
||||
});
|
||||
|
||||
if (path.isJSXText()) {
|
||||
node.type = "Literal";
|
||||
node.raw = node.value;
|
||||
}
|
||||
|
||||
if (path.isNumericLiteral() ||
|
||||
path.isStringLiteral()) {
|
||||
changeToLiteral(node);
|
||||
}
|
||||
|
||||
if (path.isBooleanLiteral()) {
|
||||
node.type = "Literal";
|
||||
node.raw = String(node.value);
|
||||
}
|
||||
|
||||
if (path.isNullLiteral()) {
|
||||
node.type = "Literal";
|
||||
node.raw = "null";
|
||||
node.value = null;
|
||||
}
|
||||
|
||||
if (path.isRegExpLiteral()) {
|
||||
node.type = "Literal";
|
||||
node.raw = node.extra.raw;
|
||||
node.value = {};
|
||||
node.regex = {
|
||||
pattern: node.pattern,
|
||||
flags: node.flags
|
||||
};
|
||||
delete node.extra;
|
||||
delete node.pattern;
|
||||
delete node.flags;
|
||||
}
|
||||
|
||||
if (path.isObjectProperty()) {
|
||||
node.type = "Property";
|
||||
node.kind = "init";
|
||||
}
|
||||
|
||||
if (path.isClassMethod() || path.isObjectMethod()) {
|
||||
var code = source.slice(node.key.end, node.body.start);
|
||||
var offset = code.indexOf("(");
|
||||
|
||||
node.value = {
|
||||
type: "FunctionExpression",
|
||||
id: node.id,
|
||||
params: node.params,
|
||||
body: node.body,
|
||||
async: node.async,
|
||||
generator: node.generator,
|
||||
expression: node.expression,
|
||||
defaults: [], // basic support - TODO: remove (old esprima)
|
||||
loc: {
|
||||
start: {
|
||||
line: node.key.loc.start.line,
|
||||
column: node.key.loc.end.column + offset // a[() {]
|
||||
},
|
||||
end: node.body.loc.end
|
||||
}
|
||||
};
|
||||
// [asdf]() {
|
||||
node.value.range = [node.key.end + offset, node.body.end];
|
||||
|
||||
node.value.start = node.value.range && node.value.range[0] || node.value.loc.start.column;
|
||||
node.value.end = node.value.range && node.value.range[1] || node.value.loc.end.column;
|
||||
|
||||
if (node.returnType) {
|
||||
node.value.returnType = node.returnType;
|
||||
}
|
||||
|
||||
if (node.typeParameters) {
|
||||
node.value.typeParameters = node.typeParameters;
|
||||
}
|
||||
|
||||
if (path.isClassMethod()) {
|
||||
node.type = "MethodDefinition";
|
||||
}
|
||||
|
||||
if (path.isObjectMethod()) {
|
||||
node.type = "Property";
|
||||
if (node.kind === "method") {
|
||||
node.kind = "init";
|
||||
}
|
||||
}
|
||||
|
||||
delete node.body;
|
||||
delete node.id;
|
||||
delete node.async;
|
||||
delete node.generator;
|
||||
delete node.expression;
|
||||
delete node.params;
|
||||
delete node.returnType;
|
||||
delete node.typeParameters;
|
||||
}
|
||||
|
||||
if (path.isRestProperty() || path.isSpreadProperty()) {
|
||||
node.type = "Experimental" + node.type;
|
||||
}
|
||||
|
||||
// flow: prevent "no-undef"
|
||||
// for "Component" in: "let x: React.Component"
|
||||
if (path.isQualifiedTypeIdentifier()) {
|
||||
delete node.id;
|
||||
}
|
||||
// for "b" in: "var a: { b: Foo }"
|
||||
if (path.isObjectTypeProperty()) {
|
||||
delete node.key;
|
||||
}
|
||||
// for "indexer" in: "var a: {[indexer: string]: number}"
|
||||
if (path.isObjectTypeIndexer()) {
|
||||
delete node.id;
|
||||
}
|
||||
// for "param" in: "var a: { func(param: Foo): Bar };"
|
||||
if (path.isFunctionTypeParam()) {
|
||||
delete node.name;
|
||||
}
|
||||
|
||||
// modules
|
||||
|
||||
if (path.isImportDeclaration()) {
|
||||
delete node.isType;
|
||||
}
|
||||
|
||||
if (path.isExportDeclaration()) {
|
||||
var declar = path.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 (path.isClassProperty()) {
|
||||
delete node.key;
|
||||
}
|
||||
|
||||
// async function as generator
|
||||
if (path.isFunction()) {
|
||||
if (node.async) node.generator = true;
|
||||
}
|
||||
|
||||
// TODO: remove (old esprima)
|
||||
if (path.isFunction()) {
|
||||
if (!node.defaults) {
|
||||
node.defaults = [];
|
||||
}
|
||||
}
|
||||
|
||||
// await transform to yield
|
||||
if (path.isAwaitExpression()) {
|
||||
node.type = "YieldExpression";
|
||||
node.delegate = node.all;
|
||||
delete node.all;
|
||||
}
|
||||
|
||||
// template string range fixes
|
||||
if (path.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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function fixDirectives (path) {
|
||||
if (!(path.isProgram() || path.isFunction())) return;
|
||||
|
||||
var node = path.node;
|
||||
var directivesContainer = node;
|
||||
var body = node.body;
|
||||
|
||||
if (node.type !== "Program") {
|
||||
directivesContainer = body;
|
||||
body = body.body;
|
||||
}
|
||||
|
||||
if (!directivesContainer.directives) return;
|
||||
|
||||
directivesContainer.directives.reverse().forEach(function (directive) {
|
||||
directive.type = "ExpressionStatement";
|
||||
directive.expression = directive.value;
|
||||
delete directive.value;
|
||||
directive.expression.type = "Literal";
|
||||
changeToLiteral(directive.expression);
|
||||
body.unshift(directive);
|
||||
});
|
||||
delete directivesContainer.directives;
|
||||
}
|
||||
// fixDirectives
|
||||
60
eslint/babel-eslint-parser/babylon-to-espree/toToken.js
Normal file
60
eslint/babel-eslint-parser/babylon-to-espree/toToken.js
Normal file
@ -0,0 +1,60 @@
|
||||
module.exports = function (token, tt, source) {
|
||||
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 = source.slice(token.start, token.end);
|
||||
} else if (type === tt.string) {
|
||||
token.type = "String";
|
||||
token.value = source.slice(token.start, token.end);
|
||||
} else if (type === tt.regexp) {
|
||||
token.type = "RegularExpression";
|
||||
var value = token.value;
|
||||
token.regex = {
|
||||
pattern: value.pattern,
|
||||
flags: value.flags
|
||||
};
|
||||
token.value = "/" + value.pattern + "/" + value.flags;
|
||||
}
|
||||
|
||||
return token;
|
||||
};
|
||||
16
eslint/babel-eslint-parser/babylon-to-espree/toTokens.js
Normal file
16
eslint/babel-eslint-parser/babylon-to-espree/toTokens.js
Normal file
@ -0,0 +1,16 @@
|
||||
var convertTemplateType = require("./convertTemplateType");
|
||||
var toToken = require("./toToken");
|
||||
|
||||
module.exports = function (tokens, tt, code) {
|
||||
// transform tokens to type "Template"
|
||||
convertTemplateType(tokens, tt);
|
||||
var transformedTokens = tokens.filter(function (token) {
|
||||
return token.type !== "CommentLine" && token.type !== "CommentBlock";
|
||||
});
|
||||
|
||||
for (var i = 0, l = transformedTokens.length; i < l; i++) {
|
||||
transformedTokens[i] = toToken(transformedTokens[i], tt, code);
|
||||
}
|
||||
|
||||
return transformedTokens;
|
||||
};
|
||||
@ -1,4 +1,4 @@
|
||||
var acornToEsprima = require("acorn-to-esprima");
|
||||
var babylonToEspree = require("./babylon-to-espree");
|
||||
var assign = require("lodash.assign");
|
||||
var pick = require("lodash.pick");
|
||||
var Module = require("module");
|
||||
@ -380,7 +380,9 @@ function monkeypatch() {
|
||||
};
|
||||
}
|
||||
|
||||
exports.parse = function (code) {
|
||||
exports.parse = function (code, options) {
|
||||
options = options || {};
|
||||
|
||||
try {
|
||||
monkeypatch();
|
||||
} catch (err) {
|
||||
@ -388,12 +390,12 @@ exports.parse = function (code) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return exports.parseNoPatch(code);
|
||||
return exports.parseNoPatch(code, options);
|
||||
}
|
||||
|
||||
exports.parseNoPatch = function (code) {
|
||||
exports.parseNoPatch = function (code, options) {
|
||||
var opts = {
|
||||
sourceType: "module",
|
||||
sourceType: options.sourceType || "module",
|
||||
strictMode: true,
|
||||
allowImportExportEverywhere: false, // consistent with espree
|
||||
allowReturnOutsideFunction: true,
|
||||
@ -422,7 +424,7 @@ exports.parseNoPatch = function (code) {
|
||||
} catch (err) {
|
||||
if (err instanceof SyntaxError) {
|
||||
err.lineNumber = err.loc.line;
|
||||
err.column = err.loc.column;
|
||||
err.column = err.loc.column + 1;
|
||||
|
||||
// remove trailing "(LINE:COLUMN)" acorn message and add in esprima syntax error message start
|
||||
err.message = "Line " + err.lineNumber + ": " + err.message.replace(/ \((\d+):(\d+)\)$/, "");
|
||||
@ -437,27 +439,27 @@ exports.parseNoPatch = function (code) {
|
||||
ast.tokens.pop();
|
||||
|
||||
// convert tokens
|
||||
ast.tokens = acornToEsprima.toTokens(ast.tokens, tt, code);
|
||||
ast.tokens = babylonToEspree.toTokens(ast.tokens, tt, code);
|
||||
|
||||
// add comments
|
||||
acornToEsprima.convertComments(ast.comments);
|
||||
babylonToEspree.convertComments(ast.comments);
|
||||
|
||||
// transform esprima and acorn divergent nodes
|
||||
acornToEsprima.toAST(ast, traverse, code);
|
||||
babylonToEspree.toAST(ast, traverse, code);
|
||||
|
||||
// ast.program.tokens = ast.tokens;
|
||||
// ast.program.comments = ast.comments;
|
||||
// ast = ast.program;
|
||||
|
||||
// remove File
|
||||
ast.type = 'Program';
|
||||
ast.type = "Program";
|
||||
ast.sourceType = ast.program.sourceType;
|
||||
ast.directives = ast.program.directives;
|
||||
ast.body = ast.program.body;
|
||||
delete ast.program;
|
||||
delete ast._paths;
|
||||
|
||||
acornToEsprima.attachComments(ast, ast.comments, ast.tokens);
|
||||
babylonToEspree.attachComments(ast, ast.comments, ast.tokens);
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
{
|
||||
"name": "babel-eslint",
|
||||
"version": "5.0.0",
|
||||
"description": "",
|
||||
"description": "Custom parser for ESLint",
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
"index.js"
|
||||
"index.js",
|
||||
"babylon-to-espree"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/babel/babel-eslint.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn-to-esprima": "^2.0.4",
|
||||
"babel-traverse": "^6.0.20",
|
||||
"babel-types": "^6.0.19",
|
||||
"babylon": "^6.0.18",
|
||||
@ -22,7 +22,8 @@
|
||||
"bootstrap": "git submodule update --init && cd eslint && npm install",
|
||||
"eslint": "cd eslint && mocha -c tests/lib/rules/*.js -r ../eslint-tester.js",
|
||||
"test": "mocha",
|
||||
"lint": "./node_modules/eslint/bin/eslint.js ./test index.js acorn-to-esprima.js",
|
||||
"lint": "./node_modules/eslint/bin/eslint.js index.js babylon-to-espree test",
|
||||
"fix": "./node_modules/eslint/bin/eslint.js index.js babylon-to-espree test --fix",
|
||||
"preversion": "npm test"
|
||||
},
|
||||
"author": "Sebastian McKenzie <sebmck@gmail.com>",
|
||||
@ -32,8 +33,8 @@
|
||||
},
|
||||
"homepage": "https://github.com/babel/babel-eslint",
|
||||
"devDependencies": {
|
||||
"eslint": "^1.10.2",
|
||||
"espree": "^2.2.5",
|
||||
"eslint": "^2.0.0",
|
||||
"espree": "^3.0.0",
|
||||
"mocha": "^2.3.3"
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,49 +32,49 @@ function assertImplementsAST(target, source, path) {
|
||||
}
|
||||
}
|
||||
|
||||
function lookup(obj, keypath, backwardsDepth) {
|
||||
if (!keypath) { return obj; }
|
||||
|
||||
return keypath.split(".").slice(0, -1 * backwardsDepth)
|
||||
.reduce(function (base, segment) { return base && base[segment], obj });
|
||||
}
|
||||
|
||||
function parseAndAssertSame(code) {
|
||||
var esAST = espree.parse(code, {
|
||||
ecmaFeatures: {
|
||||
arrowFunctions: true,
|
||||
binaryLiterals: true,
|
||||
blockBindings: true,
|
||||
classes: true,
|
||||
defaultParams: true,
|
||||
destructuring: true,
|
||||
forOf: true,
|
||||
generators: true,
|
||||
modules: true,
|
||||
objectLiteralComputedProperties: true,
|
||||
objectLiteralDuplicateProperties: true,
|
||||
objectLiteralShorthandMethods: true,
|
||||
objectLiteralShorthandProperties: true,
|
||||
octalLiterals: true,
|
||||
regexUFlag: true,
|
||||
regexYFlag: true,
|
||||
restParams: true,
|
||||
spread: true,
|
||||
superInFunctions: true,
|
||||
templateStrings: true,
|
||||
unicodeCodePointEscapes: true,
|
||||
globalReturn: true,
|
||||
// enable JSX parsing
|
||||
jsx: true,
|
||||
experimentalObjectRestSpread: true,
|
||||
// enable return in global scope
|
||||
globalReturn: true,
|
||||
// enable implied strict mode (if ecmaVersion >= 5)
|
||||
impliedStrict: true,
|
||||
// allow experimental object rest/spread
|
||||
experimentalObjectRestSpread: true
|
||||
},
|
||||
tokens: true,
|
||||
loc: true,
|
||||
range: true,
|
||||
comment: true,
|
||||
attachComment: true
|
||||
attachComment: true,
|
||||
ecmaVersion: 6,
|
||||
sourceType: "module"
|
||||
});
|
||||
var babylonAST = babelEslint.parse(code);
|
||||
try {
|
||||
assertImplementsAST(esAST, babylonAST);
|
||||
} catch(err) {
|
||||
var traversal = err.message.slice(3, err.message.indexOf(":"));
|
||||
if (esAST.tokens) {
|
||||
delete esAST.tokens;
|
||||
}
|
||||
if (babylonAST.tokens) {
|
||||
delete babylonAST.tokens;
|
||||
}
|
||||
err.message +=
|
||||
"\nespree:\n" +
|
||||
util.inspect(esAST, {depth: err.depth, colors: true}) +
|
||||
util.inspect(lookup(esAST, traversal, 2), {depth: err.depth, colors: true}) +
|
||||
"\nbabel-eslint:\n" +
|
||||
util.inspect(babylonAST, {depth: err.depth, colors: true});
|
||||
util.inspect(lookup(babylonAST, traversal, 2), {depth: err.depth, colors: true});
|
||||
throw err;
|
||||
}
|
||||
// assert.equal(esAST, babylonAST);
|
||||
@ -394,7 +394,7 @@ describe("acorn-to-esprima", function () {
|
||||
it("do not allow import export everywhere", function() {
|
||||
assert.throws(function () {
|
||||
parseAndAssertSame("function F() { import a from \"a\"; }");
|
||||
}, /Illegal import declaration/)
|
||||
}, /SyntaxError: 'import' and 'export' may only appear at the top level/)
|
||||
});
|
||||
|
||||
it("return outside function", function () {
|
||||
@ -406,7 +406,7 @@ describe("acorn-to-esprima", function () {
|
||||
});
|
||||
|
||||
it("StringLiteral", function () {
|
||||
parseAndAssertSame('');
|
||||
parseAndAssertSame("");
|
||||
parseAndAssertSame("");
|
||||
parseAndAssertSame("a");
|
||||
});
|
||||
@ -443,5 +443,17 @@ describe("acorn-to-esprima", function () {
|
||||
"};"
|
||||
].join("\n"));
|
||||
});
|
||||
|
||||
it("RestOperator", function () {
|
||||
parseAndAssertSame("var { a, ...b } = c");
|
||||
parseAndAssertSame("var [ a, ...b ] = c");
|
||||
parseAndAssertSame("var a = function (...b) {}");
|
||||
});
|
||||
|
||||
it("SpreadOperator", function () {
|
||||
parseAndAssertSame("var a = { b, ...c }");
|
||||
parseAndAssertSame("var a = [ a, ...b ]");
|
||||
parseAndAssertSame("var a = sum(...b)");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -13,6 +13,9 @@ var errorLevel = 2;
|
||||
|
||||
var baseEslintOpts = {
|
||||
parser: require.resolve(".."),
|
||||
parserOptions: {
|
||||
sourceType: "script"
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -2,43 +2,25 @@
|
||||
"use strict";
|
||||
var eslint = require("eslint");
|
||||
|
||||
function verifyAndAssertMessages(code, rules, expectedMessages, features) {
|
||||
var defaultEcmaFeatures = {
|
||||
arrowFunctions: true,
|
||||
binaryLiterals: true,
|
||||
blockBindings: true,
|
||||
classes: true,
|
||||
defaultParams: true,
|
||||
destructuring: true,
|
||||
forOf: true,
|
||||
generators: true,
|
||||
modules: true,
|
||||
objectLiteralComputedProperties: true,
|
||||
objectLiteralDuplicateProperties: true,
|
||||
objectLiteralShorthandMethods: true,
|
||||
objectLiteralShorthandProperties: true,
|
||||
octalLiterals: true,
|
||||
regexUFlag: true,
|
||||
regexYFlag: true,
|
||||
restParams: true,
|
||||
spread: true,
|
||||
superInFunctions: true,
|
||||
templateStrings: true,
|
||||
unicodeCodePointEscapes: true,
|
||||
globalReturn: true,
|
||||
jsx: true,
|
||||
experimentalObjectRestSpread: true
|
||||
};
|
||||
|
||||
function verifyAndAssertMessages(code, rules, expectedMessages, sourceType) {
|
||||
var messages = eslint.linter.verify(
|
||||
code,
|
||||
{
|
||||
parser: require.resolve(".."),
|
||||
rules: rules,
|
||||
env: {
|
||||
node: true
|
||||
node: true,
|
||||
es6: true
|
||||
},
|
||||
ecmaFeatures: features || defaultEcmaFeatures
|
||||
parserOptions: {
|
||||
ecmaVersion: 6,
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
experimentalObjectRestSpread: true,
|
||||
globalReturn: true
|
||||
},
|
||||
sourceType: sourceType || "module"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@ -143,7 +125,7 @@ describe("verify", function () {
|
||||
"\"use strict\"; () => 1",
|
||||
{ "strict": [1, "global"] },
|
||||
[],
|
||||
{ modules: false }
|
||||
"script"
|
||||
);
|
||||
});
|
||||
|
||||
@ -415,8 +397,8 @@ describe("verify", function () {
|
||||
"var b: T = 1; b;"
|
||||
].join("\n"),
|
||||
{ "no-unused-vars": 1, "no-undef": 1 },
|
||||
[ "1:21 \"T\" is defined but never used no-unused-vars",
|
||||
'2:8 "T" is not defined. no-undef' ]
|
||||
[ "1:21 'T' is defined but never used no-unused-vars",
|
||||
"2:8 'T' is not defined. no-undef" ]
|
||||
);
|
||||
});
|
||||
|
||||
@ -426,7 +408,7 @@ describe("verify", function () {
|
||||
"export class Foo extends Bar<T> {}",
|
||||
].join("\n"),
|
||||
{ "no-unused-vars": 1, "no-undef": 1 },
|
||||
[ '2:30 "T" is not defined. no-undef' ]
|
||||
[ "2:30 'T' is not defined. no-undef" ]
|
||||
);
|
||||
});
|
||||
|
||||
@ -1151,7 +1133,7 @@ describe("verify", function () {
|
||||
verifyAndAssertMessages(
|
||||
"var unused;",
|
||||
{ "no-unused-vars": 1 },
|
||||
[ "1:5 \"unused\" is defined but never used no-unused-vars" ]
|
||||
[ "1:5 'unused' is defined but never used no-unused-vars" ]
|
||||
);
|
||||
});
|
||||
|
||||
@ -1175,7 +1157,7 @@ describe("verify", function () {
|
||||
verifyAndAssertMessages(
|
||||
"const {Bacona} = require('baconjs')",
|
||||
{ "no-undef": 1, "no-unused-vars": 1 },
|
||||
[ "1:8 \"Bacona\" is defined but never used no-unused-vars" ]
|
||||
[ "1:8 'Bacona' is defined but never used no-unused-vars" ]
|
||||
);
|
||||
});
|
||||
|
||||
@ -1301,7 +1283,7 @@ describe("verify", function () {
|
||||
"var x = 1;"
|
||||
].join("\n"),
|
||||
{ "no-use-before-define": 1 },
|
||||
[ "1:13 \"x\" was used before it was defined no-use-before-define" ]
|
||||
[ "1:13 'x' was used before it was defined no-use-before-define" ]
|
||||
)
|
||||
});
|
||||
|
||||
@ -1319,7 +1301,7 @@ describe("verify", function () {
|
||||
" set a (v) { }",
|
||||
"}"
|
||||
].join("\n"),
|
||||
{ "space-before-function-paren": 1, "space-before-keywords": 1, "indent": 1 },
|
||||
{ "space-before-function-paren": 1, "keyword-spacing": [1, {"before": true}], "indent": 1 },
|
||||
[]
|
||||
)
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user