@croct/eslint-plugin 0.8.2 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,60 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.jsxAttributeSpacing = void 0;
4
- const utils_1 = require("@typescript-eslint/utils");
5
- const createRule_1 = require("../createRule");
6
- exports.jsxAttributeSpacing = (0, createRule_1.createRule)({
7
- name: 'jsx-attribute-spacing',
8
- meta: {
9
- type: 'suggestion',
10
- docs: {
11
- description: 'Enforces a surrounding line break in multiline JSX attributes.',
12
- },
13
- fixable: 'whitespace',
14
- schema: [],
15
- messages: {
16
- missing: 'Missing new line.',
17
- },
18
- },
19
- defaultOptions: [],
20
- create: context => {
21
- const sourceCode = context.getSourceCode();
22
- function check(node) {
23
- const { value } = node;
24
- if (value?.type !== utils_1.TSESTree.AST_NODE_TYPES.JSXExpressionContainer) {
25
- return;
26
- }
27
- const firstToken = sourceCode.getFirstToken(value.expression);
28
- const lastToken = sourceCode.getLastToken(value.expression);
29
- if ((firstToken.type === utils_1.TSESTree.AST_TOKEN_TYPES.Punctuator
30
- && lastToken.type === utils_1.TSESTree.AST_TOKEN_TYPES.Punctuator)
31
- || (firstToken.loc.start.line === lastToken.loc.end.line)) {
32
- return;
33
- }
34
- const leftBrace = sourceCode.getFirstToken(value);
35
- const rightBrace = sourceCode.getLastToken(value);
36
- const tokens = [
37
- [leftBrace, firstToken],
38
- [lastToken, rightBrace],
39
- ];
40
- for (const [previousToken, currentToken] of tokens) {
41
- if (previousToken.loc.end.line !== currentToken.loc.start.line) {
42
- continue;
43
- }
44
- const tokenBefore = sourceCode.getTokenBefore(currentToken, { includeComments: true });
45
- context.report({
46
- node: node,
47
- loc: {
48
- start: tokenBefore.loc.end,
49
- end: currentToken.loc.start,
50
- },
51
- messageId: 'missing',
52
- fix: fixer => fixer.replaceTextRange([tokenBefore.range[1], currentToken.range[0]], '\n'),
53
- });
54
- }
55
- }
56
- return {
57
- JSXAttribute: check,
58
- };
59
- },
60
- });
@@ -1,158 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.minChainedCallDepth = void 0;
4
- const utils_1 = require("@typescript-eslint/utils");
5
- const ast_utils_1 = require("@typescript-eslint/utils/ast-utils");
6
- const createRule_1 = require("../createRule");
7
- exports.minChainedCallDepth = (0, createRule_1.createRule)({
8
- name: 'min-chained-call-depth',
9
- meta: {
10
- type: 'layout',
11
- docs: {
12
- description: 'Enforces a minimum depth for multiline chained calls.',
13
- },
14
- fixable: 'whitespace',
15
- schema: [
16
- {
17
- type: 'object',
18
- properties: {
19
- maxLineLength: {
20
- type: 'integer',
21
- minimum: 1,
22
- default: 100,
23
- },
24
- ignoreChainDeeperThan: {
25
- type: 'integer',
26
- minimum: 1,
27
- maximum: 10,
28
- default: 2,
29
- },
30
- },
31
- additionalProperties: false,
32
- },
33
- ],
34
- messages: {
35
- unexpectedLineBreak: 'Unexpected line break.',
36
- },
37
- },
38
- defaultOptions: [
39
- {
40
- maxLineLength: 100,
41
- ignoreChainDeeperThan: 2,
42
- },
43
- ],
44
- create: context => {
45
- const sourceCode = context.getSourceCode();
46
- let maxDepth = 0;
47
- function getDepth(node) {
48
- let depth = 0;
49
- let currentNode = node;
50
- while (currentNode.type === utils_1.AST_NODE_TYPES.CallExpression
51
- || currentNode.type === utils_1.AST_NODE_TYPES.MemberExpression) {
52
- if (currentNode.type === utils_1.AST_NODE_TYPES.MemberExpression) {
53
- currentNode = currentNode.object;
54
- depth += 1;
55
- }
56
- else if (currentNode.type === utils_1.AST_NODE_TYPES.CallExpression) {
57
- currentNode = currentNode.callee;
58
- }
59
- }
60
- return depth;
61
- }
62
- function check(node) {
63
- // If the node is a member expression inside a call/new expression skip,
64
- // this is to ensure that we consider the correct line length of the result.
65
- //
66
- // Example:
67
- // ```ts
68
- // foo
69
- // .bar();
70
- // ```
71
- // The replacement of this input should be `foo.bar();`, which has 10 character.
72
- // Without this check it would consider the length up to `r`, which is 7.
73
- if (node.type === utils_1.AST_NODE_TYPES.MemberExpression
74
- && node.parent?.type === utils_1.AST_NODE_TYPES.CallExpression) {
75
- return;
76
- }
77
- // If the node is a call/new expression we need to validate it's callee as a member
78
- // expression.
79
- // If the node itself is already a member expression, like the
80
- // `property` in `this.property.function()`, we validate the node directly.
81
- const callee = node.type === utils_1.AST_NODE_TYPES.CallExpression
82
- ? node.callee
83
- : node;
84
- if (
85
- // If the callee is not a member expression, skip.
86
- // For example, root level calls like `foo();`.
87
- callee.type !== utils_1.AST_NODE_TYPES.MemberExpression
88
- // If the callee is a computed member expression, like `foo[bar]()`, skip.
89
- || callee.computed
90
- || callee.object.type === utils_1.AST_NODE_TYPES.NewExpression
91
- // If the callee is already in the same line as it's object, skip.
92
- || callee.object.loc.end.line === callee.property.loc.start.line) {
93
- return;
94
- }
95
- const currentDepth = getDepth(callee);
96
- maxDepth = Math.max(maxDepth, currentDepth);
97
- // Only affect the root level as the total depth is must be known.
98
- // If the current call is nested inside another call, skip.
99
- if (currentDepth > 1) {
100
- return;
101
- }
102
- const { maxLineLength = 100, ignoreChainDeeperThan = 2 } = context.options[0] ?? {};
103
- // If the max depth is greater than ignore threshold, skip
104
- //
105
- // Example:
106
- // ```ts
107
- // Array(10)
108
- // .fill(0)
109
- // .map(x => x + 1)
110
- // .slice(0, 5);
111
- // ```
112
- // In this case the depth is 3, and the default value of ignoreChainDeeperThan is 2.
113
- // So the check can be skipped.
114
- if (maxDepth > ignoreChainDeeperThan) {
115
- return;
116
- }
117
- const { property } = callee;
118
- const lastToken = sourceCode.getLastToken(node, {
119
- filter: token => token.loc.end.line === property.loc.start.line,
120
- });
121
- const semicolon = sourceCode.getLastToken(node.parent, {
122
- filter: token => (token.loc.start.line === property.loc.start.line
123
- && token.type === utils_1.AST_TOKEN_TYPES.Punctuator
124
- && token.value === ';'),
125
- });
126
- const lineLength = callee.object.loc.end.column
127
- + lastToken.loc.end.column - property.loc.start.column
128
- + 1
129
- + (semicolon !== null ? 1 : 0);
130
- if (maxLineLength !== null && lineLength > maxLineLength) {
131
- return;
132
- }
133
- const punctuator = sourceCode.getTokenBefore(callee.property);
134
- const previousToken = sourceCode.getTokenBefore(punctuator, { includeComments: true });
135
- const nextToken = sourceCode.getTokenAfter(punctuator, { includeComments: true });
136
- if ((0, ast_utils_1.isCommentToken)(previousToken) || (0, ast_utils_1.isCommentToken)(nextToken)) {
137
- return;
138
- }
139
- context.report({
140
- node: node,
141
- loc: {
142
- start: callee.object.loc.end,
143
- end: callee.property.loc.start,
144
- },
145
- messageId: 'unexpectedLineBreak',
146
- fix: fixer => fixer.replaceTextRange([previousToken.range[1], nextToken.range[0]], punctuator.value),
147
- });
148
- }
149
- return {
150
- CallExpression: (node) => {
151
- check(node);
152
- },
153
- MemberExpression: (node) => {
154
- check(node);
155
- },
156
- };
157
- },
158
- });
@@ -1,119 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.newlinePerChainedCall = void 0;
4
- const utils_1 = require("@typescript-eslint/utils");
5
- const createRule_1 = require("../createRule");
6
- const LINEBREAK_MATCHER = /\r\n|[\r\n\u2028\u2029]/u;
7
- exports.newlinePerChainedCall = (0, createRule_1.createRule)({
8
- name: 'newline-per-chained-call',
9
- meta: {
10
- type: 'layout',
11
- docs: {
12
- description: 'Require a newline after each call in a method chain',
13
- },
14
- fixable: 'whitespace',
15
- schema: [
16
- {
17
- type: 'object',
18
- properties: {
19
- ignoreChainDeeperThan: {
20
- type: 'integer',
21
- minimum: 1,
22
- maximum: 10,
23
- default: 2,
24
- },
25
- },
26
- additionalProperties: false,
27
- },
28
- ],
29
- messages: {
30
- expectedLineBreak: 'Expected line break before `{{propertyName}}`.',
31
- },
32
- },
33
- defaultOptions: [
34
- {
35
- ignoreChainDeeperThan: 2,
36
- },
37
- ],
38
- create: context => {
39
- const options = context.options[0] ?? {};
40
- const ignoreChainWithDepth = options.ignoreChainDeeperThan ?? 2;
41
- const sourceCode = context.getSourceCode();
42
- function getPropertyText(node) {
43
- const prefix = '.';
44
- const lines = sourceCode.getText(node.property).split(LINEBREAK_MATCHER);
45
- return prefix + lines[0];
46
- }
47
- function hasObjectAndPropertyOnSameLine(node) {
48
- return node.object.loc.end.line === node.property.loc.start.line;
49
- }
50
- function isNotClosingParenToken(token) {
51
- return token.value !== ')' || token.type !== utils_1.TSESTree.AST_TOKEN_TYPES.Punctuator;
52
- }
53
- function validateCallExpressionIgnoreDepth(node) {
54
- let hasCallExpression = false;
55
- if (node.type === utils_1.TSESTree.AST_NODE_TYPES.CallExpression) {
56
- hasCallExpression = true;
57
- }
58
- if (node.parent != null
59
- && node.parent.type !== utils_1.TSESTree.AST_NODE_TYPES.CallExpression
60
- && node.parent.type !== utils_1.TSESTree.AST_NODE_TYPES.MemberExpression) {
61
- const memberExpressions = [];
62
- let currentNode = ('callee' in node
63
- ? node.callee
64
- : node);
65
- while (currentNode.type === utils_1.TSESTree.AST_NODE_TYPES.CallExpression
66
- || currentNode.type === utils_1.TSESTree.AST_NODE_TYPES.MemberExpression) {
67
- if (currentNode.type === utils_1.TSESTree.AST_NODE_TYPES.MemberExpression) {
68
- if (currentNode.property.type === utils_1.TSESTree.AST_NODE_TYPES.Identifier
69
- && !currentNode.computed) {
70
- memberExpressions.push(currentNode);
71
- }
72
- currentNode = currentNode.object;
73
- }
74
- else if (currentNode.type === utils_1.TSESTree.AST_NODE_TYPES.CallExpression) {
75
- currentNode = currentNode.callee;
76
- }
77
- }
78
- if (memberExpressions.length > ignoreChainWithDepth
79
- && hasCallExpression
80
- && memberExpressions.some(hasObjectAndPropertyOnSameLine)) {
81
- const expressionsOnSameLine = memberExpressions
82
- .filter(hasObjectAndPropertyOnSameLine);
83
- const rootNode = expressionsOnSameLine[expressionsOnSameLine.length - 1];
84
- if (rootNode.type === utils_1.TSESTree.AST_NODE_TYPES.MemberExpression
85
- && (rootNode.parent != null && (rootNode.parent.type === utils_1.TSESTree.AST_NODE_TYPES.CallExpression
86
- || rootNode.parent.type === utils_1.TSESTree.AST_NODE_TYPES.MemberExpression))
87
- && (rootNode.object.type === utils_1.TSESTree.AST_NODE_TYPES.ThisExpression
88
- || rootNode.object.type === utils_1.TSESTree.AST_NODE_TYPES.Identifier)) {
89
- expressionsOnSameLine.pop();
90
- }
91
- expressionsOnSameLine.forEach(memberExpression => {
92
- context.report({
93
- node: memberExpression.property,
94
- loc: memberExpression.property.loc.start,
95
- messageId: 'expectedLineBreak',
96
- data: {
97
- propertyName: getPropertyText(memberExpression),
98
- },
99
- fix: fixer => {
100
- const firstTokenAfterObject = sourceCode.getTokenAfter(memberExpression.object, isNotClosingParenToken);
101
- return fixer.insertTextBefore(firstTokenAfterObject, '\n');
102
- },
103
- });
104
- });
105
- }
106
- }
107
- }
108
- return {
109
- CallExpression: (node) => {
110
- if (node.callee?.type === utils_1.TSESTree.AST_NODE_TYPES.MemberExpression) {
111
- validateCallExpressionIgnoreDepth(node);
112
- }
113
- },
114
- MemberExpression: (node) => {
115
- validateCallExpressionIgnoreDepth(node);
116
- },
117
- };
118
- },
119
- });
@@ -1,60 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parameterDestructuring = void 0;
4
- const utils_1 = require("@typescript-eslint/utils");
5
- const createRule_1 = require("../createRule");
6
- exports.parameterDestructuring = (0, createRule_1.createRule)({
7
- name: 'parameter-destructuring',
8
- meta: {
9
- type: 'layout',
10
- docs: {
11
- description: 'Prevent noisy destructuring on parameters',
12
- },
13
- hasSuggestions: true,
14
- schema: [],
15
- messages: {
16
- unexpectedDestructuring: ('Destructuring should not be done in the parameters. '
17
- + 'Bind to a variable and destructure inside the function.'),
18
- },
19
- },
20
- defaultOptions: [],
21
- create: context => {
22
- const sourceCode = context.getSourceCode();
23
- return {
24
- ObjectPattern: function checkObjectPattern(node) {
25
- const { parent } = node;
26
- // Skip for destructuring in contexts unrelated to function parameters
27
- if (parent?.type !== utils_1.AST_NODE_TYPES.FunctionExpression
28
- && parent?.type !== utils_1.AST_NODE_TYPES.FunctionDeclaration
29
- && parent?.type !== utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
30
- return;
31
- }
32
- // Allow one-line destructuring
33
- if (node.loc.start.line === node.loc.end.line) {
34
- return;
35
- }
36
- const { body } = parent;
37
- context.report({
38
- node: node,
39
- messageId: 'unexpectedDestructuring',
40
- suggest: body.type === utils_1.AST_NODE_TYPES.BlockStatement
41
- ? [
42
- {
43
- messageId: 'unexpectedDestructuring',
44
- fix: (fixer) => [
45
- // Replace the destructuring with a variable declaration
46
- fixer.replaceText(node, 'value'),
47
- // Add the destructuring inside the body
48
- fixer.insertTextAfter(
49
- // Null safety: a block expression always have the `{` token
50
- // opening the body of the function.
51
- sourceCode.getFirstToken(body), `\nconst ${sourceCode.getText(node)} = value;\n`),
52
- ],
53
- },
54
- ]
55
- : null,
56
- });
57
- },
58
- };
59
- },
60
- });