diff --git a/.README/README.md b/.README/README.md
index ec7c293..056df1a 100644
--- a/.README/README.md
+++ b/.README/README.md
@@ -160,6 +160,7 @@ When `true`, only checks files with a [`@flow` annotation](http://flowtype.org/d
{"gitdown": "include", "file": "./rules/boolean-style.md"}
{"gitdown": "include", "file": "./rules/define-flow-type.md"}
{"gitdown": "include", "file": "./rules/delimiter-dangle.md"}
+{"gitdown": "include", "file": "./rules/enforce-line-break.md"}
{"gitdown": "include", "file": "./rules/generic-spacing.md"}
{"gitdown": "include", "file": "./rules/newline-after-flow-annotation.md"}
{"gitdown": "include", "file": "./rules/no-dupe-keys.md"}
diff --git a/.README/rules/enforce-line-break.md b/.README/rules/enforce-line-break.md
new file mode 100644
index 0000000..d790661
--- /dev/null
+++ b/.README/rules/enforce-line-break.md
@@ -0,0 +1,5 @@
+### `enforce-line-break`
+
+This rule enforces line breaks between type definitions.
+
+
diff --git a/README.md b/README.md
index ae748d3..6e6b24a 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,7 @@
* [`boolean-style`](#eslint-plugin-flowtype-rules-boolean-style)
* [`define-flow-type`](#eslint-plugin-flowtype-rules-define-flow-type)
* [`delimiter-dangle`](#eslint-plugin-flowtype-rules-delimiter-dangle)
+ * [`enforce-line-break`](#eslint-plugin-flowtype-rules-enforce-line-break)
* [`generic-spacing`](#eslint-plugin-flowtype-rules-generic-spacing)
* [`newline-after-flow-annotation`](#eslint-plugin-flowtype-rules-newline-after-flow-annotation)
* [`no-dupe-keys`](#eslint-plugin-flowtype-rules-no-dupe-keys)
@@ -1662,6 +1663,83 @@ type X = []
+
+### enforce-line-break
+
+This rule enforces line breaks between type definitions.
+
+The following patterns are considered problems:
+
+```js
+type baz = 6;
+const hi = 2;
+// Message: New line required below type declaration
+
+const foo = 6;
+type hi = 2;
+
+// Message: New line required above type declaration
+
+const som = "jes";
+// a comment
+type fed = "hed";
+
+// Message: New line required above type declaration
+
+type som = "jes";
+// a comment
+const fed = "hed";
+
+// Message: New line required below type declaration
+
+type hello = 34;
+const som = "jes";
+type fed = "hed";
+
+// Message: New line required below type declaration
+// Message: New line required above type declaration
+```
+
+The following patterns are not considered problems:
+
+```js
+type gjs = 6;
+
+type gjs = 6;
+
+type hi = 2;
+
+
+type X = 4;
+
+const red = "serpent";
+console.log("hello");
+
+// number or string
+type Y = string | number;
+
+// resting + sleep
+type snooze = "dreaming" | "";
+
+type Props = {
+ accountBalance: string | number,
+ accountNumber: string | number,
+};
+
+const x = 4;
+const y = 489;
+
+// Some Comment
+type Props = {
+ accountBalance: string | number,
+ accountNumber: string | number,
+};
+
+type RoadT = "grass" | "gravel" | "cement";
+```
+
+
+
### generic-spacing
diff --git a/src/index.js b/src/index.js
index 51292ea..04b2973 100644
--- a/src/index.js
+++ b/src/index.js
@@ -6,6 +6,7 @@ import arrayStyleSimpleType from './rules/arrayStyleSimpleType';
import booleanStyle from './rules/booleanStyle';
import defineFlowType from './rules/defineFlowType';
import delimiterDangle from './rules/delimiterDangle';
+import enforceLineBreak from './rules/enforceLineBreak';
import genericSpacing from './rules/genericSpacing';
import newlineAfterFlowAnnotation from './rules/newlineAfterFlowAnnotation';
import noDupeKeys from './rules/noDupeKeys';
@@ -53,6 +54,7 @@ const rules = {
'boolean-style': booleanStyle,
'define-flow-type': defineFlowType,
'delimiter-dangle': delimiterDangle,
+ 'enforce-line-break': enforceLineBreak,
'generic-spacing': genericSpacing,
'newline-after-flow-annotation': newlineAfterFlowAnnotation,
'no-dupe-keys': noDupeKeys,
diff --git a/src/rules/enforceLineBreak.js b/src/rules/enforceLineBreak.js
new file mode 100644
index 0000000..e898bd8
--- /dev/null
+++ b/src/rules/enforceLineBreak.js
@@ -0,0 +1,63 @@
+const schema = [];
+
+const breakLineMessage = (direction) => {
+ return `New line required ${direction} type declaration`;
+};
+
+const create = (context) => {
+ return {
+ TypeAlias (node) {
+ const sourceCode = context.getSourceCode();
+ if (sourceCode.lines.length === 1) {
+ return;
+ }
+
+ if (node.loc.start.line !== 1) {
+ if (node.leadingComments && node.leadingComments[0].loc.start.line !== 1) {
+ const lineAboveComment = sourceCode.lines[node.leadingComments[0].loc.start.line - 2];
+ if (lineAboveComment !== '') {
+ context.report({
+ fix (fixer) {
+ return fixer.insertTextBeforeRange(node.leadingComments[0].range, '\n');
+ },
+ message: breakLineMessage('above'),
+ node,
+ });
+ }
+ } else if (!node.leadingComments) {
+ const isLineAbove = sourceCode.lines[node.loc.start.line - 2];
+ if (isLineAbove !== '') {
+ context.report({
+ fix (fixer) {
+ return fixer.insertTextBefore(node, '\n');
+ },
+ message: breakLineMessage('above'),
+ node,
+ });
+ }
+ }
+ }
+
+ if (sourceCode.lines.length !== node.loc.end.line) {
+ const isLineBelow = sourceCode.lines[node.loc.end.line];
+ if (isLineBelow !== '') {
+ context.report({
+ fix (fixer) {
+ return fixer.insertTextAfter(node, '\n');
+ },
+ message: breakLineMessage('below'),
+ node,
+ });
+ }
+ }
+ },
+ };
+};
+
+export default {
+ create,
+ meta: {
+ fixable: 'code',
+ },
+ schema,
+};
diff --git a/tests/rules/assertions/enforceLineBreak.js b/tests/rules/assertions/enforceLineBreak.js
new file mode 100644
index 0000000..291174a
--- /dev/null
+++ b/tests/rules/assertions/enforceLineBreak.js
@@ -0,0 +1,81 @@
+export default {
+ invalid: [
+ {
+ code: 'type baz = 6;\nconst hi = 2;',
+ errors: [{
+ message: 'New line required below type declaration',
+ }],
+ output: 'type baz = 6;\n\nconst hi = 2;',
+ },
+ {
+ code: 'const foo = 6;\ntype hi = 2;\n',
+ errors: [
+ {message: 'New line required above type declaration'},
+ ],
+ output: 'const foo = 6;\n\ntype hi = 2;\n',
+ },
+ {
+ code: 'const som = "jes";\n// a comment\ntype fed = "hed";\n',
+ errors: [
+ {message: 'New line required above type declaration'},
+ ],
+ output: 'const som = "jes";\n\n// a comment\ntype fed = "hed";\n',
+ },
+ {
+ code: 'type som = "jes";\n// a comment\nconst fed = "hed";\n',
+ errors: [
+ {message: 'New line required below type declaration'},
+ ],
+ output: 'type som = "jes";\n\n// a comment\nconst fed = "hed";\n',
+ },
+ {
+ code: 'type hello = 34;\nconst som = "jes";\ntype fed = "hed";\n',
+ errors: [
+ {message: 'New line required below type declaration'},
+ {message: 'New line required above type declaration'},
+ ],
+ output: 'type hello = 34;\n\nconst som = "jes";\n\ntype fed = "hed";\n',
+ },
+ ],
+ valid: [
+ {
+ code: 'type gjs = 6;',
+ },
+ {
+ code: 'type gjs = 6;\n\ntype hi = 2;\n',
+ },
+ {
+ code:
+`type X = 4;
+
+const red = "serpent";
+console.log("hello");
+
+// number or string
+type Y = string | number;
+
+// resting + sleep
+type snooze = "dreaming" | "";`,
+ },
+ {
+ code:
+`type Props = {
+ accountBalance: string | number,
+ accountNumber: string | number,
+};`,
+ },
+ {
+ code:
+`const x = 4;
+const y = 489;
+
+// Some Comment
+type Props = {
+ accountBalance: string | number,
+ accountNumber: string | number,
+};
+
+type RoadT = "grass" | "gravel" | "cement";`,
+ },
+ ],
+};
diff --git a/tests/rules/index.js b/tests/rules/index.js
index b030073..7fddff4 100644
--- a/tests/rules/index.js
+++ b/tests/rules/index.js
@@ -17,6 +17,7 @@ const reportingRules = [
'boolean-style',
'define-flow-type',
'delimiter-dangle',
+ 'enforce-line-break',
'generic-spacing',
'newline-after-flow-annotation',
'no-dupe-keys',