@croct/eslint-plugin 0.1.3 → 0.2.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.
package/README.md CHANGED
@@ -25,7 +25,7 @@
25
25
 
26
26
  ## Installation
27
27
 
28
- The recommended way to install the SDK is via [NPM](https://npmjs.com). It pairs nicely with module bundlers such as
28
+ The recommended way to install the package is via [NPM](https://npmjs.com). It pairs nicely with module bundlers such as
29
29
  Webpack or Browserify:
30
30
 
31
31
  ```sh
@@ -95,7 +95,6 @@ export declare const configs: {
95
95
  allowNumber: boolean;
96
96
  allowNullableObject: boolean;
97
97
  })[];
98
- '@typescript-eslint/prefer-regexp-exec': string;
99
98
  '@typescript-eslint/prefer-optional-chain': string;
100
99
  'no-shadow': string;
101
100
  '@typescript-eslint/no-shadow': (string | {
@@ -114,7 +113,10 @@ export declare const configs: {
114
113
  indent: (string | number | {
115
114
  SwitchCase: number;
116
115
  })[];
117
- '@typescript-eslint/no-unused-vars': string;
116
+ '@typescript-eslint/no-unused-vars': (string | {
117
+ args: string;
118
+ ignoreRestSiblings: boolean;
119
+ })[];
118
120
  'no-unused-vars': string;
119
121
  '@typescript-eslint/no-non-null-assertion': string;
120
122
  'object-curly-spacing': string;
@@ -156,7 +158,6 @@ export declare const configs: {
156
158
  '@typescript-eslint/type-annotation-spacing'?: undefined;
157
159
  '@typescript-eslint/semi'?: undefined;
158
160
  '@typescript-eslint/strict-boolean-expressions'?: undefined;
159
- '@typescript-eslint/prefer-regexp-exec'?: undefined;
160
161
  '@typescript-eslint/prefer-optional-chain'?: undefined;
161
162
  'no-shadow'?: undefined;
162
163
  '@typescript-eslint/no-shadow'?: undefined;
@@ -190,6 +191,9 @@ export declare const configs: {
190
191
  rules: {
191
192
  '@croct/argument-spacing': string;
192
193
  '@croct/complex-expression-spacing': string;
194
+ '@croct/newline-per-chained-call': string;
195
+ 'newline-per-chained-call': string;
196
+ 'no-plusplus': string;
193
197
  'array-bracket-newline': string[];
194
198
  'multiline-ternary': string[];
195
199
  'no-undef-init': string;
@@ -237,6 +241,10 @@ export declare const configs: {
237
241
  'max-len': (string | {
238
242
  code: number;
239
243
  ignoreStrings: boolean;
244
+ ignoreComments: boolean;
245
+ ignoreTemplateLiterals: boolean;
246
+ ignoreTrailingComments: boolean;
247
+ ignoreUrls: boolean;
240
248
  })[];
241
249
  'no-await-in-loop': string;
242
250
  'no-bitwise': string;
@@ -246,11 +254,11 @@ export declare const configs: {
246
254
  maxEOF: number;
247
255
  maxBOF: number;
248
256
  })[];
249
- 'no-plusplus': (string | {
250
- allowForLoopAfterthoughts: boolean;
251
- })[];
252
257
  'no-unused-expressions': string;
253
- 'no-unused-vars': string;
258
+ 'no-unused-vars': (string | {
259
+ args: string;
260
+ ignoreRestSiblings: boolean;
261
+ })[];
254
262
  'no-restricted-syntax': string[];
255
263
  'object-curly-newline': (string | {
256
264
  multiline: boolean;
@@ -4,6 +4,9 @@ export declare const javascript: {
4
4
  rules: {
5
5
  '@croct/argument-spacing': string;
6
6
  '@croct/complex-expression-spacing': string;
7
+ '@croct/newline-per-chained-call': string;
8
+ 'newline-per-chained-call': string;
9
+ 'no-plusplus': string;
7
10
  'array-bracket-newline': string[];
8
11
  'multiline-ternary': string[];
9
12
  'no-undef-init': string;
@@ -51,6 +54,10 @@ export declare const javascript: {
51
54
  'max-len': (string | {
52
55
  code: number;
53
56
  ignoreStrings: boolean;
57
+ ignoreComments: boolean;
58
+ ignoreTemplateLiterals: boolean;
59
+ ignoreTrailingComments: boolean;
60
+ ignoreUrls: boolean;
54
61
  })[];
55
62
  'no-await-in-loop': string;
56
63
  'no-bitwise': string;
@@ -60,11 +67,11 @@ export declare const javascript: {
60
67
  maxEOF: number;
61
68
  maxBOF: number;
62
69
  })[];
63
- 'no-plusplus': (string | {
64
- allowForLoopAfterthoughts: boolean;
65
- })[];
66
70
  'no-unused-expressions': string;
67
- 'no-unused-vars': string;
71
+ 'no-unused-vars': (string | {
72
+ args: string;
73
+ ignoreRestSiblings: boolean;
74
+ })[];
68
75
  'no-restricted-syntax': string[];
69
76
  'object-curly-newline': (string | {
70
77
  multiline: boolean;
@@ -16,6 +16,9 @@ exports.javascript = {
16
16
  rules: {
17
17
  '@croct/argument-spacing': 'error',
18
18
  '@croct/complex-expression-spacing': 'error',
19
+ '@croct/newline-per-chained-call': 'error',
20
+ 'newline-per-chained-call': 'off',
21
+ 'no-plusplus': 'off',
19
22
  'array-bracket-newline': [
20
23
  'error',
21
24
  'consistent',
@@ -99,7 +102,11 @@ exports.javascript = {
99
102
  'error',
100
103
  {
101
104
  code: 100,
102
- ignoreStrings: true,
105
+ ignoreStrings: false,
106
+ ignoreComments: false,
107
+ ignoreTemplateLiterals: false,
108
+ ignoreTrailingComments: false,
109
+ ignoreUrls: false,
103
110
  },
104
111
  ],
105
112
  'no-await-in-loop': 'off',
@@ -113,14 +120,14 @@ exports.javascript = {
113
120
  maxBOF: 0,
114
121
  },
115
122
  ],
116
- 'no-plusplus': [
123
+ 'no-unused-expressions': 'error',
124
+ 'no-unused-vars': [
117
125
  'error',
118
126
  {
119
- allowForLoopAfterthoughts: true,
127
+ args: 'after-used',
128
+ ignoreRestSiblings: true,
120
129
  },
121
130
  ],
122
- 'no-unused-expressions': 'error',
123
- 'no-unused-vars': 'error',
124
131
  'no-restricted-syntax': [
125
132
  'error',
126
133
  'ForInStatement',
@@ -18,7 +18,6 @@ export declare const typescript: {
18
18
  allowNumber: boolean;
19
19
  allowNullableObject: boolean;
20
20
  })[];
21
- '@typescript-eslint/prefer-regexp-exec': string;
22
21
  '@typescript-eslint/prefer-optional-chain': string;
23
22
  'no-shadow': string;
24
23
  '@typescript-eslint/no-shadow': (string | {
@@ -37,7 +36,10 @@ export declare const typescript: {
37
36
  indent: (string | number | {
38
37
  SwitchCase: number;
39
38
  })[];
40
- '@typescript-eslint/no-unused-vars': string;
39
+ '@typescript-eslint/no-unused-vars': (string | {
40
+ args: string;
41
+ ignoreRestSiblings: boolean;
42
+ })[];
41
43
  'no-unused-vars': string;
42
44
  '@typescript-eslint/no-non-null-assertion': string;
43
45
  'object-curly-spacing': string;
@@ -79,7 +81,6 @@ export declare const typescript: {
79
81
  '@typescript-eslint/type-annotation-spacing'?: undefined;
80
82
  '@typescript-eslint/semi'?: undefined;
81
83
  '@typescript-eslint/strict-boolean-expressions'?: undefined;
82
- '@typescript-eslint/prefer-regexp-exec'?: undefined;
83
84
  '@typescript-eslint/prefer-optional-chain'?: undefined;
84
85
  'no-shadow'?: undefined;
85
86
  '@typescript-eslint/no-shadow'?: undefined;
@@ -25,7 +25,6 @@ exports.typescript = {
25
25
  allowNumber: false,
26
26
  allowNullableObject: false,
27
27
  }],
28
- '@typescript-eslint/prefer-regexp-exec': 'error',
29
28
  '@typescript-eslint/prefer-optional-chain': 'error',
30
29
  'no-shadow': 'off',
31
30
  '@typescript-eslint/no-shadow': ['error', {
@@ -46,7 +45,13 @@ exports.typescript = {
46
45
  indent: ['error', 4, {
47
46
  SwitchCase: 1,
48
47
  }],
49
- '@typescript-eslint/no-unused-vars': 'error',
48
+ '@typescript-eslint/no-unused-vars': [
49
+ 'error',
50
+ {
51
+ args: 'after-used',
52
+ ignoreRestSiblings: true,
53
+ },
54
+ ],
50
55
  'no-unused-vars': 'off',
51
56
  '@typescript-eslint/no-non-null-assertion': 'off',
52
57
  'object-curly-spacing': 'off',
package/index.d.ts CHANGED
@@ -11,6 +11,12 @@ declare const configuration: {
11
11
  ArrowFunctionExpression: (node: import("@typescript-eslint/types/dist/ast-spec").ArrowFunctionExpression) => void;
12
12
  IfStatement: (node: import("@typescript-eslint/types/dist/ast-spec").IfStatement) => void;
13
13
  }>;
14
+ 'newline-per-chained-call': import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"expectedLineBreak", {
15
+ ignoreChainWithDepth: number;
16
+ }[], {
17
+ CallExpression: (node: import("@typescript-eslint/types/dist/ast-spec").CallExpression) => void;
18
+ MemberExpression: (node: import("@typescript-eslint/types/dist/ast-spec").MemberExpression) => void;
19
+ }>;
14
20
  };
15
21
  configs: {
16
22
  cypress: {
@@ -109,7 +115,6 @@ declare const configuration: {
109
115
  allowNumber: boolean;
110
116
  allowNullableObject: boolean;
111
117
  })[];
112
- '@typescript-eslint/prefer-regexp-exec': string;
113
118
  '@typescript-eslint/prefer-optional-chain': string;
114
119
  'no-shadow': string;
115
120
  '@typescript-eslint/no-shadow': (string | {
@@ -128,7 +133,10 @@ declare const configuration: {
128
133
  indent: (string | number | {
129
134
  SwitchCase: number;
130
135
  })[];
131
- '@typescript-eslint/no-unused-vars': string;
136
+ '@typescript-eslint/no-unused-vars': (string | {
137
+ args: string;
138
+ ignoreRestSiblings: boolean;
139
+ })[];
132
140
  'no-unused-vars': string;
133
141
  '@typescript-eslint/no-non-null-assertion': string;
134
142
  'object-curly-spacing': string;
@@ -170,7 +178,6 @@ declare const configuration: {
170
178
  '@typescript-eslint/type-annotation-spacing'?: undefined;
171
179
  '@typescript-eslint/semi'?: undefined;
172
180
  '@typescript-eslint/strict-boolean-expressions'?: undefined;
173
- '@typescript-eslint/prefer-regexp-exec'?: undefined;
174
181
  '@typescript-eslint/prefer-optional-chain'?: undefined;
175
182
  'no-shadow'?: undefined;
176
183
  '@typescript-eslint/no-shadow'?: undefined;
@@ -204,6 +211,9 @@ declare const configuration: {
204
211
  rules: {
205
212
  '@croct/argument-spacing': string;
206
213
  '@croct/complex-expression-spacing': string;
214
+ '@croct/newline-per-chained-call': string;
215
+ 'newline-per-chained-call': string;
216
+ 'no-plusplus': string;
207
217
  'array-bracket-newline': string[];
208
218
  'multiline-ternary': string[];
209
219
  'no-undef-init': string;
@@ -251,6 +261,10 @@ declare const configuration: {
251
261
  'max-len': (string | {
252
262
  code: number;
253
263
  ignoreStrings: boolean;
264
+ ignoreComments: boolean;
265
+ ignoreTemplateLiterals: boolean;
266
+ ignoreTrailingComments: boolean;
267
+ ignoreUrls: boolean;
254
268
  })[];
255
269
  'no-await-in-loop': string;
256
270
  'no-bitwise': string;
@@ -260,11 +274,11 @@ declare const configuration: {
260
274
  maxEOF: number;
261
275
  maxBOF: number;
262
276
  })[];
263
- 'no-plusplus': (string | {
264
- allowForLoopAfterthoughts: boolean;
265
- })[];
266
277
  'no-unused-expressions': string;
267
- 'no-unused-vars': string;
278
+ 'no-unused-vars': (string | {
279
+ args: string;
280
+ ignoreRestSiblings: boolean;
281
+ })[];
268
282
  'no-restricted-syntax': string[];
269
283
  'object-curly-newline': (string | {
270
284
  multiline: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@croct/eslint-plugin",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "ESLint rules and presets applied to all Croct JavaScript projects.",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -7,7 +7,8 @@ exports.argumentSpacing = (0, createRule_1.createRule)({
7
7
  meta: {
8
8
  type: 'suggestion',
9
9
  docs: {
10
- description: 'Enforces a surrounding line break before and after the argument list in multiline functional calls.',
10
+ description: 'Enforces a surrounding line break before and after '
11
+ + 'the argument list in multiline functional calls.',
11
12
  recommended: 'error',
12
13
  },
13
14
  fixable: 'whitespace',
@@ -34,7 +35,8 @@ exports.argumentSpacing = (0, createRule_1.createRule)({
34
35
  return;
35
36
  }
36
37
  const lastArgumentFirstToken = sourceCode.getFirstToken(lastArgument);
37
- if ((lastArgument.type !== 'ArrowFunctionExpression' || lastArgument.body.type === 'BlockStatement')
38
+ if ((lastArgument.type !== 'ArrowFunctionExpression'
39
+ || lastArgument.body.type === 'BlockStatement')
38
40
  && firstToken.loc.start.line === lastArgumentFirstToken.loc.start.line) {
39
41
  return;
40
42
  }
package/rules/index.d.ts CHANGED
@@ -10,4 +10,10 @@ export declare const rules: {
10
10
  ArrowFunctionExpression: (node: import("@typescript-eslint/types/dist/ast-spec").ArrowFunctionExpression) => void;
11
11
  IfStatement: (node: import("@typescript-eslint/types/dist/ast-spec").IfStatement) => void;
12
12
  }>;
13
+ 'newline-per-chained-call': import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"expectedLineBreak", {
14
+ ignoreChainWithDepth: number;
15
+ }[], {
16
+ CallExpression: (node: import("@typescript-eslint/types/dist/ast-spec").CallExpression) => void;
17
+ MemberExpression: (node: import("@typescript-eslint/types/dist/ast-spec").MemberExpression) => void;
18
+ }>;
13
19
  };
package/rules/index.js CHANGED
@@ -4,8 +4,10 @@ exports.rules = void 0;
4
4
  const argument_spacing_1 = require("./argument-spacing");
5
5
  const jsx_attribute_spacing_1 = require("./jsx-attribute-spacing");
6
6
  const complex_expression_spacing_1 = require("./complex-expression-spacing");
7
+ const newline_per_chained_call_1 = require("./newline-per-chained-call");
7
8
  exports.rules = {
8
9
  'argument-spacing': argument_spacing_1.argumentSpacing,
9
10
  'jsx-attribute-spacing': jsx_attribute_spacing_1.jsxAttributeSpacing,
10
11
  'complex-expression-spacing': complex_expression_spacing_1.complexExpressionSpacing,
12
+ 'newline-per-chained-call': newline_per_chained_call_1.newlinePerChainedCall,
11
13
  };
@@ -0,0 +1,7 @@
1
+ import { TSESTree } from '@typescript-eslint/experimental-utils';
2
+ export declare const newlinePerChainedCall: import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<"expectedLineBreak", {
3
+ ignoreChainWithDepth: number;
4
+ }[], {
5
+ CallExpression: (node: TSESTree.CallExpression) => void;
6
+ MemberExpression: (node: TSESTree.MemberExpression) => void;
7
+ }>;
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.newlinePerChainedCall = void 0;
4
+ const createRule_1 = require("../createRule");
5
+ const LINEBREAK_MATCHER = /\r\n|[\r\n\u2028\u2029]/u;
6
+ exports.newlinePerChainedCall = (0, createRule_1.createRule)({
7
+ name: 'newline-per-chained-call',
8
+ meta: {
9
+ type: 'layout',
10
+ docs: {
11
+ description: 'Require a newline after each call in a method chain',
12
+ recommended: 'error',
13
+ },
14
+ fixable: 'whitespace',
15
+ schema: [
16
+ {
17
+ type: 'object',
18
+ properties: {
19
+ ignoreChainWithDepth: {
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
+ ignoreChainWithDepth: 2,
36
+ },
37
+ ],
38
+ create: context => {
39
+ var _a, _b;
40
+ const options = (_a = context.options[0]) !== null && _a !== void 0 ? _a : {};
41
+ const ignoreChainWithDepth = (_b = options.ignoreChainWithDepth) !== null && _b !== void 0 ? _b : 2;
42
+ const sourceCode = context.getSourceCode();
43
+ function getPropertyText(node) {
44
+ const prefix = '.';
45
+ const lines = sourceCode.getText(node.property)
46
+ .split(LINEBREAK_MATCHER);
47
+ return prefix + lines[0];
48
+ }
49
+ function hasObjectAndPropertyOnSameLine(node) {
50
+ return node.object.loc.end.line === node.property.loc.start.line;
51
+ }
52
+ function isNotClosingParenToken(token) {
53
+ return token.value !== ')' || token.type !== 'Punctuator';
54
+ }
55
+ function validateCallExpressionIgnoreDepth(node) {
56
+ let hasCallExpression = false;
57
+ if (node.type === 'CallExpression') {
58
+ hasCallExpression = true;
59
+ }
60
+ if ((node.parent !== undefined)
61
+ && node.parent.type !== 'CallExpression'
62
+ && node.parent.type !== 'MemberExpression') {
63
+ const memberExpressions = [];
64
+ let currentNode = (node.type === 'CallExpression'
65
+ ? node.callee
66
+ : node);
67
+ while (currentNode.type === 'CallExpression'
68
+ || currentNode.type === 'MemberExpression') {
69
+ if (currentNode.type === 'MemberExpression') {
70
+ if (currentNode.property.type === 'Identifier'
71
+ && !currentNode.computed) {
72
+ memberExpressions.push(currentNode);
73
+ }
74
+ currentNode = currentNode.object;
75
+ }
76
+ else if (currentNode.type === 'CallExpression') {
77
+ currentNode = currentNode.callee;
78
+ }
79
+ }
80
+ if (memberExpressions.length > ignoreChainWithDepth
81
+ && hasCallExpression
82
+ && memberExpressions.some(hasObjectAndPropertyOnSameLine)) {
83
+ memberExpressions
84
+ .filter(hasObjectAndPropertyOnSameLine)
85
+ .forEach(memberExpression => {
86
+ context.report({
87
+ node: memberExpression.property,
88
+ loc: memberExpression.property.loc.start,
89
+ messageId: 'expectedLineBreak',
90
+ data: {
91
+ propertyName: getPropertyText(memberExpression),
92
+ },
93
+ fix: fixer => {
94
+ const firstTokenAfterObject = sourceCode.getTokenAfter(memberExpression.object, isNotClosingParenToken);
95
+ return fixer.insertTextBefore(firstTokenAfterObject, '\n');
96
+ },
97
+ });
98
+ });
99
+ }
100
+ }
101
+ }
102
+ return {
103
+ CallExpression: (node) => {
104
+ var _a;
105
+ if (((_a = node.callee) === null || _a === void 0 ? void 0 : _a.type) === 'MemberExpression') {
106
+ validateCallExpressionIgnoreDepth(node);
107
+ }
108
+ },
109
+ MemberExpression: (node) => {
110
+ validateCallExpressionIgnoreDepth(node);
111
+ },
112
+ };
113
+ },
114
+ });