diff --git a/babylon-to-espree/attachComments.js b/babylon-to-espree/attachComments.js new file mode 100644 index 00000000..4040ce7e --- /dev/null +++ b/babylon-to-espree/attachComments.js @@ -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; + } +}; diff --git a/babylon-to-espree/convertTemplateType.js b/babylon-to-espree/convertTemplateType.js new file mode 100644 index 00000000..0c3293dc --- /dev/null +++ b/babylon-to-espree/convertTemplateType.js @@ -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++; + } +} diff --git a/babylon-to-espree/index.js b/babylon-to-espree/index.js new file mode 100644 index 00000000..70accfdf --- /dev/null +++ b/babylon-to-espree/index.js @@ -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]; + } + } +} diff --git a/babylon-to-espree/toAST.js b/babylon-to-espree/toAST.js new file mode 100644 index 00000000..f82c4e59 --- /dev/null +++ b/babylon-to-espree/toAST.js @@ -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 diff --git a/babylon-to-espree/toToken.js b/babylon-to-espree/toToken.js new file mode 100644 index 00000000..7e13f28e --- /dev/null +++ b/babylon-to-espree/toToken.js @@ -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; +}; diff --git a/babylon-to-espree/toTokens.js b/babylon-to-espree/toTokens.js new file mode 100644 index 00000000..dab4b21b --- /dev/null +++ b/babylon-to-espree/toTokens.js @@ -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; +}; diff --git a/index.js b/index.js index 47980470..87180e67 100644 --- a/index.js +++ b/index.js @@ -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; } diff --git a/package.json b/package.json index 5433fbfe..28a969a4 100644 --- a/package.json +++ b/package.json @@ -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 ", @@ -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" } } diff --git a/test/babel-eslint.js b/test/babel-eslint.js index dea774eb..a66f1c40 100644 --- a/test/babel-eslint.js +++ b/test/babel-eslint.js @@ -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, - jsx: true, - experimentalObjectRestSpread: true, + // enable JSX parsing + jsx: 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)"); + }); }); }); diff --git a/test/integration.js b/test/integration.js index 5ce7a443..f3f09522 100644 --- a/test/integration.js +++ b/test/integration.js @@ -13,6 +13,9 @@ var errorLevel = 2; var baseEslintOpts = { parser: require.resolve(".."), + parserOptions: { + sourceType: "script" + } }; /** diff --git a/test/non-regression.js b/test/non-regression.js index 4e2d1128..0e979df4 100644 --- a/test/non-regression.js +++ b/test/non-regression.js @@ -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 {}", ].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" ] ) }); @@ -1316,10 +1298,10 @@ describe("verify", function () { it("getter/setter #218", function () { verifyAndAssertMessages([ "class Person {", - "set a (v) { }", + " 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 }, [] ) });