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 42ea9ee
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 204 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
77 changes: 14 additions & 63 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 @@ -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,23 @@ 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)
* [requirePaddingNewLinesAfterBlocks](http://jscs.info/rule/requirePaddingNewLinesAfterBlocks)
* [disallowPaddingNewLinesAfterBlocks](http://jscs.info/rule/disallowPaddingNewLinesAfterBlocks)
5 changes: 5 additions & 0 deletions docs/rules/padded-blocks.md
Expand Up @@ -354,3 +354,8 @@ if (a) {
## When Not To Use It

You can turn this rule off if you are not concerned with the consistency of padding within blocks.

## Related Rules

* [lines-between-class-members](lines-between-class-members.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 42ea9ee

Please sign in to comment.