8000 feat(eslint-plugin): add default-param-last rule (#1418) · alex-dow/typescript-eslint@a37ff9f · GitHub
[go: up one dir, main page]

Skip to content

Commit a37ff9f

Browse files
a-tarasyukbradzacher
authored andcommitted
feat(eslint-plugin): add default-param-last rule (typescript-eslint#1418)
1 parent b139540 commit a37ff9f

File tree

6 files changed

+640
-0
lines changed

6 files changed

+640
-0
lines changed

packages/eslint-plugin/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ Pro Tip: For larger codebases you may want to consider splitting our linting int
105105
| [`@typescript-eslint/class-name-casing`](./docs/rules/class-name-casing.md) | Require PascalCased class and interface names | :heavy_check_mark: | | |
106106
| [`@typescript-eslint/consistent-type-assertions`](./docs/rules/consistent-type-assertions.md) | Enforces consistent usage of type assertions | :heavy_check_mark: | | |
107107
| [`@typescript-eslint/consistent-type-definitions`](./docs/rules/consistent-type-definitions.md) | Consistent with type definition either `interface` or `type` | | :wrench: | |
108+
| [`@typescript-eslint/default-param-last`](./docs/rules/default-param-last.md) | Enforce default parameters to be last | | | |
108109
| [`@typescript-eslint/explicit-function-return-type`](./docs/rules/explicit-function-return-type.md) | Require explicit return types on functions and class methods | :heavy_check_mark: | | |
109110
| [`@typescript-eslint/explicit-member-accessibility`](./docs/rules/explicit-member-accessibility.md) | Require explicit accessibility modifiers on class properties and methods | | | |
110111
| [`@typescript-eslint/func-call-spacing`](./docs/rules/func-call-spacing.md) | Require or disallow spacing between function identifiers and their invocations | | :wrench: | |
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Enforce default parameters to be last (`default-param-last`)
2+
3+
## Rule Details
4+
5+
This rule enforces default or optional parameters to be the last of parameters.
6+
7+
Examples of **incorrect** code for this rule:
8+
9+
```ts
10+
/* eslint @typescript-eslint/default-param-last: ["error"] */
11+
12+
function f(a = 0, b: number) {}
13+
function f(a: number, b = 0, c?: number) {}
14+
function f(a: number, b = 0, c: number) {}
15+
function f(a: number, b?: number, c: number) {}
16+
```
17+
18+
Examples of **correct** code for this rule:
19+
20+
```ts
21+
/* eslint @typescript-eslint/default-param-last: ["error"] */
22+
23+
function f(a = 0) {}
24+
function f(a: number, b = 0) {}
25+
function f(a: number, b?: number) {}
26+
function f(a: number, b?: number, c = 0) {}
27+
```
28+
29+
<sup>Taken with ❤️ [from ESLint core](https://github.com/eslint/eslint/blob/master/docs/rules/default-param-last.md)</sup>

packages/eslint-plugin/src/configs/all.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"@typescript-eslint/class-name-casing": "error",
1414
"@typescript-eslint/consistent-type-assertions": "error",
1515
"@typescript-eslint/consistent-type-definitions": "error",
16+
"@typescript-eslint/default-param-last": "error",
1617
"@typescript-eslint/explicit-function-return-type": "error",
1718
"@typescript-eslint/explicit-member-accessibility": "error",
1819
"func-call-spacing": "off",
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { createRule } from '../util';
2+
import {
3+
TSESTree,
4+
AST_NODE_TYPES,
5+
} from '@typescript-eslint/experimental-utils';
6+
7+
export default createRule({
8+
name: 'default-param-last',
9+
meta: {
10+
type: 'suggestion',
11+
docs: {
12+
description: 'Enforce default parameters to be last',
13+
category: 'Best Practices',
14+
recommended: false,
15+
},
16+
schema: [],
17+
messages: {
18+
shouldBeLast: 'Default parameters should be last.',
19+
},
20+
},
21+
defaultOptions: [],
22+
create(context) {
23+
/**
24+
* checks if node is optional parameter
25+
* @param node the node to be evaluated
26+
* @private
27+
*/
28+
function isOptionalParam(node: TSESTree.Parameter): boolean {
29+
return 'optional' in node && node.optional === true;
30+
}
31+
32+
/**
33+
* checks if node is plain parameter
34+
* @param node the node to be evaluated
35+
* @private
36+
*/
37+
function isPlainParam(node: TSESTree.Parameter): boolean {
38+
return !(
39+
node.type === AST_NODE_TYPES.AssignmentPattern ||
40+
node.type === AST_NODE_TYPES.RestElement ||
41+
isOptionalParam(node)
42+
);
43+
}
44+
45+
function checkDefaultParamLast(
46+
node:
47+
| TSESTree.ArrowFunctionExpression
48+
| TSESTree.FunctionDeclaration
49+
| TSESTree.FunctionExpression,
50+
): void {
51+
let hasSeenPlainParam = false;
52+
for (let i = node.params.length - 1; i >= 0; i--) {
53+
const param = node.params[i];
54+
55+
if (isPlainParam(param)) {
56+
hasSeenPlainParam = true;
57+
continue;
58+
}
59+
60+
if (
61+
hasSeenPlainParam &&
62+
(isOptionalParam(param) ||
63+
param.type === AST_NODE_TYPES.AssignmentPattern)
64+
) {
65+
context.report({ node: param, messageId: 'shouldBeLast' });
66+
}
67+
}
68+
}
69+
70+
return {
71+
ArrowFunctionExpression: checkDefaultParamLast,
72+
FunctionDeclaration: checkDefaultParamLast,
73+
FunctionExpression: checkDefaultParamLast,
74+
};
75+
},
76+
});

packages/eslint-plugin/src/rules/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import camelcase from './camelcase';
88
import classNameCasing from './class-name-casing';
99
import consistentTypeAssertions from './consistent-type-assertions';
1010
import consistentTypeDefinitions from './consistent-type-definitions';
11+
import defaultParamLast from './default-param-last';
1112
import explicitFunctionReturnType from './explicit-function-return-type';
1213
import explicitMemberAccessibility from './explicit-member-accessibility';
1314
import funcCallSpacing from './func-call-spacing';
@@ -87,6 +88,7 @@ export default {
8788
'class-name-casing': classNameCasing,
8889
'consistent-type-assertions': consistentTypeAssertions,
8990
'consistent-type-definitions': consistentTypeDefinitions,
91+
'default-param-last': defaultParamLast,
9092
'explicit-function-return-type': explicitFunctionReturnType,
9193
'explicit-member-accessibility': explicitMemberAccessibility,
9294
'func-call-spacing': funcCallSpacing,

0 commit comments

Comments
 (0)
0