-
-
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 func-call-spacing (#448)
- Loading branch information
1 parent
8c88dff
commit 92e65ec
Showing
7 changed files
with
551 additions
and
2 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,26 @@ | ||
# require or disallow spacing between function identifiers and their invocations (func-call-spacing) | ||
|
||
When calling a function, developers may insert optional whitespace between the function’s name and the parentheses that invoke it. | ||
This rule requires or disallows spaces between the function name and the opening parenthesis that calls it. | ||
|
||
## Rule Details | ||
|
||
This rule extends the base [eslint/func-call-spacing](https://eslint.org/docs/rules/func-call-spacing) rule. | ||
It supports all options and features of the base 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 | ||
"func-call-spacing": "off", | ||
"@typescript-eslint/func-call-spacing": ["error"] | ||
} | ||
``` | ||
|
||
## Options | ||
|
||
See [eslint/func-call-spacing options](https://eslint.org/docs/rules/func-call-spacing#options). | ||
|
||
<sup>Taken with ❤️ [from ESLint core](https://github.com/eslint/eslint/blob/master/docs/rules/func-call-spacing.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,153 @@ | ||
import { TSESTree } from '@typescript-eslint/typescript-estree'; | ||
import { isOpeningParenToken } from 'eslint-utils'; | ||
import * as util from '../util'; | ||
|
||
export type Options = [ | ||
'never' | 'always', | ||
{ | ||
allowNewlines?: boolean; | ||
}? | ||
]; | ||
export type MessageIds = 'unexpected' | 'missing'; | ||
|
||
export default util.createRule<Options, MessageIds>({ | ||
name: 'func-call-spacing', | ||
meta: { | ||
type: 'layout', | ||
docs: { | ||
description: | ||
'require or disallow spacing between function identifiers and their invocations', | ||
category: 'Stylistic Issues', | ||
recommended: false, | ||
}, | ||
fixable: 'whitespace', | ||
schema: { | ||
anyOf: [ | ||
{ | ||
type: 'array', | ||
items: [ | ||
{ | ||
enum: ['never'], | ||
}, | ||
], | ||
minItems: 0, | ||
maxItems: 1, | ||
}, | ||
{ | ||
type: 'array', | ||
items: [ | ||
{ | ||
enum: ['always'], | ||
}, | ||
{ | ||
type: 'object', | ||
properties: { | ||
allowNewlines: { | ||
type: 'boolean', | ||
}, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
], | ||
minItems: 0, | ||
maxItems: 2, | ||
}, | ||
], | ||
}, | ||
|
||
messages: { | ||
unexpected: | ||
'Unexpected space or newline between function name and paren.', | ||
missing: 'Missing space between function name and paren.', | ||
}, | ||
}, | ||
defaultOptions: ['never', {}], | ||
create(context, [option, config]) { | ||
const sourceCode = context.getSourceCode(); | ||
const text = sourceCode.getText(); | ||
|
||
/** | ||
* Check if open space is present in a function name | ||
* @param {ASTNode} node node to evaluate | ||
* @returns {void} | ||
* @private | ||
*/ | ||
function checkSpacing( | ||
node: TSESTree.CallExpression | TSESTree.NewExpression, | ||
): void { | ||
const closingParenToken = sourceCode.getLastToken(node)!; | ||
const lastCalleeTokenWithoutPossibleParens = sourceCode.getLastToken( | ||
node.typeParameters || node.callee, | ||
)!; | ||
const openingParenToken = sourceCode.getFirstTokenBetween( | ||
lastCalleeTokenWithoutPossibleParens, | ||
closingParenToken, | ||
isOpeningParenToken, | ||
); | ||
if (!openingParenToken || openingParenToken.range[1] >= node.range[1]) { | ||
// new expression with no parens... | ||
return; | ||
} | ||
const lastCalleeToken = sourceCode.getTokenBefore(openingParenToken)!; | ||
|
||
const textBetweenTokens = text | ||
.slice(lastCalleeToken.range[1], openingParenToken.range[0]) | ||
.replace(/\/\*.*?\*\//gu, ''); | ||
const hasWhitespace = /\s/u.test(textBetweenTokens); | ||
const hasNewline = | ||
hasWhitespace && util.LINEBREAK_MATCHER.test(textBetweenTokens); | ||
|
||
if (option === 'never') { | ||
if (hasWhitespace) { | ||
return context.report({ | ||
node, | ||
loc: lastCalleeToken.loc.start, | ||
messageId: 'unexpected', | ||
fix(fixer) { | ||
/* | ||
* Only autofix if there is no newline | ||
* https://github.com/eslint/eslint/issues/7787 | ||
*/ | ||
if (!hasNewline) { | ||
return fixer.removeRange([ | ||
lastCalleeToken.range[1], | ||
openingParenToken.range[0], | ||
]); | ||
} | ||
|
||
return null; | ||
}, | ||
}); | ||
} | ||
} else { | ||
if (!hasWhitespace) { | ||
context.report({ | ||
node, | ||
loc: lastCalleeToken.loc.start, | ||
messageId: 'missing', | ||
fix(fixer) { | ||
return fixer.insertTextBefore(openingParenToken, ' '); | ||
}, | ||
}); | ||
} else if (!config!.allowNewlines && hasNewline) { | ||
context.report({ | ||
node, | ||
loc: lastCalleeToken.loc.start, | ||
messageId: 'unexpected', | ||
fix(fixer) { | ||
return fixer.replaceTextRange( | ||
[lastCalleeToken.range[1], openingParenToken.range[0]], | ||
' ', | ||
); | ||
}, | ||
}); | ||
} | ||
} | ||
} | ||
|
||
return { | ||
CallExpression: checkSpacing, | ||
NewExpression: checkSpacing, | ||
}; | ||
}, | ||
}); |
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 @@ | ||
export const LINEBREAK_MATCHER = /\r\n|[\r\n\u2028\u2029]/; |
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
Oops, something went wrong.