Skip to content

Commit d7abd9f

Browse files
authored
feat: Interface Id Match rule (#492)
* create rule and tests * reset readme * update naming conventions
1 parent c40937a commit d7abd9f

File tree

7 files changed

+128
-6
lines changed

7 files changed

+128
-6
lines changed

.README/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ npm install eslint babel-eslint eslint-plugin-flowtype --save-dev
5454
2,
5555
"never"
5656
],
57+
"flowtype/interface-id-match": [
58+
2,
59+
"^([A-Z][a-z0-9]+)+Type$"
60+
],
5761
"flowtype/no-mixed": 2,
5862
"flowtype/no-primitive-constructor-types": 2,
5963
"flowtype/no-types-missing-file-annotation": 2,
@@ -162,6 +166,7 @@ When `true`, only checks files with a [`@flow` annotation](http://flowtype.org/d
162166
{"gitdown": "include", "file": "./rules/delimiter-dangle.md"}
163167
{"gitdown": "include", "file": "./rules/enforce-line-break.md"}
164168
{"gitdown": "include", "file": "./rules/generic-spacing.md"}
169+
{"gitdown": "include", "file": "./rules/interface-id-match.md"}
165170
{"gitdown": "include", "file": "./rules/newline-after-flow-annotation.md"}
166171
{"gitdown": "include", "file": "./rules/no-dupe-keys.md"}
167172
{"gitdown": "include", "file": "./rules/no-existential-type.md"}

.README/rules/interface-id-match.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
### `interface-id-match`
2+
3+
Enforces a consistent naming pattern for interfaces.
4+
5+
#### Options
6+
7+
This rule requires a text RegExp:
8+
9+
```js
10+
{
11+
"rules": {
12+
"flowtype/interface-id-match": [
13+
2,
14+
"^([A-Z][a-z0-9]*)+Type$"
15+
]
16+
}
17+
}
18+
```
19+
20+
`'^([A-Z][a-z0-9]*)+Type$$'` is the default pattern.
21+
22+
<!-- assertions interfaceIdMatch -->

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,7 +1870,7 @@ import Foo from './foo';
18701870
// Message: Expected newline after flow annotation
18711871

18721872
// Options: ["always-windows"]
1873-
// @flow
1873+
// @flow
18741874
import Foo from './foo';
18751875
// Message: Expected newline after flow annotation
18761876

@@ -1890,8 +1890,8 @@ The following patterns are not considered problems:
18901890
import Foo from './foo';
18911891

18921892
// Options: ["always-windows"]
1893-
// @flow
1894-
1893+
// @flow
1894+
18951895
import Foo from './foo';
18961896

18971897
// Options: ["never"]
@@ -3028,7 +3028,7 @@ The rule has two options:
30283028
}
30293029
```
30303030
3031-
* `allowNull` allows compound types where one of the members is a `null`, e.g. `string | null`.
3031+
* `allowNull` allows compound types where one of the members is a `null`, e.g. `string | null`.
30323032
30333033
The following patterns are considered problems:
30343034
@@ -5392,7 +5392,7 @@ The following patterns are not considered problems:
53925392
{ a: string, b: number }) => {}
53935393
53945394
// Options: ["always",{"allowLineBreak":true}]
5395-
(foo:
5395+
(foo:
53965396
{ a: string, b: number }) => {}
53975397
53985398
// Options: ["never"]
@@ -6719,4 +6719,3 @@ function x(foo: Type = bar()) {}
67196719
```
67206720
67216721
6722-

src/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import defineFlowType from './rules/defineFlowType';
88
import delimiterDangle from './rules/delimiterDangle';
99
import enforceLineBreak from './rules/enforceLineBreak';
1010
import genericSpacing from './rules/genericSpacing';
11+
import interfaceIdMatch from './rules/interfaceIdMatch';
1112
import newlineAfterFlowAnnotation from './rules/newlineAfterFlowAnnotation';
1213
import noDupeKeys from './rules/noDupeKeys';
1314
import noExistentialType from './rules/noExistentialType';
@@ -56,6 +57,7 @@ const rules = {
5657
'delimiter-dangle': delimiterDangle,
5758
'enforce-line-break': enforceLineBreak,
5859
'generic-spacing': genericSpacing,
60+
'interface-id-match': interfaceIdMatch,
5961
'newline-after-flow-annotation': newlineAfterFlowAnnotation,
6062
'no-dupe-keys': noDupeKeys,
6163
'no-existential-type': noExistentialType,
@@ -113,6 +115,7 @@ export default {
113115
'define-flow-type': 0,
114116
'delimiter-dangle': 0,
115117
'generic-spacing': 0,
118+
'interface-id-match': 0,
116119
'newline-after-flow-annotation': 0,
117120
'no-dupe-keys': 0,
118121
'no-flow-fix-me-comments': 0,

src/rules/interfaceIdMatch.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const schema = [
2+
{
3+
type: 'string',
4+
},
5+
];
6+
7+
const create = (context) => {
8+
const pattern = new RegExp(context.options[0] || '^([A-Z][a-z0-9]*)+Type$');
9+
10+
const checkInterface = (interfaceDeclarationNode) => {
11+
const interfaceIdentifierName = interfaceDeclarationNode.id.name;
12+
13+
if (!pattern.test(interfaceIdentifierName)) {
14+
context.report(interfaceDeclarationNode, 'Interface identifier \'{{name}}\' does not match pattern \'{{pattern}}\'.', {
15+
name: interfaceIdentifierName,
16+
pattern: pattern.toString(),
17+
});
18+
}
19+
};
20+
21+
return {
22+
InterfaceDeclaration: checkInterface,
23+
};
24+
};
25+
26+
export default {
27+
create,
28+
schema,
29+
};
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
export default {
2+
invalid: [
3+
{
4+
code: 'interface foo{};',
5+
errors: [
6+
{
7+
message: 'Interface identifier \'foo\' does not match pattern \'/^([A-Z][a-z0-9]*)+Type$/\'.',
8+
},
9+
],
10+
},
11+
{
12+
code: 'interface FooType{};',
13+
errors: [
14+
{
15+
message: 'Interface identifier \'FooType\' does not match pattern \'/^foo$/\'.',
16+
},
17+
],
18+
options: [
19+
'^foo$',
20+
],
21+
},
22+
],
23+
misconfigured: [
24+
{
25+
errors: [
26+
{
27+
data: 7,
28+
dataPath: '[0]',
29+
keyword: 'type',
30+
message: 'should be string',
31+
params: {
32+
type: 'string',
33+
},
34+
parentSchema: {
35+
type: 'string',
36+
},
37+
schema: 'string',
38+
schemaPath: '#/items/0/type',
39+
},
40+
],
41+
options: [7],
42+
},
43+
],
44+
valid: [
45+
{
46+
code: 'interface FooType {};',
47+
},
48+
{
49+
code: 'interface foo {};',
50+
options: [
51+
'^foo$',
52+
],
53+
},
54+
{
55+
code: 'interface foo {};',
56+
settings: {
57+
flowtype: {
58+
onlyFilesWithFlowAnnotation: true,
59+
},
60+
},
61+
},
62+
],
63+
};

tests/rules/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const reportingRules = [
1919
'delimiter-dangle',
2020
'enforce-line-break',
2121
'generic-spacing',
22+
'interface-id-match',
2223
'newline-after-flow-annotation',
2324
'no-dupe-keys',
2425
'no-existential-type',

0 commit comments

Comments
 (0)