-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(eslint-plugin): Add semi [extension] (#461)
- Loading branch information
1 parent
0205e3e
commit 0962017
Showing
6 changed files
with
243 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# require or disallow semicolons instead of ASI (semi) | ||
|
||
This rule enforces consistent use of semicolons. | ||
|
||
## Rule Details | ||
|
||
This rule extends the base [eslint/semi](https://eslint.org/docs/rules/semi) rule. | ||
It supports all options and features of the base rule. | ||
This version adds support for numerous typescript features. | ||
|
||
## How to use | ||
|
||
```cjson | ||
{ | ||
// note you must disable the base rule as it can report incorrect errors | ||
"semi": "off", | ||
"@typescript-eslint/semi": ["error"] | ||
} | ||
``` | ||
|
||
## Options | ||
|
||
See [eslint/semi options](https://eslint.org/docs/rules/semi#options). | ||
|
||
<sup>Taken with ❤️ [from ESLint core](https://github.com/eslint/eslint/blob/master/docs/rules/semi.md)</sup> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree'; | ||
import baseRule from 'eslint/lib/rules/semi'; | ||
import { RuleListener, RuleFunction } from 'ts-eslint'; | ||
import * as util from '../util'; | ||
|
||
export type Options = util.InferOptionsTypeFromRule<typeof baseRule>; | ||
export type MessageIds = util.InferMessageIdsTypeFromRule<typeof baseRule>; | ||
|
||
export default util.createRule<Options, MessageIds>({ | ||
name: 'semi', | ||
meta: { | ||
type: 'layout', | ||
docs: { | ||
description: 'Require or disallow semicolons instead of ASI', | ||
category: 'Stylistic Issues', | ||
recommended: false, | ||
}, | ||
fixable: 'code', | ||
schema: baseRule.meta.schema, | ||
messages: baseRule.meta.messages, | ||
}, | ||
defaultOptions: [ | ||
'always', | ||
{ | ||
omitLastInOneLineBlock: false, | ||
beforeStatementContinuationChars: 'any', | ||
}, | ||
], | ||
create(context) { | ||
const rules = baseRule.create(context); | ||
const checkForSemicolon = rules.ExpressionStatement as RuleFunction< | ||
TSESTree.Node | ||
>; | ||
|
||
/* | ||
The following nodes are handled by the member-delimiter-style rule | ||
AST_NODE_TYPES.TSCallSignatureDeclaration, | ||
AST_NODE_TYPES.TSConstructSignatureDeclaration, | ||
AST_NODE_TYPES.TSIndexSignature, | ||
AST_NODE_TYPES.TSMethodSignature, | ||
AST_NODE_TYPES.TSPropertySignature, | ||
*/ | ||
const nodesToCheck = [ | ||
AST_NODE_TYPES.ClassProperty, | ||
AST_NODE_TYPES.TSAbstractClassProperty, | ||
AST_NODE_TYPES.TSAbstractMethodDefinition, | ||
AST_NODE_TYPES.TSDeclareFunction, | ||
AST_NODE_TYPES.TSExportAssignment, | ||
AST_NODE_TYPES.TSImportEqualsDeclaration, | ||
AST_NODE_TYPES.TSTypeAliasDeclaration, | ||
].reduce<RuleListener>((acc, node) => { | ||
acc[node] = checkForSemicolon; | ||
return acc; | ||
}, {}); | ||
|
||
return { | ||
...rules, | ||
...nodesToCheck, | ||
ExportDefaultDeclaration(node) { | ||
if (node.declaration.type !== AST_NODE_TYPES.TSInterfaceDeclaration) { | ||
rules.ExportDefaultDeclaration(node); | ||
} | ||
}, | ||
}; | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import rule, { MessageIds, Options } from '../../src/rules/semi'; | ||
import { InvalidTestCase, RuleTester, ValidTestCase } from '../RuleTester'; | ||
|
||
const ruleTester = new RuleTester({ | ||
parser: '@typescript-eslint/parser', | ||
}); | ||
|
||
ruleTester.run('semi', rule, { | ||
valid: [ | ||
` | ||
class Class { | ||
prop: string; | ||
} | ||
`, | ||
` | ||
abstract class AbsClass { | ||
abstract prop: string; | ||
abstract meth(): string; | ||
} | ||
`, | ||
`declare function declareFn(): string;`, | ||
`export default interface Foo {}`, | ||
'export = Foo;', | ||
'import f = require("f");', | ||
'type Foo = {};', | ||
].reduce<ValidTestCase<Options>[]>((acc, code) => { | ||
acc.push({ | ||
code, | ||
options: ['always'], | ||
}); | ||
acc.push({ | ||
code: code.replace(/;/g, ''), | ||
options: ['never'], | ||
}); | ||
|
||
return acc; | ||
}, []), | ||
invalid: [ | ||
{ | ||
code: ` | ||
class Class { | ||
prop: string; | ||
} | ||
`, | ||
errors: [ | ||
{ | ||
line: 3, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: ` | ||
abstract class AbsClass { | ||
abstract prop: string; | ||
abstract meth(): string; | ||
} | ||
`, | ||
errors: [ | ||
{ | ||
line: 3, | ||
}, | ||
{ | ||
line: 4, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: `declare function declareFn(): string;`, | ||
errors: [ | ||
{ | ||
line: 1, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: 'export = Foo;', | ||
errors: [ | ||
{ | ||
line: 1, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: 'import f = require("f");', | ||
errors: [ | ||
{ | ||
line: 1, | ||
}, | ||
], | ||
}, | ||
{ | ||
code: 'type Foo = {};', | ||
errors: [ | ||
{ | ||
line: 1, | ||
}, | ||
], | ||
}, | ||
].reduce<InvalidTestCase<MessageIds, Options>[]>((acc, test) => { | ||
acc.push({ | ||
code: test.code.replace(/;/g, ''), | ||
options: ['always'], | ||
errors: test.errors.map(e => ({ | ||
...e, | ||
message: 'Missing semicolon.', | ||
})) as any, | ||
}); | ||
acc.push({ | ||
code: test.code, | ||
options: ['never'], | ||
errors: test.errors.map(e => ({ | ||
...e, | ||
message: 'Extra semicolon.', | ||
})) as any, | ||
}); | ||
|
||
return acc; | ||
}, []), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters