diff --git a/docs/rules/padding-line-between-statements.md b/docs/rules/padding-line-between-statements.md index 390dada294e..1f2c4ab8950 100644 --- a/docs/rules/padding-line-between-statements.md +++ b/docs/rules/padding-line-between-statements.md @@ -52,7 +52,7 @@ You can supply any number of configurations. If a statement pair matches multipl - `"cjs-export"` is `export` statements of CommonJS; e.g. `module.exports = 0`, `module.exports.foo = 1`, and `exports.foo = 2`. This is a special case of assignment. - `"cjs-import"` is `import` statements of CommonJS; e.g. `const foo = require("foo")`. This is a special case of variable declarations. - `"class"` is `class` declarations. - - `"const"` is `const` variable declarations. + - `"const"` is `const` variable declarations, both single-line and multiline. - `"continue"` is `continue` statements. - `"debugger"` is `debugger` statements. - `"default"` is `default` labels. @@ -66,14 +66,20 @@ You can supply any number of configurations. If a statement pair matches multipl - `"if"` is `if` statements. - `"iife"` is immediately invoked function expression statements. This matches calls on a function expression, optionally prefixed with a unary operator. - `"import"` is `import` declarations. - - `"let"` is `let` variable declarations. + - `"let"` is `let` variable declarations, both single-line and multiline. - `"multiline-block-like"` is block like statements. This is the same as `block-like` type, but only if the block is multiline. + - `"multiline-const"` is multiline `const` variable declarations. - `"multiline-expression"` is expression statements. This is the same as `expression` type, but only if the statement is multiline. + - `"multiline-let"` is multiline `let` variable declarations. + - `"multiline-var"` is multiline `var` variable declarations. - `"return"` is `return` statements. + - `"singleline-const"` is single-line `const` variable declarations. + - `"singleline-let"` is single-line `let` variable declarations. + - `"singleline-var"` is single-line `var` variable declarations. - `"switch"` is `switch` statements. - `"throw"` is `throw` statements. - `"try"` is `try` statements. - - `"var"` is `var` variable declarations. + - `"var"` is `var` variable declarations, both single-line and multiline. - `"while"` is `while` loop statements. - `"with"` is `with` statements. diff --git a/lib/rules/padding-line-between-statements.js b/lib/rules/padding-line-between-statements.js index 3e55a2516d0..c9995885442 100644 --- a/lib/rules/padding-line-between-statements.js +++ b/lib/rules/padding-line-between-statements.js @@ -36,6 +36,36 @@ function newKeywordTester(keyword) { }; } +/** + * Creates tester which check if a node starts with specific keyword and spans a single line. + * + * @param {string} keyword The keyword to test. + * @returns {Object} the created tester. + * @private + */ +function newSinglelineKeywordTester(keyword) { + return { + test: (node, sourceCode) => + node.loc.start.line === node.loc.end.line && + sourceCode.getFirstToken(node).value === keyword + }; +} + +/** + * Creates tester which check if a node starts with specific keyword and spans multiple lines. + * + * @param {string} keyword The keyword to test. + * @returns {Object} the created tester. + * @private + */ +function newMultilineKeywordTester(keyword) { + return { + test: (node, sourceCode) => + node.loc.start.line !== node.loc.end.line && + sourceCode.getFirstToken(node).value === keyword + }; +} + /** * Creates tester which check if a node is specific type. * @@ -368,6 +398,13 @@ const StatementTypes = { !isDirectivePrologue(node, sourceCode) }, + "multiline-const": newMultilineKeywordTester("const"), + "multiline-let": newMultilineKeywordTester("let"), + "multiline-var": newMultilineKeywordTester("var"), + "singleline-const": newSinglelineKeywordTester("const"), + "singleline-let": newSinglelineKeywordTester("let"), + "singleline-var": newSinglelineKeywordTester("var"), + block: newNodeTypeTester("BlockStatement"), empty: newNodeTypeTester("EmptyStatement"), function: newNodeTypeTester("FunctionDeclaration"), diff --git a/tests/lib/rules/padding-line-between-statements.js b/tests/lib/rules/padding-line-between-statements.js index 82147d389d4..dc5d81c42a2 100644 --- a/tests/lib/rules/padding-line-between-statements.js +++ b/tests/lib/rules/padding-line-between-statements.js @@ -1071,6 +1071,204 @@ ruleTester.run("padding-line-between-statements", rule, { ] }, + //---------------------------------------------------------------------- + // multiline-const + //---------------------------------------------------------------------- + + { + code: "const a={\nb:1,\nc:2\n}\n\nconst d=3", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "multiline-const", next: "*" } + ] + }, + { + code: "const a=1\n\nconst b={\nc:2,\nd:3\n}", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "*", next: "multiline-const" } + ] + }, + { + code: "const a=1\nconst b=2", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "multiline-const", next: "*" } + ] + }, + { + code: "const a=1\nconst b=2", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "*", next: "multiline-const" } + ] + }, + + //---------------------------------------------------------------------- + // multiline-let + //---------------------------------------------------------------------- + + { + code: "let a={\nb:1,\nc:2\n}\n\nlet d=3", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "multiline-let", next: "*" } + ] + }, + { + code: "let a=1\n\nlet b={\nc:2,\nd:3\n}", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "*", next: "multiline-let" } + ] + }, + { + code: "let a=1\nlet b=2", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "multiline-let", next: "*" } + ] + }, + { + code: "let a=1\nlet b=2", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "*", next: "multiline-let" } + ] + }, + + //---------------------------------------------------------------------- + // multiline-var + //---------------------------------------------------------------------- + + { + code: "var a={\nb:1,\nc:2\n}\n\nvar d=3", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "multiline-var", next: "*" } + ] + }, + { + code: "var a=1\n\nvar b={\nc:2,\nd:3\n}", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "*", next: "multiline-var" } + ] + }, + { + code: "var a=1\nvar b=2", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "multiline-var", next: "*" } + ] + }, + { + code: "var a=1\nvar b=2", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "*", next: "multiline-var" } + ] + }, + + //---------------------------------------------------------------------- + // singleline-const + //---------------------------------------------------------------------- + + { + code: "const a=1\n\nconst b=2", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "singleline-const", next: "*" } + ] + }, + { + code: "const a=1\n\nconst b=2", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "*", next: "singleline-const" } + ] + }, + { + code: "const a={\nb:1,\nc:2\n}\nconst d={\ne:3,\nf:4\n}", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "singleline-const", next: "*" } + ] + }, + { + code: "const a={\nb:1,\nc:2\n}\nconst d={\ne:3,\nf:4\n}", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "*", next: "singleline-const" } + ] + }, + + //---------------------------------------------------------------------- + // singleline-let + //---------------------------------------------------------------------- + + { + code: "let a=1\n\nlet b=2", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "singleline-let", next: "*" } + ] + }, + { + code: "let a=1\n\nlet b=2", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "*", next: "singleline-let" } + ] + }, + { + code: "let a={\nb:1,\nc:2\n}\nlet d={\ne:3,\nf:4\n}", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "singleline-let", next: "*" } + ] + }, + { + code: "let a={\nb:1,\nc:2\n}\nlet d={\ne:3,\nf:4\n}", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "*", next: "singleline-let" } + ] + }, + + //---------------------------------------------------------------------- + // singleline-var + //---------------------------------------------------------------------- + + { + code: "var a=1\n\nvar b=2", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "singleline-var", next: "*" } + ] + }, + { + code: "var a=1\n\nvar b=2", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "*", next: "singleline-var" } + ] + }, + { + code: "var a={\nb:1,\nc:2\n}\nvar d={\ne:3,\nf:4\n}", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "singleline-var", next: "*" } + ] + }, + { + code: "var a={\nb:1,\nc:2\n}\nvar d={\ne:3,\nf:4\n}", + options: [ + { blankLine: "never", prev: "*", next: "*" }, + { blankLine: "always", prev: "*", next: "singleline-var" } + ] + }, + //---------------------------------------------------------------------- // Tests from newline-after-var //---------------------------------------------------------------------- @@ -3696,6 +3894,228 @@ ruleTester.run("padding-line-between-statements", rule, { errors: [MESSAGE_ALWAYS] }, + //---------------------------------------------------------------------- + // multiline-const + //---------------------------------------------------------------------- + + { + code: "const a={\nb:1,\nc:2\n}\n\nconst d=3", + output: "const a={\nb:1,\nc:2\n}\nconst d=3", + options: [ + { blankLine: "never", prev: "multiline-const", next: "*" } + ], + errors: [MESSAGE_NEVER] + }, + { + code: "const a={\nb:1,\nc:2\n}\nconst d=3", + output: "const a={\nb:1,\nc:2\n}\n\nconst d=3", + options: [ + { blankLine: "always", prev: "multiline-const", next: "*" } + ], + errors: [MESSAGE_ALWAYS] + }, + { + code: "const a=1\n\nconst b={\nc:2,\nd:3\n}", + output: "const a=1\nconst b={\nc:2,\nd:3\n}", + options: [ + { blankLine: "never", prev: "*", next: "multiline-const" } + ], + errors: [MESSAGE_NEVER] + }, + { + code: "const a=1\nconst b={\nc:2,\nd:3\n}", + output: "const a=1\n\nconst b={\nc:2,\nd:3\n}", + options: [ + { blankLine: "always", prev: "*", next: "multiline-const" } + ], + errors: [MESSAGE_ALWAYS] + }, + + //---------------------------------------------------------------------- + // multiline-let + //---------------------------------------------------------------------- + + { + code: "let a={\nb:1,\nc:2\n}\n\nlet d=3", + output: "let a={\nb:1,\nc:2\n}\nlet d=3", + options: [ + { blankLine: "never", prev: "multiline-let", next: "*" } + ], + errors: [MESSAGE_NEVER] + }, + { + code: "let a={\nb:1,\nc:2\n}\nlet d=3", + output: "let a={\nb:1,\nc:2\n}\n\nlet d=3", + options: [ + { blankLine: "always", prev: "multiline-let", next: "*" } + ], + errors: [MESSAGE_ALWAYS] + }, + { + code: "let a=1\n\nlet b={\nc:2,\nd:3\n}", + output: "let a=1\nlet b={\nc:2,\nd:3\n}", + options: [ + { blankLine: "never", prev: "*", next: "multiline-let" } + ], + errors: [MESSAGE_NEVER] + }, + { + code: "let a=1\nlet b={\nc:2,\nd:3\n}", + output: "let a=1\n\nlet b={\nc:2,\nd:3\n}", + options: [ + { blankLine: "always", prev: "*", next: "multiline-let" } + ], + errors: [MESSAGE_ALWAYS] + }, + + //---------------------------------------------------------------------- + // multiline-var + //---------------------------------------------------------------------- + + { + code: "var a={\nb:1,\nc:2\n}\n\nvar d=3", + output: "var a={\nb:1,\nc:2\n}\nvar d=3", + options: [ + { blankLine: "never", prev: "multiline-var", next: "*" } + ], + errors: [MESSAGE_NEVER] + }, + { + code: "var a={\nb:1,\nc:2\n}\nvar d=3", + output: "var a={\nb:1,\nc:2\n}\n\nvar d=3", + options: [ + { blankLine: "always", prev: "multiline-var", next: "*" } + ], + errors: [MESSAGE_ALWAYS] + }, + { + code: "var a=1\n\nvar b={\nc:2,\nd:3\n}", + output: "var a=1\nvar b={\nc:2,\nd:3\n}", + options: [ + { blankLine: "never", prev: "*", next: "multiline-var" } + ], + errors: [MESSAGE_NEVER] + }, + { + code: "var a=1\nvar b={\nc:2,\nd:3\n}", + output: "var a=1\n\nvar b={\nc:2,\nd:3\n}", + options: [ + { blankLine: "always", prev: "*", next: "multiline-var" } + ], + errors: [MESSAGE_ALWAYS] + }, + + //---------------------------------------------------------------------- + // singleline-const + //---------------------------------------------------------------------- + + { + code: "const a=1\n\nconst b=2", + output: "const a=1\nconst b=2", + options: [ + { blankLine: "never", prev: "singleline-const", next: "*" } + ], + errors: [MESSAGE_NEVER] + }, + { + code: "const a=1\nconst b=2", + output: "const a=1\n\nconst b=2", + options: [ + { blankLine: "always", prev: "singleline-const", next: "*" } + ], + errors: [MESSAGE_ALWAYS] + }, + { + code: "const a=1\n\nconst b=2", + output: "const a=1\nconst b=2", + options: [ + { blankLine: "never", prev: "*", next: "singleline-const" } + ], + errors: [MESSAGE_NEVER] + }, + { + code: "const a=1\nconst b=2", + output: "const a=1\n\nconst b=2", + options: [ + { blankLine: "always", prev: "*", next: "singleline-const" } + ], + errors: [MESSAGE_ALWAYS] + }, + + //---------------------------------------------------------------------- + // singleline-let + //---------------------------------------------------------------------- + + { + code: "let a=1\n\nlet b=2", + output: "let a=1\nlet b=2", + options: [ + { blankLine: "never", prev: "singleline-let", next: "*" } + ], + errors: [MESSAGE_NEVER] + }, + { + code: "let a=1\nlet b=2", + output: "let a=1\n\nlet b=2", + options: [ + { blankLine: "always", prev: "singleline-let", next: "*" } + ], + errors: [MESSAGE_ALWAYS] + }, + { + code: "let a=1\n\nlet b=2", + output: "let a=1\nlet b=2", + options: [ + { blankLine: "never", prev: "*", next: "singleline-let" } + ], + errors: [MESSAGE_NEVER] + }, + { + code: "let a=1\nlet b=2", + output: "let a=1\n\nlet b=2", + options: [ + { blankLine: "always", prev: "*", next: "singleline-let" } + ], + errors: [MESSAGE_ALWAYS] + }, + + //---------------------------------------------------------------------- + // singleline-var + //---------------------------------------------------------------------- + + { + code: "var a=1\n\nvar b=2", + output: "var a=1\nvar b=2", + options: [ + { blankLine: "never", prev: "singleline-var", next: "*" } + ], + errors: [MESSAGE_NEVER] + }, + { + code: "var a=1\nvar b=2", + output: "var a=1\n\nvar b=2", + options: [ + { blankLine: "always", prev: "singleline-var", next: "*" } + ], + errors: [MESSAGE_ALWAYS] + }, + { + code: "var a=1\n\nvar b=2", + output: "var a=1\nvar b=2", + options: [ + { blankLine: "never", prev: "*", next: "singleline-var" } + ], + errors: [MESSAGE_NEVER] + }, + { + code: "var a=1\nvar b=2", + output: "var a=1\n\nvar b=2", + options: [ + { blankLine: "always", prev: "*", next: "singleline-var" } + ], + errors: [MESSAGE_ALWAYS] + }, + //---------------------------------------------------------------------- // Tests from newline-after-var //----------------------------------------------------------------------