From 98800e5550daf1158600a189edd02140e8028b09 Mon Sep 17 00:00:00 2001 From: Teddy Katz Date: Sat, 18 Feb 2017 19:54:52 -0500 Subject: [PATCH] New: function-paren-newline rule (fixes #6074) --- Makefile.js | 11 +- conf/eslint.json | 1 + docs/rules/function-paren-newline.md | 225 +++++++ lib/cli-engine.js | 12 +- lib/code-path-analysis/code-path-analyzer.js | 12 +- lib/code-path-analysis/code-path-segment.js | 3 +- lib/code-path-analysis/code-path-state.js | 29 +- lib/code-path-analysis/code-path.js | 3 +- lib/code-path-analysis/fork-context.js | 3 +- lib/eslint.js | 8 +- lib/formatters/codeframe.js | 4 +- lib/rules/capitalized-comments.js | 12 +- lib/rules/comma-style.js | 6 +- lib/rules/function-paren-newline.js | 220 +++++++ lib/rules/indent.js | 4 +- lib/rules/key-spacing.js | 4 +- lib/rules/no-eval.js | 5 +- lib/rules/no-invalid-this.js | 3 +- lib/rules/no-this-before-super.js | 5 +- lib/rules/no-unmodified-loop-condition.js | 6 +- lib/rules/require-await.js | 4 +- lib/testers/rule-tester.js | 32 +- lib/timing.js | 3 +- lib/util/comment-event-generator.js | 6 +- lib/util/source-code.js | 6 +- packages/eslint-config-eslint/default.yml | 1 + .../code-path-analysis/code-path-analyzer.js | 4 +- tests/lib/eslint.js | 31 +- tests/lib/ignored-paths.js | 6 +- tests/lib/rules/function-paren-newline.js | 552 ++++++++++++++++++ tests/lib/rules/indent.js | 18 +- tests/lib/token-store.js | 8 +- tests/lib/util/comment-event-generator.js | 4 +- tests/lib/util/node-event-generator.js | 4 +- tests/lib/util/source-code.js | 7 +- 35 files changed, 1125 insertions(+), 137 deletions(-) create mode 100644 docs/rules/function-paren-newline.md create mode 100644 lib/rules/function-paren-newline.js create mode 100644 tests/lib/rules/function-paren-newline.js diff --git a/Makefile.js b/Makefile.js index 477522cc3a18..6cd4dff133af 100644 --- a/Makefile.js +++ b/Makefile.js @@ -863,7 +863,8 @@ target.checkLicenses = function() { if (impermissible.length) { impermissible.forEach(dependency => { - console.error("%s license for %s is impermissible.", + console.error( + "%s license for %s is impermissible.", dependency.licenses, dependency.name ); @@ -1081,11 +1082,9 @@ target.perf = function() { () => { // Count test target files. - const count = glob.sync( - process.platform === "win32" - ? PERF_MULTIFILES_TARGETS.slice(2).replace("\\", "/") - : PERF_MULTIFILES_TARGETS - ).length; + const count = glob.sync(process.platform === "win32" + ? PERF_MULTIFILES_TARGETS.slice(2).replace("\\", "/") + : PERF_MULTIFILES_TARGETS).length; runPerformanceTest( `Multi Files (${count} files):`, diff --git a/conf/eslint.json b/conf/eslint.json index 774a06d8f597..74a155cdb0c2 100755 --- a/conf/eslint.json +++ b/conf/eslint.json @@ -165,6 +165,7 @@ "func-names": "off", "func-name-matching": "off", "func-style": "off", + "function-paren-newline": "off", "generator-star-spacing": "off", "global-require": "off", "guard-for-in": "off", diff --git a/docs/rules/function-paren-newline.md b/docs/rules/function-paren-newline.md new file mode 100644 index 000000000000..83912b7b2832 --- /dev/null +++ b/docs/rules/function-paren-newline.md @@ -0,0 +1,225 @@ +# enforce consistent line breaks inside function parentheses (function-paren-newline) + +(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#fix) automatically fixes problems reported by this rule. + +Many styleguides require or disallow newlines inside of function parentheses. + +## Rule Details + +This rule enforces consistent line breaks inside parentheses of function parameters or arguments. + +### Options + +This rule has a single option, which can either be a string or an object. + +* `"always"` requires line breaks inside all function parentheses. +* `"never"` disallows line breaks inside all function parentheses. +* `"multiline"` (default) requires linebreaks inside function parentheses if any of the parameters/arguments have a line break between them. Otherwise, it disallows linebreaks. +* `{ "minItems": value }` requires linebreaks inside function parentheses if the number of parameters/arguments is at least `value`. Otherwise, it disallows linebreaks. + +Example configurations: + +```json +{ + "rules": { + "function-paren-newline": ["error", "never"] + } +} +``` + +```json +{ + "rules": { + "function-paren-newline": ["error", { "minItems": 3 }] + } +} +``` + +Examples of **incorrect** code for this rule with the `"always"` option: + +```js +/* eslint function-paren-newline: ["error", "always"] */ + +function foo(bar, baz) {} + +var foo = function(bar, baz) {}; + +var foo = (bar, baz) => {}; + +foo(bar, baz); +``` + +Examples of **correct** code for this rule with the `"always"` option: + +```js +/* eslint function-paren-newline: ["error", "always"] */ + +function foo( + bar, + baz +) {} + +var foo = function( + bar, baz +) {}; + +var foo = ( + bar, + baz +) => {}; + +foo( + bar, + baz +); +``` + +Examples of **incorrect** code for this rule with the `"never"` option: + +```js +/* eslint function-paren-newline: ["error", "never"] */ + +function foo( + bar, + baz +) {} + +var foo = function( + bar, baz +) {}; + +var foo = ( + bar, + baz +) => {}; + +foo( + bar, + baz +); +``` + +Examples of **correct** code for this rule with the `"never"` option: + +```js +/* eslint function-paren-newline: ["error", "never"] */ + +function foo(bar, baz) {} + +function foo(bar, + baz) {} + +var foo = function(bar, baz) {}; + +var foo = (bar, baz) => {}; + +foo(bar, baz); + +foo(bar, + baz); +``` + +Examples of **incorrect** code for this rule with the default `"multiline"` option: + +```js +/* eslint function-paren-newline: ["error", "multiline"] */ + +function foo(bar, + baz +) {} + +var foo = function( + bar, baz +) {}; + +var foo = ( + bar, + baz) => {}; + +foo(bar, + baz); + +foo( + function() { + return baz; + } +); +``` + +Examples of **correct** code for this rule with the default `"multiline"` option: + +```js +/* eslint function-paren-newline: ["error", "multiline"] */ + +function foo(bar, baz) {} + +var foo = function( + bar, + baz +) {}; + +var foo = (bar, baz) => {}; + +foo(bar, baz, qux); + +foo( + bar, + baz, + qux +); + +foo(function() { + return baz; +}); +``` + +Examples of **incorrect** code for this rule with the `{ "minItems": 3 }` option: + +```js +/* eslint function-paren-newline: ["error", { "minItems": 3 }] */ + +function foo( + bar, + baz +) {} + +function foo(bar, baz, qux) {} + +var foo = function( + bar, baz +) {}; + +var foo = (bar, + baz) => {}; + +foo(bar, + baz); +``` + +Examples of **correct** code for this rule with the `{ "minItems": 3 }` option: + +```js +/* eslint function-paren-newline: ["error", { "minItems": 3 }] */ + +function foo(bar, baz) {} + +var foo = function( + bar, + baz, + qux +) {}; + +var foo = ( + bar, baz, qux +) => {}; + +foo(bar, baz); + +foo( + bar, baz, qux +); +``` + +## When Not To Use It + +If don't want to enforce consistent linebreaks inside function parentheses, do not turn on this rule. diff --git a/lib/cli-engine.js b/lib/cli-engine.js index de875a4d3529..656a188aa695 100644 --- a/lib/cli-engine.js +++ b/lib/cli-engine.js @@ -530,13 +530,11 @@ CLIEngine.getErrorResults = function(results) { const filteredMessages = result.messages.filter(isErrorMessage); if (filteredMessages.length > 0) { - filtered.push( - Object.assign(result, { - messages: filteredMessages, - errorCount: filteredMessages.length, - warningCount: 0 - }) - ); + filtered.push(Object.assign(result, { + messages: filteredMessages, + errorCount: filteredMessages.length, + warningCount: 0 + })); } }); diff --git a/lib/code-path-analysis/code-path-analyzer.js b/lib/code-path-analysis/code-path-analyzer.js index cb8b1e1bf8ce..80d9f2849f44 100644 --- a/lib/code-path-analysis/code-path-analyzer.js +++ b/lib/code-path-analysis/code-path-analyzer.js @@ -154,7 +154,8 @@ function forwardCurrentToHead(analyzer, node) { analyzer.emitter.emit( "onCodePathSegmentEnd", currentSegment, - node); + node + ); } } } @@ -175,7 +176,8 @@ function forwardCurrentToHead(analyzer, node) { analyzer.emitter.emit( "onCodePathSegmentStart", headSegment, - node); + node + ); } } } @@ -202,7 +204,8 @@ function leaveFromCurrentSegment(analyzer, node) { analyzer.emitter.emit( "onCodePathSegmentEnd", currentSegment, - node); + node + ); } } @@ -369,7 +372,8 @@ function processCodePathToEnter(analyzer, node) { case "SwitchStatement": state.pushSwitchContext( node.cases.some(isCaseNode), - astUtils.getLabel(node)); + astUtils.getLabel(node) + ); break; case "TryStatement": diff --git a/lib/code-path-analysis/code-path-segment.js b/lib/code-path-analysis/code-path-segment.js index db1eba4560c2..825c9b74bf3e 100644 --- a/lib/code-path-analysis/code-path-segment.js +++ b/lib/code-path-analysis/code-path-segment.js @@ -164,7 +164,8 @@ class CodePathSegment { return new CodePathSegment( id, flattenUnusedSegments(allPrevSegments), - allPrevSegments.some(isReachable)); + allPrevSegments.some(isReachable) + ); } /** diff --git a/lib/code-path-analysis/code-path-state.js b/lib/code-path-analysis/code-path-state.js index 3faff3ebb859..1ee094a5dad4 100644 --- a/lib/code-path-analysis/code-path-state.js +++ b/lib/code-path-analysis/code-path-state.js @@ -517,9 +517,7 @@ class CodePathState { context.processed = false; // Creates new path from the `true` case. - forkContext.replaceHead( - context.trueForkContext.makeNext(0, -1) - ); + forkContext.replaceHead(context.trueForkContext.makeNext(0, -1)); } /** @@ -540,9 +538,7 @@ class CodePathState { context.processed = true; // Creates new path from the `false` case. - forkContext.replaceHead( - context.falseForkContext.makeNext(0, -1) - ); + forkContext.replaceHead(context.falseForkContext.makeNext(0, -1)); } //-------------------------------------------------------------------------- @@ -857,7 +853,8 @@ class CodePathState { segments.push(CodePathSegment.newNext( this.idGenerator.next(), - prevSegsOfLeavingSegment)); + prevSegsOfLeavingSegment + )); } this.pushForkContext(true); @@ -992,7 +989,8 @@ class CodePathState { makeLooped( this, forkContext.head, - context.continueDestSegments); + context.continueDestSegments + ); break; case "DoWhileStatement": { @@ -1013,7 +1011,8 @@ class CodePathState { makeLooped( this, segmentsList[i], - context.entrySegments); + context.entrySegments + ); } break; } @@ -1024,7 +1023,8 @@ class CodePathState { makeLooped( this, forkContext.head, - context.leftSegments); + context.leftSegments + ); break; /* istanbul ignore next */ @@ -1149,7 +1149,8 @@ class CodePathState { finalizeTestSegmentsOfFor( context, choiceContext, - forkContext.head); + forkContext.head + ); } else { context.endOfInitSegments = forkContext.head; } @@ -1180,13 +1181,15 @@ class CodePathState { makeLooped( this, context.endOfUpdateSegments, - context.testSegments); + context.testSegments + ); } } else if (context.testSegments) { finalizeTestSegmentsOfFor( context, choiceContext, - forkContext.head); + forkContext.head + ); } else { context.endOfInitSegments = forkContext.head; } diff --git a/lib/code-path-analysis/code-path.js b/lib/code-path-analysis/code-path.js index 6ef07b4a2d93..5fc5d22b01bf 100644 --- a/lib/code-path-analysis/code-path.js +++ b/lib/code-path-analysis/code-path.js @@ -51,7 +51,8 @@ class CodePath { Object.defineProperty( this, "internal", - { value: new CodePathState(new IdGenerator(`${id}_`), onLooped) }); + { value: new CodePathState(new IdGenerator(`${id}_`), onLooped) } + ); // Adds this into `childCodePaths` of `upper`. if (upper) { diff --git a/lib/code-path-analysis/fork-context.js b/lib/code-path-analysis/fork-context.js index 7423c13199b3..4fae6bbb1e8a 100644 --- a/lib/code-path-analysis/fork-context.js +++ b/lib/code-path-analysis/fork-context.js @@ -254,7 +254,8 @@ class ForkContext { return new ForkContext( parentContext.idGenerator, parentContext, - (forkLeavingPath ? 2 : 1) * parentContext.count); + (forkLeavingPath ? 2 : 1) * parentContext.count + ); } } diff --git a/lib/eslint.js b/lib/eslint.js index 15cb0b4b69ee..cf0f7f67d624 100755 --- a/lib/eslint.js +++ b/lib/eslint.js @@ -869,9 +869,11 @@ module.exports = (function() { // add all the node types as listeners Object.keys(rule).forEach(nodeType => { - api.on(nodeType, timing.enabled - ? timing.time(key, rule[nodeType]) - : rule[nodeType] + api.on( + nodeType, + timing.enabled + ? timing.time(key, rule[nodeType]) + : rule[nodeType] ); }); } catch (ex) { diff --git a/lib/formatters/codeframe.js b/lib/formatters/codeframe.js index 39ba06de4fd2..8ddd02e89f0c 100644 --- a/lib/formatters/codeframe.js +++ b/lib/formatters/codeframe.js @@ -62,9 +62,7 @@ function formatMessage(message, parentResult) { const result = [firstLine]; if (sourceCode) { - result.push( - codeFrame(sourceCode, message.line, message.column, { highlightCode: false }) - ); + result.push(codeFrame(sourceCode, message.line, message.column, { highlightCode: false })); } return result.join("\n"); diff --git a/lib/rules/capitalized-comments.js b/lib/rules/capitalized-comments.js index b7ed13f3ab59..4e8264a19be3 100644 --- a/lib/rules/capitalized-comments.js +++ b/lib/rules/capitalized-comments.js @@ -166,12 +166,10 @@ module.exports = { const previousToken = sourceCode.getTokenOrCommentBefore(comment), nextToken = sourceCode.getTokenOrCommentAfter(comment); - return Boolean( - previousToken && + return Boolean(previousToken && nextToken && comment.loc.start.line === previousToken.loc.end.line && - comment.loc.end.line === nextToken.loc.start.line - ); + comment.loc.end.line === nextToken.loc.start.line); } /** @@ -183,10 +181,8 @@ module.exports = { function isConsecutiveComment(comment) { const previousTokenOrComment = sourceCode.getTokenOrCommentBefore(comment); - return Boolean( - previousTokenOrComment && - ["Block", "Line"].indexOf(previousTokenOrComment.type) !== -1 - ); + return Boolean(previousTokenOrComment && + ["Block", "Line"].indexOf(previousTokenOrComment.type) !== -1); } /** diff --git a/lib/rules/comma-style.js b/lib/rules/comma-style.js index 74fee9623797..47861d2bbf92 100644 --- a/lib/rules/comma-style.js +++ b/lib/rules/comma-style.js @@ -211,8 +211,10 @@ module.exports = { * they are always valid regardless of an undefined item. */ if (isComma(commaToken)) { - validateCommaItemSpacing(previousItemToken, commaToken, - currentItemToken, reportItem); + validateCommaItemSpacing( + previousItemToken, commaToken, + currentItemToken, reportItem + ); } previousItemToken = item ? sourceCode.getLastToken(item) : previousItemToken; diff --git a/lib/rules/function-paren-newline.js b/lib/rules/function-paren-newline.js new file mode 100644 index 000000000000..924c64c8b6e4 --- /dev/null +++ b/lib/rules/function-paren-newline.js @@ -0,0 +1,220 @@ +/** + * @fileoverview enforce consistent line breaks inside function parentheses + * @author Teddy Katz + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "enforce consistent line breaks inside function parentheses", + category: "Stylistic Issues", + recommended: false + }, + fixable: "whitespace", + schema: [ + { + oneOf: [ + { + enum: ["always", "never", "multiline"] + }, + { + type: "object", + properties: { + minItems: { + type: "integer", + minimum: 0 + } + }, + additionalProperties: false + } + ] + } + ] + }, + + create(context) { + const sourceCode = context.getSourceCode(); + const rawOption = context.options[0] || "multiline"; + const multilineOption = rawOption === "multiline"; + let minItems; + + if (typeof rawOption === "object") { + minItems = rawOption.minItems; + } else if (rawOption === "always") { + minItems = 0; + } else if (rawOption === "never") { + minItems = Infinity; + } else { + minItems = null; + } + + //---------------------------------------------------------------------- + // Helpers + //---------------------------------------------------------------------- + + /** + * Determines whether there should be newlines inside function parens + * @param {ASTNode[]} elements The arguments or parameters in the list + * @returns {boolean} `true` if there should be newlines inside the function parens + */ + function shouldHaveNewlines(elements) { + if (multilineOption) { + return elements.some((element, index) => index !== elements.length - 1 && element.loc.end.line !== elements[index + 1].loc.start.line); + } + return elements.length >= minItems; + } + + /** + * Validates a list of arguments or parameters + * @param {Object} parens An object with keys `leftParen` for the left paren token, and `rightParen` for the right paren token + * @param {ASTNode[]} elements The arguments or parameters in the list + * @returns {void} + */ + function validateParens(parens, elements) { + if (parens === null) { + return; + } + + const leftParen = parens.leftParen; + const rightParen = parens.rightParen; + const tokenAfterLeftParen = sourceCode.getTokenAfter(leftParen); + const tokenBeforeRightParen = sourceCode.getTokenBefore(rightParen); + const hasLeftNewline = !astUtils.isTokenOnSameLine(leftParen, tokenAfterLeftParen); + const hasRightNewline = !astUtils.isTokenOnSameLine(tokenBeforeRightParen, rightParen); + const needsNewlines = shouldHaveNewlines(elements); + + if (hasLeftNewline && !needsNewlines) { + context.report({ + node: leftParen, + message: "Unexpected newline after '('.", + fix(fixer) { + return sourceCode.getText().slice(leftParen.range[1], tokenAfterLeftParen.range[0]).trim() + + // If there is a comment between the ( and the first element, don't do a fix. + ? null + : fixer.removeRange([leftParen.range[1], tokenAfterLeftParen.range[0]]); + } + }); + } else if (!hasLeftNewline && needsNewlines) { + context.report({ + node: leftParen, + message: "Expected a newline after '('.", + fix: fixer => fixer.insertTextAfter(leftParen, "\n") + }); + } + + if (hasRightNewline && !needsNewlines) { + context.report({ + node: rightParen, + message: "Unexpected newline before ')'.", + fix(fixer) { + return sourceCode.getText().slice(tokenBeforeRightParen.range[1], rightParen.range[0]).trim() + + // If there is a comment between the last element and the ), don't do a fix. + ? null + : fixer.removeRange([tokenBeforeRightParen.range[1], rightParen.range[0]]); + } + }); + } else if (!hasRightNewline && needsNewlines) { + context.report({ + node: rightParen, + message: "Expected a newline before ')'.", + fix: fixer => fixer.insertTextBefore(rightParen, "\n") + }); + } + } + + /** + * Gets the left paren and right paren tokens of a node. + * @param {ASTNode} node The node with parens + * @returns {Object} An object with keys `leftParen` for the left paren token, and `rightParen` for the right paren token. + * Can also return `null` if an expression has no parens (e.g. a NewExpression with no arguments, or an ArrowFunctionExpression + * with a single parameter) + */ + function getParenTokens(node) { + switch (node.type) { + case "NewExpression": + if (!node.arguments.length && !( + astUtils.isOpeningParenToken(sourceCode.getLastToken(node, { skip: 1 })) && + astUtils.isClosingParenToken(sourceCode.getLastToken(node)) + )) { + + // If the NewExpression does not have parens (e.g. `new Foo`), return null. + return null; + } + + // falls through + + case "CallExpression": + return { + leftParen: sourceCode.getTokenAfter(node.callee, astUtils.isOpeningParenToken), + rightParen: sourceCode.getLastToken(node) + }; + + case "FunctionDeclaration": + case "FunctionExpression": { + const leftParen = sourceCode.getFirstToken(node, astUtils.isOpeningParenToken); + const rightParen = node.params.length + ? sourceCode.getTokenAfter(node.params[node.params.length - 1], astUtils.isClosingParenToken) + : sourceCode.getTokenAfter(leftParen); + + return { leftParen, rightParen }; + } + + case "ArrowFunctionExpression": { + const firstToken = sourceCode.getFirstToken(node); + + if (!astUtils.isOpeningParenToken(firstToken)) { + + // If the ArrowFunctionExpression has a single param without parens, return null. + return null; + } + + return { + leftParen: firstToken, + rightParen: sourceCode.getTokenBefore(node.body, astUtils.isClosingParenToken) + }; + } + + default: + return null; + } + } + + /** + * Validates the parentheses for a node + * @param {ASTNode} node The node with parens + * @returns {void} + */ + function validateNode(node) { + const parens = getParenTokens(node); + + if (parens) { + validateParens(parens, astUtils.isFunction(node) ? node.params : node.arguments); + } + } + + //---------------------------------------------------------------------- + // Public + //---------------------------------------------------------------------- + + return { + ArrowFunctionExpression: validateNode, + CallExpression: validateNode, + FunctionDeclaration: validateNode, + FunctionExpression: validateNode, + NewExpression: validateNode + }; + } +}; diff --git a/lib/rules/indent.js b/lib/rules/indent.js index bba1b20bcf44..6634b2801bc2 100644 --- a/lib/rules/indent.js +++ b/lib/rules/indent.js @@ -961,8 +961,8 @@ module.exports = { function isWrappedInParenthesis(node) { const regex = /^return\s*?\(\s*?\);*?/; - const statementWithoutArgument = sourceCode.getText(node).replace( - sourceCode.getText(node.argument), ""); + const statementWithoutArgument = sourceCode.getText(node) + .replace(sourceCode.getText(node.argument), ""); return regex.test(statementWithoutArgument); } diff --git a/lib/rules/key-spacing.js b/lib/rules/key-spacing.js index 1416e46c243c..0e2a036d09fe 100644 --- a/lib/rules/key-spacing.js +++ b/lib/rules/key-spacing.js @@ -487,9 +487,7 @@ module.exports = { * @returns {Object} Whitespace before and after the property's colon. */ function getPropertyWhitespace(property) { - const whitespace = /(\s*):(\s*)/.exec(sourceCode.getText().slice( - property.key.range[1], property.value.range[0] - )); + const whitespace = /(\s*):(\s*)/.exec(sourceCode.getText().slice(property.key.range[1], property.value.range[0])); if (whitespace) { return { diff --git a/lib/rules/no-eval.js b/lib/rules/no-eval.js index fe1456cba0a4..7465ea3d5196 100644 --- a/lib/rules/no-eval.js +++ b/lib/rules/no-eval.js @@ -94,10 +94,7 @@ module.exports = { }, create(context) { - const allowIndirect = Boolean( - context.options[0] && - context.options[0].allowIndirect - ); + const allowIndirect = Boolean(context.options[0] && context.options[0].allowIndirect); const sourceCode = context.getSourceCode(); let funcInfo = null; diff --git a/lib/rules/no-invalid-this.js b/lib/rules/no-invalid-this.js index 64ef4882e252..5a0a62f7a1d4 100644 --- a/lib/rules/no-invalid-this.js +++ b/lib/rules/no-invalid-this.js @@ -46,7 +46,8 @@ module.exports = { current.init = true; current.valid = !astUtils.isDefaultThisBinding( current.node, - sourceCode); + sourceCode + ); } return current; }; diff --git a/lib/rules/no-this-before-super.js b/lib/rules/no-this-before-super.js index c8d5dc4698d7..35f6498129f0 100644 --- a/lib/rules/no-this-before-super.js +++ b/lib/rules/no-this-before-super.js @@ -145,10 +145,7 @@ module.exports = { funcInfo = { upper: funcInfo, isConstructor: true, - hasExtends: Boolean( - classNode.superClass && - !astUtils.isNullOrUndefined(classNode.superClass) - ), + hasExtends: Boolean(classNode.superClass && !astUtils.isNullOrUndefined(classNode.superClass)), codePath }; } else { diff --git a/lib/rules/no-unmodified-loop-condition.js b/lib/rules/no-unmodified-loop-condition.js index 8243611913a1..25c9e05b9b47 100644 --- a/lib/rules/no-unmodified-loop-condition.js +++ b/lib/rules/no-unmodified-loop-condition.js @@ -227,11 +227,9 @@ function updateModifiedFlag(conditions, modifiers) { * in the loop. * FIXME: This should probably be extracted to a function. */ - const inLoop = condition.isInLoop(modifier) || Boolean( - (funcNode = getEncloseFunctionDeclaration(modifier)) && + const inLoop = condition.isInLoop(modifier) || Boolean((funcNode = getEncloseFunctionDeclaration(modifier)) && (funcVar = astUtils.getVariableByName(modifier.from.upper, funcNode.id.name)) && - funcVar.references.some(condition.isInLoop) - ); + funcVar.references.some(condition.isInLoop)); condition.modified = inLoop; } diff --git a/lib/rules/require-await.js b/lib/rules/require-await.js index a5698ae058bd..2a0b7a27da32 100644 --- a/lib/rules/require-await.js +++ b/lib/rules/require-await.js @@ -69,9 +69,7 @@ module.exports = { loc: astUtils.getFunctionHeadLoc(node, sourceCode), message: "{{name}} has no 'await' expression.", data: { - name: capitalizeFirstLetter( - astUtils.getFunctionNameWithKind(node) - ) + name: capitalizeFirstLetter(astUtils.getFunctionNameWithKind(node)) } }); } diff --git a/lib/testers/rule-tester.js b/lib/testers/rule-tester.js index 16e4637890e9..b6e4fc6f86c4 100644 --- a/lib/testers/rule-tester.js +++ b/lib/testers/rule-tester.js @@ -419,8 +419,11 @@ RuleTester.prototype = { const result = runRuleForItem(ruleName, item); const messages = result.messages; - assert.equal(messages.length, 0, util.format("Should have no errors but had %d: %s", - messages.length, util.inspect(messages))); + assert.equal(messages.length, 0, util.format( + "Should have no errors but had %d: %s", + messages.length, + util.inspect(messages) + )); assertASTDidntChange(result.beforeAST, result.afterAST); } @@ -434,8 +437,10 @@ RuleTester.prototype = { * @private */ function testInvalidTemplate(ruleName, item) { - assert.ok(item.errors || item.errors === 0, - `Did not specify errors for an invalid test of ${ruleName}`); + assert.ok( + item.errors || item.errors === 0, + `Did not specify errors for an invalid test of ${ruleName}` + ); const result = runRuleForItem(ruleName, item); const messages = result.messages; @@ -443,12 +448,21 @@ RuleTester.prototype = { if (typeof item.errors === "number") { - assert.equal(messages.length, item.errors, util.format("Should have %d error%s but had %d: %s", - item.errors, item.errors === 1 ? "" : "s", messages.length, util.inspect(messages))); + assert.equal(messages.length, item.errors, util.format( + "Should have %d error%s but had %d: %s", + item.errors, + item.errors === 1 ? "" : "s", + messages.length, + util.inspect(messages) + )); } else { - assert.equal(messages.length, item.errors.length, - util.format("Should have %d error%s but had %d: %s", - item.errors.length, item.errors.length === 1 ? "" : "s", messages.length, util.inspect(messages))); + assert.equal(messages.length, item.errors.length, util.format( + "Should have %d error%s but had %d: %s", + item.errors.length, + item.errors.length === 1 ? "" : "s", + messages.length, + util.inspect(messages) + )); for (let i = 0, l = item.errors.length; i < l; i++) { assert.ok(!("fatal" in messages[i]), `A fatal parsing error occurred: ${messages[i].message}`); diff --git a/lib/timing.js b/lib/timing.js index 20456628640b..317588253d36 100644 --- a/lib/timing.js +++ b/lib/timing.js @@ -87,8 +87,7 @@ function display(data) { const table = rows.map(row => row .map((cell, index) => ALIGN[index](cell, widths[index])) - .join(" | ") - ); + .join(" | ")); table.splice(1, 0, widths.map((w, index) => { if (index !== 0 && index !== widths.length - 1) { diff --git a/lib/util/comment-event-generator.js b/lib/util/comment-event-generator.js index 239a9834d0ed..883819057242 100644 --- a/lib/util/comment-event-generator.js +++ b/lib/util/comment-event-generator.js @@ -44,7 +44,8 @@ function emitCommentsEnter(generator, comments) { comments, generator.emitter, generator.commentLocsEnter, - "Comment"); + "Comment" + ); } /** @@ -58,7 +59,8 @@ function emitCommentsExit(generator, comments) { comments, generator.emitter, generator.commentLocsExit, - "Comment:exit"); + "Comment:exit" + ); } //------------------------------------------------------------------------------ diff --git a/lib/util/source-code.js b/lib/util/source-code.js index 28853370b5b2..b98892463f88 100644 --- a/lib/util/source-code.js +++ b/lib/util/source-code.js @@ -176,8 +176,10 @@ SourceCode.prototype = { */ getText(node, beforeCount, afterCount) { if (node) { - return this.text.slice(Math.max(node.range[0] - (beforeCount || 0), 0), - node.range[1] + (afterCount || 0)); + return this.text.slice( + Math.max(node.range[0] - (beforeCount || 0), 0), + node.range[1] + (afterCount || 0) + ); } return this.text; diff --git a/packages/eslint-config-eslint/default.yml b/packages/eslint-config-eslint/default.yml index 6f47d7d87ef7..5a42528d4199 100644 --- a/packages/eslint-config-eslint/default.yml +++ b/packages/eslint-config-eslint/default.yml @@ -24,6 +24,7 @@ rules: eqeqeq: "error" func-call-spacing: "error" func-style: ["error", "declaration"] + function-paren-newline: "error" generator-star-spacing: "error" guard-for-in: "error" key-spacing: ["error", { beforeColon: false, afterColon: true }] diff --git a/tests/lib/code-path-analysis/code-path-analyzer.js b/tests/lib/code-path-analysis/code-path-analyzer.js index c0377852511b..2971cfcbf0b4 100644 --- a/tests/lib/code-path-analysis/code-path-analyzer.js +++ b/tests/lib/code-path-analysis/code-path-analyzer.js @@ -58,9 +58,7 @@ describe("CodePathAnalyzer", () => { eslint.reset(); }); - EventGeneratorTester.testEventGeneratorInterface( - new CodePathAnalyzer(new NodeEventGenerator(new EventEmitter())) - ); + EventGeneratorTester.testEventGeneratorInterface(new CodePathAnalyzer(new NodeEventGenerator(new EventEmitter()))); describe("interface of code paths", () => { let actual = []; diff --git a/tests/lib/eslint.js b/tests/lib/eslint.js index 406302a69f0e..764ef8fbb3d0 100644 --- a/tests/lib/eslint.js +++ b/tests/lib/eslint.js @@ -1202,9 +1202,10 @@ describe("eslint", () => { }; eslint.reset(); - eslint.defineRule("test-rule", sandbox.mock().withArgs( - sinon.match({ parserOptions }) - ).returns({})); + eslint.defineRule( + "test-rule", + sandbox.mock().withArgs(sinon.match({ parserOptions })).returns({}) + ); const config = { rules: { "test-rule": 2 }, parserOptions }; @@ -1216,9 +1217,10 @@ describe("eslint", () => { const parserOptions = {}; eslint.reset(); - eslint.defineRule("test-rule", sandbox.mock().withArgs( - sinon.match({ parserOptions }) - ).returns({})); + eslint.defineRule( + "test-rule", + sandbox.mock().withArgs(sinon.match({ parserOptions })).returns({}) + ); const config = { rules: { "test-rule": 2 } }; @@ -1236,9 +1238,10 @@ describe("eslint", () => { const alternateParser = "esprima-fb"; eslint.reset(); - eslint.defineRule("test-rule", sandbox.mock().withArgs( - sinon.match({ parserPath: alternateParser }) - ).returns({})); + eslint.defineRule( + "test-rule", + sandbox.mock().withArgs(sinon.match({ parserPath: alternateParser })).returns({}) + ); const config = { rules: { "test-rule": 2 }, parser: alternateParser }; @@ -1284,9 +1287,10 @@ describe("eslint", () => { const DEFAULT_PARSER = eslint.defaults().parser; eslint.reset(); - eslint.defineRule("test-rule", sandbox.mock().withArgs( - sinon.match({ parserPath: DEFAULT_PARSER }) - ).returns({})); + eslint.defineRule( + "test-rule", + sandbox.mock().withArgs(sinon.match({ parserPath: DEFAULT_PARSER })).returns({}) + ); const config = { rules: { "test-rule": 2 } }; @@ -2893,8 +2897,7 @@ describe("eslint", () => { assert.equal(messages[0].ruleId, "no-alert"); }); - it("should report a violation for global variable declarations", - () => { + it("should report a violation for global variable declarations", () => { const code = [ "/* global foo */" ].join("\n"); diff --git a/tests/lib/ignored-paths.js b/tests/lib/ignored-paths.js index 381589883905..9caaaf67a598 100644 --- a/tests/lib/ignored-paths.js +++ b/tests/lib/ignored-paths.js @@ -158,11 +158,7 @@ describe("IgnoredPaths", () => { ignorePattern }); - assert.ok( - ignorePattern.every(pattern => - getIgnoreRules(ignoredPaths).some(rule => rule.pattern === pattern) - ) - ); + assert.ok(ignorePattern.every(pattern => getIgnoreRules(ignoredPaths).some(rule => rule.pattern === pattern))); }); }); diff --git a/tests/lib/rules/function-paren-newline.js b/tests/lib/rules/function-paren-newline.js new file mode 100644 index 000000000000..abc9a8653697 --- /dev/null +++ b/tests/lib/rules/function-paren-newline.js @@ -0,0 +1,552 @@ +/** + * @fileoverview enforce consistent line breaks inside function parentheses + * @author Teddy Katz + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/function-paren-newline"); +const RuleTester = require("../../../lib/testers/rule-tester"); + + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const LEFT_MISSING_ERROR = { message: "Expected a newline after '('.", type: "Punctuator" }; +const LEFT_UNEXPECTED_ERROR = { message: "Unexpected newline after '('.", type: "Punctuator" }; +const RIGHT_MISSING_ERROR = { message: "Expected a newline before ')'.", type: "Punctuator" }; +const RIGHT_UNEXPECTED_ERROR = { message: "Unexpected newline before ')'.", type: "Punctuator" }; + +const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } }); + +ruleTester.run("function-paren-newline", rule, { + + valid: [ + + // multiline option (default) + "function baz(foo, bar) {}", + "(function(foo, bar) {});", + "(function baz(foo, bar) {});", + "(foo, bar) => {};", + "foo => {};", + "baz(foo, bar);", + "function baz() {}", + ` + function baz( + foo, + bar + ) {} + `, + ` + (function( + foo, + bar + ) {}); + `, + ` + (function baz( + foo, + bar + ) {}); + `, + ` + ( + foo, + bar + ) => {}; + `, + ` + baz( + foo, + bar + ); + `, + ` + baz(\`foo + bar\`) + `, + "new Foo(bar, baz)", + "new Foo", + "new (Foo)", + + ` + (foo) + (bar) + `, + ` + foo.map(value => { + return value; + }) + `, + + // always option + { + code: "function baz(foo, bar) {}", + options: ["multiline"] + }, + { + code: ` + function baz( + foo, + bar + ) {} + `, + options: ["always"] + }, + { + code: ` + (function( + foo, + bar + ) {}); + `, + options: ["always"] + }, + { + code: ` + (function baz( + foo, + bar + ) {}); + `, + options: ["always"] + }, + { + code: ` + ( + foo, + bar + ) => {}; + `, + options: ["always"] + }, + { + code: ` + baz( + foo, + bar + ); + `, + options: ["always"] + }, + { + code: ` + function baz( + ) {} + `, + options: ["always"] + }, + + // never option + { + code: "function baz(foo, bar) {}", + options: ["never"] + }, + { + code: "(function(foo, bar) {});", + options: ["never"] + }, + { + code: "(function baz(foo, bar) {});", + options: ["never"] + }, + { + code: "(foo, bar) => {};", + options: ["never"] + }, + { + code: "baz(foo, bar);", + options: ["never"] + }, + { + code: "function baz() {}", + options: ["never"] + }, + + // minItems option + { + code: "function baz(foo, bar) {}", + options: [{ minItems: 3 }] + }, + { + code: ` + function baz( + foo, bar, qux + ) {} + `, + options: [{ minItems: 3 }] + }, + { + code: ` + baz( + foo, bar, qux + ); + `, + options: [{ minItems: 3 }] + }, + { + code: "baz(foo, bar);", + options: [{ minItems: 3 }] + } + ], + + invalid: [ + + // multiline option (default) + { + code: ` + function baz(foo, + bar + ) {} + `, + output: ` + function baz(\nfoo, + bar + ) {} + `, + errors: [LEFT_MISSING_ERROR] + }, + { + code: ` + (function( + foo, + bar) {}) + `, + output: ` + (function( + foo, + bar\n) {}) + `, + errors: [RIGHT_MISSING_ERROR] + }, + { + code: ` + (function baz(foo, + bar) {}) + `, + output: ` + (function baz(\nfoo, + bar\n) {}) + `, + errors: [LEFT_MISSING_ERROR, RIGHT_MISSING_ERROR] + }, + { + code: ` + baz( + foo, bar); + `, + output: ` + baz(foo, bar); + `, + errors: [LEFT_UNEXPECTED_ERROR] + }, + { + code: ` + (foo, bar + ) => {}; + `, + output: ` + (foo, bar) => {}; + `, + errors: [RIGHT_UNEXPECTED_ERROR] + }, + { + code: ` + function baz( + foo, bar + ) {} + `, + output: ` + function baz(foo, bar) {} + `, + errors: [LEFT_UNEXPECTED_ERROR, RIGHT_UNEXPECTED_ERROR] + }, + { + code: ` + function baz( + foo = + 1 + ) {} + `, + output: ` + function baz(foo = + 1) {} + `, + errors: [LEFT_UNEXPECTED_ERROR, RIGHT_UNEXPECTED_ERROR] + }, + { + code: ` + function baz( + ) {} + `, + output: ` + function baz() {} + `, + errors: [LEFT_UNEXPECTED_ERROR, RIGHT_UNEXPECTED_ERROR] + }, + { + code: ` + new Foo(bar, + baz); + `, + output: ` + new Foo(\nbar, + baz\n); + `, + errors: [LEFT_MISSING_ERROR, RIGHT_MISSING_ERROR] + }, + { + code: ` + function baz(/* not fixed due to comment */ + foo) {} + `, + output: ` + function baz(/* not fixed due to comment */ + foo) {} + `, + errors: [LEFT_UNEXPECTED_ERROR] + }, + { + code: ` + function baz(foo + /* not fixed due to comment */) {} + `, + output: ` + function baz(foo + /* not fixed due to comment */) {} + `, + errors: [RIGHT_UNEXPECTED_ERROR] + }, + + // always option + { + code: ` + function baz(foo, + bar + ) {} + `, + output: ` + function baz(\nfoo, + bar + ) {} + `, + options: ["always"], + errors: [LEFT_MISSING_ERROR] + }, + { + code: ` + (function( + foo, + bar) {}) + `, + output: ` + (function( + foo, + bar\n) {}) + `, + options: ["always"], + errors: [RIGHT_MISSING_ERROR] + }, + { + code: ` + (function baz(foo, + bar) {}) + `, + output: ` + (function baz(\nfoo, + bar\n) {}) + `, + options: ["always"], + errors: [LEFT_MISSING_ERROR, RIGHT_MISSING_ERROR] + }, + { + code: "function baz(foo, bar) {}", + output: "function baz(\nfoo, bar\n) {}", + options: ["always"], + errors: [LEFT_MISSING_ERROR, RIGHT_MISSING_ERROR] + }, + { + code: "(function(foo, bar) {});", + output: "(function(\nfoo, bar\n) {});", + options: ["always"], + errors: [LEFT_MISSING_ERROR, RIGHT_MISSING_ERROR] + }, + { + code: "(function baz(foo, bar) {});", + output: "(function baz(\nfoo, bar\n) {});", + options: ["always"], + errors: [LEFT_MISSING_ERROR, RIGHT_MISSING_ERROR] + }, + { + code: "(foo, bar) => {};", + output: "(\nfoo, bar\n) => {};", + options: ["always"], + errors: [LEFT_MISSING_ERROR, RIGHT_MISSING_ERROR] + }, + { + code: "baz(foo, bar);", + output: "baz(\nfoo, bar\n);", + options: ["always"], + errors: [LEFT_MISSING_ERROR, RIGHT_MISSING_ERROR] + }, + { + code: "function baz() {}", + output: "function baz(\n) {}", + options: ["always"], + errors: [LEFT_MISSING_ERROR, RIGHT_MISSING_ERROR] + }, + + // never option + { + code: ` + function baz(foo, + bar + ) {} + `, + output: ` + function baz(foo, + bar) {} + `, + options: ["never"], + errors: [RIGHT_UNEXPECTED_ERROR] + }, + { + code: ` + (function( + foo, + bar) {}) + `, + output: ` + (function(foo, + bar) {}) + `, + options: ["never"], + errors: [LEFT_UNEXPECTED_ERROR] + }, + { + code: ` + function baz( + foo, + bar + ) {} + `, + output: ` + function baz(foo, + bar) {} + `, + options: ["never"], + errors: [LEFT_UNEXPECTED_ERROR, RIGHT_UNEXPECTED_ERROR] + }, + { + code: ` + (function( + foo, + bar + ) {}); + `, + output: ` + (function(foo, + bar) {}); + `, + options: ["never"], + errors: [LEFT_UNEXPECTED_ERROR, RIGHT_UNEXPECTED_ERROR] + }, + { + code: ` + (function baz( + foo, + bar + ) {}); + `, + output: ` + (function baz(foo, + bar) {}); + `, + options: ["never"], + errors: [LEFT_UNEXPECTED_ERROR, RIGHT_UNEXPECTED_ERROR] + }, + { + code: ` + ( + foo, + bar + ) => {}; + `, + output: ` + (foo, + bar) => {}; + `, + options: ["never"], + errors: [LEFT_UNEXPECTED_ERROR, RIGHT_UNEXPECTED_ERROR] + }, + { + code: ` + baz( + foo, + bar + ); + `, + output: ` + baz(foo, + bar); + `, + options: ["never"], + errors: [LEFT_UNEXPECTED_ERROR, RIGHT_UNEXPECTED_ERROR] + }, + { + code: ` + function baz( + ) {} + `, + output: ` + function baz() {} + `, + options: ["never"], + errors: [LEFT_UNEXPECTED_ERROR, RIGHT_UNEXPECTED_ERROR] + }, + + // minItems option + { + code: "function baz(foo, bar, qux) {}", + output: "function baz(\nfoo, bar, qux\n) {}", + options: [{ minItems: 3 }], + errors: [LEFT_MISSING_ERROR, RIGHT_MISSING_ERROR] + }, + { + code: ` + function baz( + foo, bar + ) {} + `, + output: ` + function baz(foo, bar) {} + `, + options: [{ minItems: 3 }], + errors: [LEFT_UNEXPECTED_ERROR, RIGHT_UNEXPECTED_ERROR] + }, + { + code: "baz(foo, bar, qux);", + output: "baz(\nfoo, bar, qux\n);", + options: [{ minItems: 3 }], + errors: [LEFT_MISSING_ERROR, RIGHT_MISSING_ERROR] + }, + { + code: ` + baz( + foo, + bar + ); + `, + output: ` + baz(foo, + bar); + `, + options: [{ minItems: 3 }], + errors: [LEFT_UNEXPECTED_ERROR, RIGHT_UNEXPECTED_ERROR] + } + ] +}); diff --git a/tests/lib/rules/indent.js b/tests/lib/rules/indent.js index 11c8e3dc62f6..7cf6919d1011 100644 --- a/tests/lib/rules/indent.js +++ b/tests/lib/rules/indent.js @@ -2278,9 +2278,7 @@ ruleTester.run("indent", rule, { " .bar\n" + "}", options: [4, { MemberExpression: 1 }], - errors: expectedErrors( - [3, 8, 10, "Punctuator"] - ) + errors: expectedErrors([3, 8, 10, "Punctuator"]) }, { code: @@ -2289,9 +2287,7 @@ ruleTester.run("indent", rule, { " .bar\n" + "}", options: [4, { MemberExpression: 2 }], - errors: expectedErrors( - [3, 12, 13, "Punctuator"] - ) + errors: expectedErrors([3, 12, 13, "Punctuator"]) }, { code: @@ -2301,9 +2297,7 @@ ruleTester.run("indent", rule, { "}", options: [4, { MemberExpression: 2 }], parserOptions: { ecmaVersion: 6 }, - errors: expectedErrors( - [3, 12, 13, "Punctuator"] - ) + errors: expectedErrors([3, 12, 13, "Punctuator"]) }, { code: @@ -2315,11 +2309,7 @@ ruleTester.run("indent", rule, { "};", options: [2, { MemberExpression: 1 }], parserOptions: { ecmaVersion: 6 }, - errors: expectedErrors( - [ - [3, 4, 6, "Punctuator"] - ] - ) + errors: expectedErrors([3, 4, 6, "Punctuator"]) }, { code: diff --git a/tests/lib/token-store.js b/tests/lib/token-store.js index a465918f633f..d11dde58662a 100644 --- a/tests/lib/token-store.js +++ b/tests/lib/token-store.js @@ -643,9 +643,7 @@ describe("TokenStore", () => { // Actually, the first of nodes is always tokens, not comments. // But I think this test case is needed for completeness. - const token = tokenStore.getFirstToken( - { range: [ast.comments[0].range[0], ast.tokens[5].range[1]] } - ); + const token = tokenStore.getFirstToken({ range: [ast.comments[0].range[0], ast.tokens[5].range[1]] }); assert.strictEqual(token.value, "c"); }); @@ -826,9 +824,7 @@ describe("TokenStore", () => { // Actually, the last of nodes is always tokens, not comments. // But I think this test case is needed for completeness. - const token = tokenStore.getLastToken( - { range: [ast.tokens[0].range[0], ast.comments[0].range[1]] } - ); + const token = tokenStore.getLastToken({ range: [ast.tokens[0].range[0], ast.comments[0].range[1]] }); assert.strictEqual(token.value, "b"); }); diff --git a/tests/lib/util/comment-event-generator.js b/tests/lib/util/comment-event-generator.js index bbec4bde96fe..b319abbe15ca 100644 --- a/tests/lib/util/comment-event-generator.js +++ b/tests/lib/util/comment-event-generator.js @@ -23,9 +23,7 @@ const assert = require("assert"), //------------------------------------------------------------------------------ describe("NodeEventGenerator", () => { - EventGeneratorTester.testEventGeneratorInterface( - new CommentEventGenerator(new NodeEventGenerator(new EventEmitter())) - ); + EventGeneratorTester.testEventGeneratorInterface(new CommentEventGenerator(new NodeEventGenerator(new EventEmitter()))); it("should generate comment events without duplicate.", () => { const emitter = new EventEmitter(); diff --git a/tests/lib/util/node-event-generator.js b/tests/lib/util/node-event-generator.js index faf63e698be7..3cfdb0ad7f93 100644 --- a/tests/lib/util/node-event-generator.js +++ b/tests/lib/util/node-event-generator.js @@ -19,9 +19,7 @@ const assert = require("assert"), //------------------------------------------------------------------------------ describe("NodeEventGenerator", () => { - EventGeneratorTester.testEventGeneratorInterface( - new NodeEventGenerator(new EventEmitter()) - ); + EventGeneratorTester.testEventGeneratorInterface(new NodeEventGenerator(new EventEmitter())); let emitter, generator; diff --git a/tests/lib/util/source-code.js b/tests/lib/util/source-code.js index ef4864f37c00..314a47e1c1a5 100644 --- a/tests/lib/util/source-code.js +++ b/tests/lib/util/source-code.js @@ -175,7 +175,8 @@ describe("SourceCode", () => { it("should not has BOM in `text` property.", () => { assert.equal( sourceCode.text, - "\"use strict\";\n\nconsole.log(\"This file has [0xEF, 0xBB, 0xBF] as BOM.\");\n"); + "\"use strict\";\n\nconsole.log(\"This file has [0xEF, 0xBB, 0xBF] as BOM.\");\n" + ); }); }); }); @@ -1158,9 +1159,7 @@ describe("SourceCode", () => { sourceCode = new SourceCode(code, ast); assert.equal( - sourceCode.isSpaceBetweenTokens( - sourceCode.ast.tokens[0], sourceCode.ast.tokens[1] - ), + sourceCode.isSpaceBetweenTokens(sourceCode.ast.tokens[0], sourceCode.ast.tokens[1]), expected ); });