diff --git a/lib/rules/newline-after-var.js b/lib/rules/newline-after-var.js index 9e84f441abd..433fa7ebf8b 100644 --- a/lib/rules/newline-after-var.js +++ b/lib/rules/newline-after-var.js @@ -45,6 +45,37 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- + /** + * Gets a token from the given node to compare line to the next statement. + * + * In general, the token is the last token of the node. However, the token is the second last token if the following conditions satisfy. + * + * - The last token is semicolon. + * - The semicolon is on a different line from the previous token of the semicolon. + * + * This behavior would address semicolon-less style code. e.g.: + * + * var foo = 1 + * + * ;(a || b).doSomething() + * + * @param {ASTNode} node - The node to get. + * @returns {Token} The token to compare line to the next statement. + */ + function getLastToken(node) { + const lastToken = sourceCode.getLastToken(node); + + if (lastToken.type === "Punctuator" && lastToken.value === ";") { + const prevToken = sourceCode.getTokenBefore(lastToken); + + if (prevToken.loc.end.line !== lastToken.loc.start.line) { + return prevToken; + } + } + + return lastToken; + } + /** * Determine if provided keyword is a variable declaration * @private @@ -114,7 +145,7 @@ module.exports = { * @returns {void} */ function checkForBlankLine(node) { - const lastToken = sourceCode.getLastToken(node), + const lastToken = getLastToken(node), nextToken = sourceCode.getTokenAfter(node), nextLineNum = lastToken.loc.end.line + 1; diff --git a/tests/lib/rules/newline-after-var.js b/tests/lib/rules/newline-after-var.js index 85a5c48b5fe..6ed4429e4e2 100644 --- a/tests/lib/rules/newline-after-var.js +++ b/tests/lib/rules/newline-after-var.js @@ -224,7 +224,24 @@ ruleTester.run("newline-after-var", rule, { // should handle one/no blank before case. { code: ONE_BLANK_BEFORE_CASE, options: ["always"] }, - { code: NO_BLANK_BEFORE_CASE, options: ["never"] } + { code: NO_BLANK_BEFORE_CASE, options: ["never"] }, + + // https://github.com/eslint/eslint/issues/6834 + { + code: ` + var a = 1 + + ;(b || c).doSomething() + `, + options: ["always"] + }, + { + code: ` + var a = 1 + ;(b || c).doSomething() + `, + options: ["never"] + }, ], invalid: [ @@ -268,6 +285,25 @@ ruleTester.run("newline-after-var", rule, { { code: MULTI_LINE_NEXT_LINE_COMMENT, options: ["always"], errors: [ALWAYS_ERROR] }, { code: MULTI_LINE_NEXT_LINE_BLOCK_COMMENT, options: ["always"], errors: [ALWAYS_ERROR] }, { code: NEXT_LINE_TWO_COMMENTS_NO_BLANK, options: ["always"], errors: [ALWAYS_ERROR] }, - { code: NEXT_LINE_COMMENT_BLOCK_COMMENT_NO_BLANK, options: ["always"], errors: [ALWAYS_ERROR] } + { code: NEXT_LINE_COMMENT_BLOCK_COMMENT_NO_BLANK, options: ["always"], errors: [ALWAYS_ERROR] }, + + // https://github.com/eslint/eslint/issues/6834 + { + code: ` + var a = 1 + ;(b || c).doSomething() + `, + options: ["always"], + errors: [ALWAYS_ERROR] + }, + { + code: ` + var a = 1 + + ;(b || c).doSomething() + `, + options: ["never"], + errors: [NEVER_ERROR] + }, ] });