Skip to content

Commit

Permalink
modify options & update docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
薛定谔的猫 authored and aladdin-add committed Sep 15, 2017
1 parent af58efc commit 796985e
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 205 deletions.
2 changes: 1 addition & 1 deletion conf/eslint-recommended.js
Expand Up @@ -63,6 +63,7 @@ module.exports = {
"linebreak-style": "off",
"lines-around-comment": "off",
"lines-around-directive": "off",
"lines-between-class-members": "off",
"max-depth": "off",
"max-len": "off",
"max-lines": "off",
Expand Down Expand Up @@ -221,7 +222,6 @@ module.exports = {
"operator-assignment": "off",
"operator-linebreak": "off",
"padded-blocks": "off",
"padding-line-after-class-members": "off",
"padding-line-between-statements": "off",
"prefer-arrow-callback": "off",
"prefer-const": "off",
Expand Down
73 changes: 9 additions & 64 deletions docs/rules/lines-between-class-members.md
@@ -1,6 +1,6 @@
# require or disallow an empty line after after class members (lines-between-class-members)
# require or disallow an empty line between class members (lines-between-class-members)

This rule improves readability by enforcing lines between class members. it will not check empty lines before the first member and after the last member, since that is already taken care of by padded-blocks.
This rule improves readability by enforcing lines between class members. It will not check empty lines before the first member and after the last member, since that is already taken care of by padded-blocks.

## Rule Details

Expand Down Expand Up @@ -44,10 +44,8 @@ String option:

Object option:

* `"multiline": "always"` require an empty line after after multiline class members
* `"multiline": "never"` disallows an empty line after after multiline class members
* `"singleline": "always"` require an empty line after after singleline class members
* `"singleline": "never"` disallows an empty line after after singleline class members
* `"exceptAfterSingleLine": "false"`(default) **do not** skip checking empty lines after singleline class members
* `"exceptAfterSingleLine": "true"` skip checking empty lines after singleline class members

Examples of **incorrect** code for this rule with the string option:

Expand Down Expand Up @@ -83,70 +81,17 @@ class Foo{
}
```

Examples of **incorrect** code for this rule with the object option:
Examples of **correct** code for this rule with the object option:

```js
/* eslint lines-between-class-members: ["error", { multiline: "always" }]*/
class Foo{
bar(){
bar();
}
baz(){}
}

/* eslint lines-between-class-members: ["error", { multiline: "never" }]*/
class Foo{
bar(){
bar();
}

baz(){}
}

/* eslint lines-between-class-members: ["error", { singleline: "always" }]*/
class Foo{
bar(){}
baz(){}
}

/* eslint lines-between-class-members: ["error", { singleline: "never" }]*/
/* eslint lines-between-class-members: ["error", "always", { exceptAfterSingleLine: true }]*/
class Foo{
bar(){}

baz(){}
}
```

Examples of **correct** code for this rule with the object option:

```js
/* eslint lines-between-class-members: ["error", { multiline: "always" }]*/
class Foo{
bar(){
bar();
}

baz(){}
}
## Related Rules

/* eslint lines-between-class-members: ["error", { multiline: "never" }]*/
class Foo{
bar(){
bar();
}
baz(){}
}

/* eslint lines-between-class-members: ["error", { singleline: "always" }]*/
class Foo{
bar(){}

baz(){}
}

/* eslint lines-between-class-members: ["error", { singleline: "never" }]*/
class Foo{
bar(){}
baz(){}
}
```
* [padded-blocks](padded-blocks.md)
* [padding-line-between-statement](padding-line-between-statement.md)
65 changes: 29 additions & 36 deletions lib/rules/lines-between-class-members.js
Expand Up @@ -28,27 +28,20 @@ module.exports = {
type: "object",
properties: {
exceptAfterSingleLine: {
enum: [true, false]
type: "boolean"
}
},
additionalProperties: false,
minProperties: 0
additionalProperties: false
}
]
},

create(context) {

const options = {};
const config = context.options[0] || "always";
const options = [];

if (typeof config === "string") {
options.multiline = options.singleline = config;
}

if (context.options[1].exceptAfterSingleLine) {
options.singleline = "never";
}
options[0] = context.options[0] || "always";
options[1] = context.options[1] || { exceptAfterSingleLine: false };

const ALWAYS_MESSAGE = "Expected blank line between class members.";
const NEVER_MESSAGE = "Unexpected blank line between class members.";
Expand All @@ -71,34 +64,34 @@ module.exports = {
* @returns {void} undefined.
*/
function checkPadding(node) {

const body = node.body;

for (let i = 0; i < body.length - 1; i++) {

// only check padding lines after methods definition.
if (body[i] && body[i].type !== "MethodDefinition") {
continue;
}

const curFirst = sourceCode.getFirstToken(body[i]);
const curLast = sourceCode.getLastToken(body[i]);
const comments = sourceCode.getCommentsBefore(body[i + 1]);
const nextFirst = comments.length ? comments[0] : sourceCode.getFirstToken(body[i + 1]);
const isPadded = isPaddingBetweenTokens(curLast, nextFirst);
const isMulti = !astUtils.isTokenOnSameLine(curFirst, curLast);

if ((isMulti && options.multiline && (options.multiline === "always") !== isPadded) ||
!isMulti && options.singleline && (options.singleline === "always") !== isPadded) {
context.report({
node: body[i + 1],
message: isPadded ? NEVER_MESSAGE : ALWAYS_MESSAGE,
fix(fixer) {
return isPadded
? fixer.replaceTextRange([curLast.range[1], nextFirst.range[0]], "\n")
: fixer.insertTextAfter(curLast, "\n");
}
});
// only check padding lines after class members(skip empty).
if (body[i]) {

const curFirst = sourceCode.getFirstToken(body[i]);
const curLast = sourceCode.getLastToken(body[i]);
const comments = sourceCode.getCommentsBefore(body[i + 1]);
const nextFirst = comments.length ? comments[0] : sourceCode.getFirstToken(body[i + 1]);
const isPadded = isPaddingBetweenTokens(curLast, nextFirst);
const isMulti = !astUtils.isTokenOnSameLine(curFirst, curLast);
const skip = !isMulti && options[1].exceptAfterSingleLine;


if ((options[0] === "always" && !skip && !isPadded) ||
(options[0] === "never" && isPadded)) {
context.report({
node: body[i + 1],
message: isPadded ? NEVER_MESSAGE : ALWAYS_MESSAGE,
fix(fixer) {
return isPadded
? fixer.replaceTextRange([curLast.range[1], nextFirst.range[0]], "\n")
: fixer.insertTextAfter(curLast, "\n");
}
});
}
}
}
}
Expand Down
109 changes: 5 additions & 104 deletions tests/lib/rules/lines-between-class-members.js
Expand Up @@ -25,7 +25,7 @@ const NEVER_MESSAGE = "Unexpected blank line between class members.";

const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });

ruleTester.run("lines-between-class-methods", rule, {
ruleTester.run("lines-between-class-members", rule, {
valid: [
"class foo{}",
"class foo{\n\n}",
Expand All @@ -44,124 +44,25 @@ ruleTester.run("lines-between-class-methods", rule, {
{ code: "class foo{ bar(){}\n\n/*comments*/baz(){}}", options: ["always"] },
{ code: "class foo{ bar(){}\n\n//comments\nbaz(){}}", options: ["always"] },

{ code: "class foo{ bar(){\n}\n\nbaz(){}}", options: [{ multiline: "always" }] },
{ code: "class foo{ bar(){\n}\n\n/*comments*/baz(){}}", options: [{ multiline: "always" }] },
{ code: "class foo{ bar(){\n}\n\n//comments\nbaz(){}}", options: [{ multiline: "always" }] },
{ code: "class foo{ bar(){}\nbaz(){}}", options: [{ multiline: "always" }] },
{ code: "class foo{ bar(){}\n\nbaz(){}}", options: [{ multiline: "always" }] },

{ code: "class foo{ bar(){\n}\nbaz(){}}", options: [{ multiline: "never" }] },
{ code: "class foo{ bar(){\n}\n/*comments*/baz(){}}", options: [{ multiline: "never" }] },
{ code: "class foo{ bar(){\n}\n//comments\nbaz(){}}", options: [{ multiline: "never" }] },
{ code: "class foo{ bar(){}\nbaz(){}}", options: [{ multiline: "never" }] },
{ code: "class foo{ bar(){}\n\nbaz(){}}", options: [{ multiline: "never" }] },

{ code: "class foo{ bar(){}\n\nbaz(){}}", options: [{ singleline: "always" }] },
{ code: "class foo{ bar(){}\n\n/*comments*/baz(){}}", options: [{ singleline: "always" }] },
{ code: "class foo{ bar(){}\n\n//comments\nbaz(){}}", options: [{ singleline: "always" }] },

{ code: "class foo{ bar(){}\nbaz(){}}", options: [{ singleline: "never" }] },
{ code: "class foo{ bar(){}\n/*comments*/baz(){}}", options: [{ singleline: "never" }] },
{ code: "class foo{ bar(){}\n//comments\nbaz(){}}", options: [{ singleline: "never" }] }
{ code: "class foo{ bar(){}\nbaz(){}}", options: ["always", { exceptAfterSingleLine: true }] },
{ code: "class foo{ bar(){\n}\n\nbaz(){}}", options: ["always", { exceptAfterSingleLine: true }] }
],
invalid: [
{
code: "class foo{ bar(){}\nbaz(){}}",
output: "class foo{ bar(){}\n\nbaz(){}}",
errors: [{ message: ALWAYS_MESSAGE }]
}, {
code: "class foo{ bar(){}\n/*comments*/baz(){}}",
output: "class foo{ bar(){}\n\n/*comments*/baz(){}}",
errors: [{ message: ALWAYS_MESSAGE }]
}, {
code: "class foo{ bar(){}\n//comments\nbaz(){}}",
output: "class foo{ bar(){}\n\n//comments\nbaz(){}}",
options: ["always"],
errors: [{ message: ALWAYS_MESSAGE }]
}, {
code: "class foo{ bar(){}\n\nbaz(){}}",
output: "class foo{ bar(){}\nbaz(){}}",
options: ["never"],
errors: [{ message: NEVER_MESSAGE }]
}, {
code: "class foo{ bar(){}\n\n/*comments*/baz(){}}",
output: "class foo{ bar(){}\n/*comments*/baz(){}}",
options: ["never"],
errors: [{ message: NEVER_MESSAGE }]
}, {
code: "class foo{ bar(){}\n\n//comments\nbaz(){}}",
output: "class foo{ bar(){}\n//comments\nbaz(){}}",
options: ["never"],
errors: [{ message: NEVER_MESSAGE }]
}, {
code: "class foo{ bar(){\n}\nbaz(){}}",
output: "class foo{ bar(){\n}\n\nbaz(){}}",
options: [{ multiline: "always" }],
errors: [{ message: ALWAYS_MESSAGE }]
}, {
code: "class foo{ bar(){\n}\n/*comments*/baz(){}}",
output: "class foo{ bar(){\n}\n\n/*comments*/baz(){}}",
options: [{ multiline: "always" }],
errors: [{ message: ALWAYS_MESSAGE }]
}, {
code: "class foo{ bar(){\n}\n//comments\nbaz(){}}",
output: "class foo{ bar(){\n}\n\n//comments\nbaz(){}}",
options: [{ multiline: "always" }],
options: ["always", { exceptAfterSingleLine: true }],
errors: [{ message: ALWAYS_MESSAGE }]
}, {
code: "class foo{ bar(){\n}\n\nbaz(){}}",
output: "class foo{ bar(){\n}\nbaz(){}}",
options: [{ multiline: "never" }],
errors: [{ message: NEVER_MESSAGE }]
}, {
code: "class foo{ bar(){\n}\n\n/*comments*/baz(){}}",
output: "class foo{ bar(){\n}\n/*comments*/baz(){}}",
options: [{ multiline: "never" }],
errors: [{ message: NEVER_MESSAGE }]
}, {
code: "class foo{ bar(){\n}\n\n//comments\nbaz(){}}",
output: "class foo{ bar(){\n}\n//comments\nbaz(){}}",
options: [{ multiline: "never" }],
errors: [{ message: NEVER_MESSAGE }]
}, {
code: "class foo{ bar(){}\nbaz(){}}",
output: "class foo{ bar(){}\n\nbaz(){}}",
options: [{ singleline: "always" }],
errors: [{ message: ALWAYS_MESSAGE }]
}, {
code: "class foo{ bar(){}\n/*comments*/baz(){}}",
output: "class foo{ bar(){}\n\n/*comments*/baz(){}}",
options: [{ singleline: "always" }],
errors: [{ message: ALWAYS_MESSAGE }]
}, {
code: "class foo{ bar(){}\n//comments\nbaz(){}}",
output: "class foo{ bar(){}\n\n//comments\nbaz(){}}",
options: [{ singleline: "always" }],
errors: [{ message: ALWAYS_MESSAGE }]
}, {
code: "class foo{ bar(){}\n\nbaz(){}}",
output: "class foo{ bar(){}\nbaz(){}}",
options: [{ singleline: "never" }],
errors: [{ message: NEVER_MESSAGE }]
}, {
code: "class foo{ bar(){}\n\n/*comments*/baz(){}}",
output: "class foo{ bar(){}\n/*comments*/baz(){}}",
options: [{ singleline: "never" }],
errors: [{ message: NEVER_MESSAGE }]
}, {
code: "class foo{ bar(){}\n\n//comments\nbaz(){}}",
output: "class foo{ bar(){}\n//comments\nbaz(){}}",
options: [{ singleline: "never" }],
errors: [{ message: NEVER_MESSAGE }]
}, {
code: "class foo{ bar(){\n}\nbaz(){}\n\nfn(){}}",
output: "class foo{ bar(){\n}\n\nbaz(){}\nfn(){}}",
options: [{ multiline: "always", singleline: "never" }],
errors: [{ message: ALWAYS_MESSAGE }, { message: NEVER_MESSAGE }]
}, {
code: "class foo{ bar(){\n}\n\nbaz(){}\nfn(){}}",
output: "class foo{ bar(){\n}\nbaz(){}\n\nfn(){}}",
options: [{ multiline: "never", singleline: "always" }],
errors: [{ message: NEVER_MESSAGE }, { message: ALWAYS_MESSAGE }]
}
]
});

0 comments on commit 796985e

Please sign in to comment.