Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

New: Rule - 'lines-between-class-methods' (fixes #5949) #5950

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions conf/eslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@
"keyword-spacing": "off",
"linebreak-style": "off",
"lines-around-comment": "off",
"lines-between-class-methods": "off",
"max-depth": "off",
"max-len": "off",
"max-lines": "off",
Expand Down
206 changes: 206 additions & 0 deletions docs/rules/lines-between-class-methods.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
# Enforce lines between class methods (lines-between-class-methods)

Some style guides require class methods to have a empty line between them. The
goal is to improve readability by visually separating the methods from each
other.

```js
class T {
a () {
// ...
}

b () {
// ...
}
}
```

Since it's good to have a consistent code style, you should either always add a
empty line between methods or never do it.

## Rule Details

This rule enforces empty lines between class methods.

## Options

This rule has a string option:

* `"always"` (default) requires one or more empty line between class methods
* `"never"` disallows empty lines between class methods

### always

Examples of **incorrect** code for this rule with the default `"always"` option:

```js
/*eslint lines-between-class-methods: ["error", "always"]*/

class T {
a () {
// ...
}
b () {
// ...
}
}

class T {
a () {
// ...
}

b () {
// ...
}
c () {
// ...
}
}

class T {
a () {
// ...
}
// comment
b () {
// ...
}
}
```

Examples of **correct** code for this rule with the default `"always"` option:

```js
/*eslint lines-between-class-methods: ["error", "always"]*/

class T {
a () {
// ...
}

b () {
// ...
}
}

class T {
a () {
// ...
}

b () {
// ...
}

c () {
// ...
}
}

class T {
a () {
// ...
}


b () {
// ...
}
}

class T {
a () {
// ...
}

// comment
b () {
// ...
}
}
```

### never

Examples of **incorrect** code for this rule with the `"never"` option:

```js
/*eslint lines-between-class-methods: ["error", "never"]*/

class T {
a () {
// ...
}

b () {
// ...
}
}

class T {
a () {
// ...
}
b () {
// ...
}

c () {
// ...
}
}

class T {
a () {
// ...
}


b () {
// ...
}
}
```

Examples of **correct** code for this rule with the `"never"` option:

```js
/*eslint lines-between-class-methods: ["error", "never"]*/

class T {
a () {
// ...
}
b () {
// ...
}
}

class T {
a () {
// ...
}
b () {
// ...
}
c () {
// ...
}
}

class T {
a () {
// ...
}
// comment
b () {
// ...
}
}
```

## When Not To Use It

You can turn this rule off if you are not concerned with the consistency of spacing between class methods.
68 changes: 68 additions & 0 deletions lib/rules/lines-between-class-methods.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* @fileoverview A rule to ensure empty lines between class functions.
* @author Linus Unneb盲ck <https://github.com/LinusU>
*/

"use strict";

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

module.exports = function(context) {
var config = context.options[0] || "always";

var ALWAYS_MESSAGE = "Class methods must be separated by at least one blank line.",
NEVER_MESSAGE = "Class methods must not be separated by blank lines.";

var sourceCode = context.getSourceCode();

return {
"ClassBody:exit": function(node) {
node.body.reduce(function(prev, next) {
var firstEmptyLine = null;
var nextLine = prev.loc.end.line + 1;
var comments = sourceCode.getComments(prev).trailing;

for (var i = 0; i < comments.length; i++) {
var comment = comments[i];

if (comment.loc.start.line > nextLine) {
firstEmptyLine = nextLine;
break;
}

nextLine = comment.loc.end.line + 1;
}

if (firstEmptyLine === null && next.loc.start.line > nextLine) {
firstEmptyLine = nextLine;
}

if (config === "always" && firstEmptyLine === null) {
context.report({
node: node,
loc: { line: next.loc.start.line, column: next.loc.start.column },
message: ALWAYS_MESSAGE
});
}

if (config === "never" && firstEmptyLine !== null) {
context.report({
node: node,
loc: { line: firstEmptyLine, column: 0 },
message: NEVER_MESSAGE
});
}

return next;
});
}
};
};

module.exports.schema = [
{
enum: ["always", "never"]
}
];