-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
feat(eslint-plugin): add extension rule keyword-spacing
#1739
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’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
bradzacher
merged 32 commits into
typescript-eslint:master
from
OoDeLally:keyword-spacing
Apr 20, 2020
Merged
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
16b5b1b
keyword-spacing
OoDeLally fca75e7
Cleaned
OoDeLally 82f1109
Doc
OoDeLally 47b6f2d
all.json
OoDeLally 668e9e9
Docs
OoDeLally 936913b
Prettified
OoDeLally e0dc659
removed as any
OoDeLally 644cb33
Import what's available from base rule
OoDeLally 23975f2
Moved keyword typing file
OoDeLally f0e95bf
Prettyfied
OoDeLally 6da07f6
Better typing
OoDeLally de86f6f
Better typing
OoDeLally 7d0dd81
export Options
OoDeLally f40bc1c
Fixed typing
OoDeLally 88e4e70
pretty
OoDeLally e9bb029
Linting
OoDeLally 6789102
Linting again...
OoDeLally 94eccbc
Better typing
OoDeLally 2941964
typing, typing, typing...
OoDeLally 0022f7e
typo
OoDeLally f4011c9
Test coverage for `after`
OoDeLally bdab59d
import the keyword list
OoDeLally c8b69fd
Dropped Keyword const type
OoDeLally 80dcfe7
linting
OoDeLally 1cee759
Added some tests to please the coverage check
OoDeLally b2973c4
Update packages/eslint-plugin/src/rules/keyword-spacing.ts
OoDeLally 1a757d0
Update packages/eslint-plugin/typings/eslint-rules.d.ts
OoDeLally c9795c7
Update packages/eslint-plugin/src/rules/keyword-spacing.ts
OoDeLally 4dd789e
Stuff
OoDeLally c26af99
Apparently these tools dont like force-push
OoDeLally 0715791
Update keyword-spacing.md
bradzacher 21f2c5f
Merge branch 'master' into keyword-spacing
bradzacher File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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,22 @@ | ||
# Enforce consistent spacing before and after keywords (`keyword-spacing`) | ||
|
||
## Rule Details | ||
|
||
This rule extends the base [`eslint/keyword-spacing`](https://eslint.org/docs/rules/keyword-spacing) rule. | ||
This version adds support for generic type parameters on function calls. | ||
|
||
## How to use | ||
|
||
```cjson | ||
{ | ||
// note you must disable the base rule as it can report incorrect errors | ||
"keyword-spacing": "off", | ||
"@typescript-eslint/keyword-spacing": ["error"] | ||
} | ||
``` | ||
|
||
## Options | ||
|
||
See [`eslint/keyword-spacing` options](https://eslint.org/docs/rules/keyword-spacing#options). | ||
|
||
<sup>Taken with ❤️ [from ESLint core](https://github.com/eslint/eslint/blob/master/docs/rules/keyword-spacing.md)</sup> |
This file contains hidden or 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 hidden or 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 hidden or 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,52 @@ | ||
import { AST_TOKEN_TYPES } from '@typescript-eslint/experimental-utils'; | ||
import baseRule from 'eslint/lib/rules/keyword-spacing'; | ||
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: 'keyword-spacing', | ||
meta: { | ||
type: 'layout', | ||
docs: { | ||
description: 'Enforce consistent spacing before and after keywords', | ||
category: 'Stylistic Issues', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
}, | ||
fixable: 'whitespace', | ||
schema: baseRule.meta.schema, | ||
messages: baseRule.meta.messages, | ||
}, | ||
defaultOptions: [{}], | ||
|
||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
const baseRules = baseRule.create(context); | ||
return { | ||
...baseRules, | ||
TSAsExpression(node): void { | ||
const asToken = util.nullThrows( | ||
sourceCode.getTokenAfter( | ||
node.expression, | ||
token => token.value === 'as', | ||
), | ||
util.NullThrowsReasons.MissingToken('as', node.type), | ||
); | ||
const oldTokenType = asToken.type; | ||
// as is a contextual keyword, so it's always reported as an Identifier | ||
// the rule looks for keyword tokens, so we temporarily override it | ||
// we mutate it at the token level because the rule calls sourceCode.getFirstToken, | ||
// so mutating a copy would not change the underlying copy returned by that method | ||
asToken.type = AST_TOKEN_TYPES.Keyword; | ||
|
||
// use this selector just because it is just a call to `checkSpacingAroundFirstToken` | ||
baseRules.DebuggerStatement(asToken as never); | ||
|
||
// make sure to reset the type afterward so we don't permanently mutate the AST | ||
asToken.type = oldTokenType; | ||
}, | ||
}; | ||
}, | ||
}); |
153 changes: 153 additions & 0 deletions
153
packages/eslint-plugin/tests/rules/keyword-spacing.test.ts
This file contains hidden or 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,153 @@ | ||
/* eslint-disable eslint-comments/no-use */ | ||
// this rule tests the spacing, which prettier will want to fix and break the tests | ||
/* eslint "@typescript-eslint/internal/plugin-test-formatting": ["error", { formatWithPrettier: false }] */ | ||
/* eslint-enable eslint-comments/no-use */ | ||
import { TSESLint } from '@typescript-eslint/experimental-utils'; | ||
import rule, { MessageIds, Options } from '../../src/rules/keyword-spacing'; | ||
import { RuleTester } from '../RuleTester'; | ||
|
||
//------------------------------------------------------------------------------ | ||
// Helpers | ||
//------------------------------------------------------------------------------ | ||
|
||
const BOTH = { before: true, after: true }; | ||
const NEITHER = { before: false, after: false }; | ||
|
||
/** | ||
* Creates an option object to test an 'overrides' option. | ||
* | ||
* e.g. | ||
* | ||
* override('as', BOTH) | ||
* | ||
* returns | ||
* | ||
* { | ||
* before: false, | ||
* after: false, | ||
* overrides: {as: {before: true, after: true}} | ||
* } | ||
* @param keyword A keyword to be overridden. | ||
* @param value A value to override.< F438 /td> | ||
* @returns An option object to test an 'overrides' option. | ||
*/ | ||
function overrides(keyword: string, value: Options[0]): Options[0] { | ||
return { | ||
before: value.before === false, | ||
after: value.after === false, | ||
overrides: { [keyword]: value }, | ||
}; | ||
} | ||
|
||
/** | ||
* Gets an error message that expected space(s) before a specified keyword. | ||
* @param keyword A keyword. | ||
* @returns An error message. | ||
*/ | ||
function expectedBefore(keyword: string): TSESLint.TestCaseError<MessageIds>[] { | ||
return [{ messageId: 'expectedBefore', data: { value: keyword } }]; | ||
} | ||
|
||
/** | ||
* Gets an error message that expected space(s) after a specified keyword. | ||
* @param keyword A keyword. | ||
* @returns An error message. | ||
*/ | ||
function expectedAfter(keyword: string): TSESLint.TestCaseError<MessageIds>[] { | ||
return [{ messageId: 'expectedAfter', data: { value: keyword } }]; | ||
} | ||
|
||
/** | ||
* Gets an error message that unexpected space(s) before a specified keyword. | ||
* @param keyword A keyword. | ||
* @returns An error message. | ||
*/ | ||
function unexpectedBefore( | ||
keyword: string, | ||
): TSESLint.TestCaseError<MessageIds>[] { | ||
return [{ messageId: 'unexpectedBefore', data: { value: keyword } }]; | ||
} | ||
|
||
/** | ||
* Gets an error message that unexpected space(s) after a specified keyword. | ||
* @param keyword A keyword. | ||
* @returns An error message. | ||
*/ | ||
function unexpectedAfter( | ||
keyword: string, | ||
): TSESLint.TestCaseError<MessageIds>[] { | ||
return [{ messageId: 'unexpectedAfter', data: { value: keyword } }]; | ||
} | ||
|
||
const ruleTester = new RuleTester({ | ||
parser: '@typescript-eslint/parser', | ||
}); | ||
|
||
ruleTester.run('keyword-spacing', rule, { | ||
valid: [ | ||
//---------------------------------------------------------------------- | ||
// as (typing) | ||
//---------------------------------------------------------------------- | ||
{ | ||
code: 'const foo = {} as {};', | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'const foo = {}as{};', | ||
options: [NEITHER], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'const foo = {} as {};', | ||
options: [overrides('as', BOTH)], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'const foo = {}as{};', | ||
options: [overrides('as', NEITHER)], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'const foo = {} as {};', | ||
options: [{ overrides: { as: {} } }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
], | ||
invalid: [ | ||
//---------------------------------------------------------------------- | ||
// as (typing) | ||
bradzacher marked this conversation as resolved.
Show resolved
Hide resolved
|
||
//---------------------------------------------------------------------- | ||
{ | ||
code: 'const foo = {}as {};', | ||
output: 'const foo = {} as {};', | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
errors: expectedBefore('as'), | ||
}, | ||
{ | ||
code: 'const foo = {} as{};', | ||
output: 'const foo = {}as{};', | ||
options: [NEITHER], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
errors: unexpectedBefore('as'), | ||
}, | ||
{ | ||
code: 'const foo = {} as{};', | ||
output: 'const foo = {} as {};', | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
errors: expectedAfter('as'), | ||
}, | ||
{ | ||
code: 'const foo = {}as {};', | ||
output: 'const foo = {}as{};', | ||
options: [NEITHER], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
errors: unexpectedAfter('as'), | ||
}, | ||
{ | ||
code: 'const foo = {} as{};', | ||
options: [{ overrides: { as: {} } }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
errors: expectedAfter('as'), | ||
}, | ||
], | ||
}); |
This file contains hidden or 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
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.