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 c43e1dd
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 204 deletions.
2 changes: 1 addition & 1 deletion conf/eslint-recommended.js
Original file line number Diff line number Diff line change
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
75 changes: 12 additions & 63 deletions docs/rules/lines-between-class-members.md
Original file line number Diff line number Diff line change
@@ -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 @@ -35,7 +35,7 @@ class MyClass {

### Options

This rule has one option, which can be a string option or an object option.
This rule has a string option and an object option.

String option:

Expand All @@ -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,21 @@ 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(){}
}

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

/* eslint lines-between-class-members: ["error", { singleline: "always" }]*/
class Foo{
bar(){}
If you don't want enforce empty lines between class members, you can disable this rule.

baz(){}
}
## Related Rules

/* 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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 c43e1dd

Please sign in to comment.