Merge pull request babel/babel-eslint#264 from hzoo/eslint2

ESLint 2
This commit is contained in:
Henry Zhu 2016-03-01 22:34:53 -05:00
parent dce22ce5f6
commit 511862c4ee
11 changed files with 603 additions and 85 deletions

View File

@ -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;
}
};

View File

@ -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++;
}
}

View 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];
}
}
}

View 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

View 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;
};

View 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;
};

View File

@ -1,4 +1,4 @@
var acornToEsprima = require("acorn-to-esprima"); var babylonToEspree = require("./babylon-to-espree");
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");
@ -380,7 +380,9 @@ function monkeypatch() {
}; };
} }
exports.parse = function (code) { exports.parse = function (code, options) {
options = options || {};
try { try {
monkeypatch(); monkeypatch();
} catch (err) { } catch (err) {
@ -388,12 +390,12 @@ exports.parse = function (code) {
process.exit(1); process.exit(1);
} }
return exports.parseNoPatch(code); return exports.parseNoPatch(code, options);
} }
exports.parseNoPatch = function (code) { exports.parseNoPatch = function (code, options) {
var opts = { var opts = {
sourceType: "module", sourceType: options.sourceType || "module",
strictMode: true, strictMode: true,
allowImportExportEverywhere: false, // consistent with espree allowImportExportEverywhere: false, // consistent with espree
allowReturnOutsideFunction: true, allowReturnOutsideFunction: true,
@ -422,7 +424,7 @@ exports.parseNoPatch = function (code) {
} catch (err) { } catch (err) {
if (err instanceof SyntaxError) { if (err instanceof SyntaxError) {
err.lineNumber = err.loc.line; 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 // remove trailing "(LINE:COLUMN)" acorn message and add in esprima syntax error message start
err.message = "Line " + err.lineNumber + ": " + err.message.replace(/ \((\d+):(\d+)\)$/, ""); err.message = "Line " + err.lineNumber + ": " + err.message.replace(/ \((\d+):(\d+)\)$/, "");
@ -437,27 +439,27 @@ exports.parseNoPatch = function (code) {
ast.tokens.pop(); ast.tokens.pop();
// convert tokens // convert tokens
ast.tokens = acornToEsprima.toTokens(ast.tokens, tt, code); ast.tokens = babylonToEspree.toTokens(ast.tokens, tt, code);
// add comments // add comments
acornToEsprima.convertComments(ast.comments); babylonToEspree.convertComments(ast.comments);
// transform esprima and acorn divergent nodes // transform esprima and acorn divergent nodes
acornToEsprima.toAST(ast, traverse, code); babylonToEspree.toAST(ast, traverse, code);
// ast.program.tokens = ast.tokens; // ast.program.tokens = ast.tokens;
// ast.program.comments = ast.comments; // ast.program.comments = ast.comments;
// ast = ast.program; // ast = ast.program;
// remove File // remove File
ast.type = 'Program'; ast.type = "Program";
ast.sourceType = ast.program.sourceType; ast.sourceType = ast.program.sourceType;
ast.directives = ast.program.directives; ast.directives = ast.program.directives;
ast.body = ast.program.body; ast.body = ast.program.body;
delete ast.program; delete ast.program;
delete ast._paths; delete ast._paths;
acornToEsprima.attachComments(ast, ast.comments, ast.tokens); babylonToEspree.attachComments(ast, ast.comments, ast.tokens);
return ast; return ast;
} }

View File

@ -1,17 +1,17 @@
{ {
"name": "babel-eslint", "name": "babel-eslint",
"version": "5.0.0", "version": "5.0.0",
"description": "", "description": "Custom parser for ESLint",
"main": "index.js", "main": "index.js",
"files": [ "files": [
"index.js" "index.js",
"babylon-to-espree"
], ],
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/babel/babel-eslint.git" "url": "https://github.com/babel/babel-eslint.git"
}, },
"dependencies": { "dependencies": {
"acorn-to-esprima": "^2.0.4",
"babel-traverse": "^6.0.20", "babel-traverse": "^6.0.20",
"babel-types": "^6.0.19", "babel-types": "^6.0.19",
"babylon": "^6.0.18", "babylon": "^6.0.18",
@ -22,7 +22,8 @@
"bootstrap": "git submodule update --init && cd eslint && npm install", "bootstrap": "git submodule update --init && cd eslint && npm install",
"eslint": "cd eslint && mocha -c tests/lib/rules/*.js -r ../eslint-tester.js", "eslint": "cd eslint && mocha -c tests/lib/rules/*.js -r ../eslint-tester.js",
"test": "mocha", "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" "preversion": "npm test"
}, },
"author": "Sebastian McKenzie <sebmck@gmail.com>", "author": "Sebastian McKenzie <sebmck@gmail.com>",
@ -32,8 +33,8 @@
}, },
"homepage": "https://github.com/babel/babel-eslint", "homepage": "https://github.com/babel/babel-eslint",
"devDependencies": { "devDependencies": {
"eslint": "^1.10.2", "eslint": "^2.0.0",
"espree": "^2.2.5", "espree": "^3.0.0",
"mocha": "^2.3.3" "mocha": "^2.3.3"
} }
} }

View File

@ -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) { function parseAndAssertSame(code) {
var esAST = espree.parse(code, { var esAST = espree.parse(code, {
ecmaFeatures: { ecmaFeatures: {
arrowFunctions: true, // enable JSX parsing
binaryLiterals: true, jsx: true,
blockBindings: true, // enable return in global scope
classes: true, globalReturn: true,
defaultParams: true, // enable implied strict mode (if ecmaVersion >= 5)
destructuring: true, impliedStrict: true,
forOf: true, // allow experimental object rest/spread
generators: true, experimentalObjectRestSpread: 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,
}, },
tokens: true, tokens: true,
loc: true, loc: true,
range: true, range: true,
comment: true, comment: true,
attachComment: true attachComment: true,
ecmaVersion: 6,
sourceType: "module"
}); });
var babylonAST = babelEslint.parse(code); var babylonAST = babelEslint.parse(code);
try { try {
assertImplementsAST(esAST, babylonAST); assertImplementsAST(esAST, babylonAST);
} catch(err) { } 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 += err.message +=
"\nespree:\n" + "\nespree:\n" +
util.inspect(esAST, {depth: err.depth, colors: true}) + util.inspect(lookup(esAST, traversal, 2), {depth: err.depth, colors: true}) +
"\nbabel-eslint:\n" + "\nbabel-eslint:\n" +
util.inspect(babylonAST, {depth: err.depth, colors: true}); util.inspect(lookup(babylonAST, traversal, 2), {depth: err.depth, colors: true});
throw err; throw err;
} }
// assert.equal(esAST, babylonAST); // assert.equal(esAST, babylonAST);
@ -394,7 +394,7 @@ describe("acorn-to-esprima", function () {
it("do not allow import export everywhere", function() { it("do not allow import export everywhere", function() {
assert.throws(function () { assert.throws(function () {
parseAndAssertSame("function F() { import a from \"a\"; }"); 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 () { it("return outside function", function () {
@ -406,7 +406,7 @@ describe("acorn-to-esprima", function () {
}); });
it("StringLiteral", function () { it("StringLiteral", function () {
parseAndAssertSame(''); parseAndAssertSame("");
parseAndAssertSame(""); parseAndAssertSame("");
parseAndAssertSame("a"); parseAndAssertSame("a");
}); });
@ -443,5 +443,17 @@ describe("acorn-to-esprima", function () {
"};" "};"
].join("\n")); ].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)");
});
}); });
}); });

View File

@ -13,6 +13,9 @@ var errorLevel = 2;
var baseEslintOpts = { var baseEslintOpts = {
parser: require.resolve(".."), parser: require.resolve(".."),
parserOptions: {
sourceType: "script"
}
}; };
/** /**

View File

@ -2,43 +2,25 @@
"use strict"; "use strict";
var eslint = require("eslint"); var eslint = require("eslint");
function verifyAndAssertMessages(code, rules, expectedMessages, features) { function verifyAndAssertMessages(code, rules, expectedMessages, sourceType) {
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
};
var messages = eslint.linter.verify( var messages = eslint.linter.verify(
code, code,
{ {
parser: require.resolve(".."), parser: require.resolve(".."),
rules: rules, rules: rules,
env: { 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", "\"use strict\"; () => 1",
{ "strict": [1, "global"] }, { "strict": [1, "global"] },
[], [],
{ modules: false } "script"
); );
}); });
@ -415,8 +397,8 @@ describe("verify", function () {
"var b: T = 1; b;" "var b: T = 1; b;"
].join("\n"), ].join("\n"),
{ "no-unused-vars": 1, "no-undef": 1 }, { "no-unused-vars": 1, "no-undef": 1 },
[ "1:21 \"T\" is defined but never used no-unused-vars", [ "1:21 'T' is defined but never used no-unused-vars",
'2:8 "T" is not defined. no-undef' ] "2:8 'T' is not defined. no-undef" ]
); );
}); });
@ -426,7 +408,7 @@ describe("verify", function () {
"export class Foo extends Bar<T> {}", "export class Foo extends Bar<T> {}",
].join("\n"), ].join("\n"),
{ "no-unused-vars": 1, "no-undef": 1 }, { "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( verifyAndAssertMessages(
"var unused;", "var unused;",
{ "no-unused-vars": 1 }, { "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( verifyAndAssertMessages(
"const {Bacona} = require('baconjs')", "const {Bacona} = require('baconjs')",
{ "no-undef": 1, "no-unused-vars": 1 }, { "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;" "var x = 1;"
].join("\n"), ].join("\n"),
{ "no-use-before-define": 1 }, { "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" ]
) )
}); });
@ -1316,10 +1298,10 @@ describe("verify", function () {
it("getter/setter #218", function () { it("getter/setter #218", function () {
verifyAndAssertMessages([ verifyAndAssertMessages([
"class Person {", "class Person {",
"set a (v) { }", " set a (v) { }",
"}" "}"
].join("\n"), ].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 },
[] []
) )
}); });