Skip to content

Commit 3c67223

Browse files
danwanggajus
authored andcommitted
feat: add type-import-style rule (#320)
1 parent 74bcb8c commit 3c67223

File tree

6 files changed

+118
-0
lines changed

6 files changed

+118
-0
lines changed

.README/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ When `true`, only checks files with a [`@flow` annotation](http://flowtype.org/d
168168
{"gitdown": "include", "file": "./rules/space-before-generic-bracket.md"}
169169
{"gitdown": "include", "file": "./rules/space-before-type-colon.md"}
170170
{"gitdown": "include", "file": "./rules/type-id-match.md"}
171+
{"gitdown": "include", "file": "./rules/type-import-style.md"}
171172
{"gitdown": "include", "file": "./rules/union-intersection-spacing.md"}
172173
{"gitdown": "include", "file": "./rules/use-flow-type.md"}
173174
{"gitdown": "include", "file": "./rules/valid-syntax.md"}

.README/rules/type-import-style.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
### `type-import-style`
2+
3+
_The `--fix` option on the command line automatically fixes problems reported by this rule._
4+
5+
Enforces a particular style for type imports:
6+
7+
```
8+
// 'identifier' style
9+
import {type T, type U, type V} from '...';
10+
11+
// 'declaration' style
12+
import type {T, U, V} from '...';
13+
```
14+
15+
The rule has a string option:
16+
17+
* `"identifier"` (default): Enforces that type imports are all in the
18+
'identifier' style.
19+
* `"declaration"`: Enforces that type imports are all in the 'declaration'
20+
style.
21+
22+
<!-- assertions typeImportStyle -->

src/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import spaceAfterTypeColon from './rules/spaceAfterTypeColon';
2626
import spaceBeforeGenericBracket from './rules/spaceBeforeGenericBracket';
2727
import spaceBeforeTypeColon from './rules/spaceBeforeTypeColon';
2828
import typeIdMatch from './rules/typeIdMatch';
29+
import typeImportStyle from './rules/typeImportStyle';
2930
import unionIntersectionSpacing from './rules/unionIntersectionSpacing';
3031
import useFlowType from './rules/useFlowType';
3132
import validSyntax from './rules/validSyntax';
@@ -58,6 +59,7 @@ const rules = {
5859
'space-before-generic-bracket': spaceBeforeGenericBracket,
5960
'space-before-type-colon': spaceBeforeTypeColon,
6061
'type-id-match': typeIdMatch,
62+
'type-import-style': typeImportStyle,
6163
'union-intersection-spacing': unionIntersectionSpacing,
6264
'use-flow-type': useFlowType,
6365
'valid-syntax': validSyntax
@@ -98,6 +100,7 @@ export default {
98100
'space-before-generic-bracket': 0,
99101
'space-before-type-colon': 0,
100102
'type-id-match': 0,
103+
'type-import-style': 0,
101104
'union-intersection-spacing': 0,
102105
'use-flow-type': 0,
103106
'valid-syntax': 0

src/rules/typeImportStyle.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
const schema = [
2+
{
3+
enum: ['declaration', 'identifier'],
4+
type: 'string'
5+
}
6+
];
7+
8+
const create = (context) => {
9+
if (context.options[0] === 'declaration') {
10+
return {
11+
ImportDeclaration (node) {
12+
if (node.importKind !== 'type') {
13+
node.specifiers.forEach((specifier) => {
14+
if (specifier.importKind === 'type') {
15+
context.report({
16+
message: 'Unexpected type import',
17+
node
18+
});
19+
}
20+
});
21+
}
22+
}
23+
};
24+
} else {
25+
// Default to 'identifier'
26+
return {
27+
ImportDeclaration (node) {
28+
if (node.importKind === 'type') {
29+
context.report({
30+
fix (fixer) {
31+
const imports = node.specifiers.map((specifier) => {
32+
return 'type ' + specifier.local.name;
33+
});
34+
const source = node.source.value;
35+
36+
return fixer.replaceText(node,
37+
'import {' + imports.join(', ') + '} from \'' + source + '\';'
38+
);
39+
},
40+
message: 'Unexpected "import type"',
41+
node
42+
});
43+
}
44+
}
45+
};
46+
}
47+
};
48+
49+
export default {
50+
create,
51+
schema
52+
};
53+
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
export default {
2+
invalid: [
3+
{
4+
code: 'import type {A, B} from \'a\';',
5+
errors: [{message: 'Unexpected "import type"'}],
6+
output: 'import {type A, type B} from \'a\';'
7+
},
8+
{
9+
code: 'import type {A, B} from \'a\';',
10+
errors: [{message: 'Unexpected "import type"'}],
11+
options: ['identifier'],
12+
output: 'import {type A, type B} from \'a\';'
13+
},
14+
{
15+
code: 'import {type A, type B} from \'a\';',
16+
errors: [
17+
{message: 'Unexpected type import'},
18+
{message: 'Unexpected type import'}
19+
],
20+
options: ['declaration']
21+
}
22+
],
23+
valid: [
24+
{
25+
code: 'import {type A, type B} from \'a\';'
26+
},
27+
{
28+
code: 'import {type A, type B} from \'a\';',
29+
options: ['identifier']
30+
},
31+
{
32+
code: 'import type {A, B} from \'a\';',
33+
options: ['declaration']
34+
}
35+
]
36+
};
37+
38+

tests/rules/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const reportingRules = [
3636
'space-before-generic-bracket',
3737
'space-before-type-colon',
3838
'type-id-match',
39+
'type-import-style',
3940
'union-intersection-spacing',
4041
'use-flow-type',
4142
'valid-syntax'

0 commit comments

Comments
 (0)