eslint-plugin-complete 1.0.9 → 1.0.11
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/dist/comments.js +24 -24
- package/dist/completeCommon.js +3 -3
- package/dist/completeSentence.js +34 -32
- package/dist/format.js +33 -33
- package/dist/jsdoc.js +2 -2
- package/dist/leadingLineComments.js +4 -4
- package/dist/list.js +9 -9
- package/dist/rules/complete-sentences-line-comments.js +4 -4
- package/dist/rules/format-jsdoc-comments.js +3 -3
- package/dist/rules/no-empty-line-comments.js +2 -2
- package/dist/rules/no-mutable-return.js +3 -3
- package/dist/rules/no-object-methods-with-map-set.js +4 -4
- package/dist/rules/no-string-length-0.js +4 -4
- package/dist/rules/no-template-curly-in-string-fix.js +2 -2
- package/dist/rules/no-unnecessary-assignment.js +36 -36
- package/dist/rules/no-void-return-type.js +3 -3
- package/dist/rules/prefer-readonly-parameter-types.d.ts.map +1 -1
- package/dist/rules/prefer-readonly-parameter-types.js +20 -8
- package/dist/rules/require-variadic-function-argument.d.ts.map +1 -1
- package/dist/rules/require-variadic-function-argument.js +29 -8
- package/dist/rules/strict-array-methods.js +5 -5
- package/dist/rules/strict-enums.js +16 -16
- package/package.json +8 -8
package/dist/comments.js
CHANGED
|
@@ -18,27 +18,27 @@ export function isEnumBlockLabel(text) {
|
|
|
18
18
|
text = text.trim();
|
|
19
19
|
return (
|
|
20
20
|
// e.g. CollectibleType.SAD_ONION
|
|
21
|
-
/^\w+\.\w+$/.test(text)
|
|
21
|
+
/^\w+\.\w+$/.test(text)
|
|
22
22
|
// e.g. CollectibleType.SAD_ONION (1)
|
|
23
|
-
/^\w+\.\w+ \(\d+\)$/.test(text)
|
|
23
|
+
|| /^\w+\.\w+ \(\d+\)$/.test(text)
|
|
24
24
|
// e.g. CacheFlag.FIRE_DELAY (1 << 1)
|
|
25
|
-
/^\w+\.\w+ \(\d+ << \d+\)$/.test(text)
|
|
25
|
+
|| /^\w+\.\w+ \(\d+ << \d+\)$/.test(text)
|
|
26
26
|
// e.g. 1
|
|
27
|
-
/^\d+$/.test(text)
|
|
27
|
+
|| /^\d+$/.test(text)
|
|
28
28
|
// e.g. 1.0
|
|
29
|
-
/^\d+\.\d+$/.test(text)
|
|
29
|
+
|| /^\d+\.\d+$/.test(text)
|
|
30
30
|
// e.g. 1 << 1
|
|
31
|
-
/^\d+ << \d+$/.test(text)
|
|
31
|
+
|| /^\d+ << \d+$/.test(text)
|
|
32
32
|
// e.g. 1, 2, 3, 4, 5
|
|
33
|
-
/^\d+, \d+$/.test(text)
|
|
34
|
-
/^\d+, \d+, \d+$/.test(text)
|
|
35
|
-
/^(?:\d+, ){3}\d+$/.test(text)
|
|
36
|
-
/^(?:\d+, ){4}\d+$/.test(text)
|
|
33
|
+
|| /^\d+, \d+$/.test(text)
|
|
34
|
+
|| /^\d+, \d+, \d+$/.test(text)
|
|
35
|
+
|| /^(?:\d+, ){3}\d+$/.test(text)
|
|
36
|
+
|| /^(?:\d+, ){4}\d+$/.test(text)
|
|
37
37
|
// e.g. 1.0, 2.0, 3.0, 4.0, 5.0
|
|
38
|
-
/^\d+\.\d+, \d+\.\d+$/.test(text)
|
|
39
|
-
/^(?:\d+\.\d+, ){2}\d+\.\d+$/.test(text)
|
|
40
|
-
/^(?:\d+\.\d+, ){3}\d+\.\d+$/.test(text)
|
|
41
|
-
/^(?:\d+\.\d+, ){4}\d+\.\d+$/.test(text));
|
|
38
|
+
|| /^\d+\.\d+, \d+\.\d+$/.test(text)
|
|
39
|
+
|| /^(?:\d+\.\d+, ){2}\d+\.\d+$/.test(text)
|
|
40
|
+
|| /^(?:\d+\.\d+, ){3}\d+\.\d+$/.test(text)
|
|
41
|
+
|| /^(?:\d+\.\d+, ){4}\d+\.\d+$/.test(text));
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
44
|
* A "separator" line is a line with all hyphens like the following:
|
|
@@ -54,14 +54,14 @@ export function isSeparatorLine(text) {
|
|
|
54
54
|
}
|
|
55
55
|
export function isSpecialComment(text) {
|
|
56
56
|
text = text.trim();
|
|
57
|
-
return (text.startsWith("eslint-")
|
|
58
|
-
text.startsWith("prettier-")
|
|
59
|
-
text.startsWith("cspell:")
|
|
60
|
-
text.startsWith("ts-prune-")
|
|
61
|
-
text.startsWith("@ts-")
|
|
62
|
-
text.startsWith("@template-")
|
|
63
|
-
text.startsWith("TODO:")
|
|
64
|
-
text.startsWith("FIXME:")
|
|
65
|
-
text === "TODO"
|
|
66
|
-
text === "FIXME");
|
|
57
|
+
return (text.startsWith("eslint-")
|
|
58
|
+
|| text.startsWith("prettier-")
|
|
59
|
+
|| text.startsWith("cspell:")
|
|
60
|
+
|| text.startsWith("ts-prune-") // e.g. ts-prune-ignore-next
|
|
61
|
+
|| text.startsWith("@ts-")
|
|
62
|
+
|| text.startsWith("@template-") // e.g. @template-customization-start (complete-cli directives)
|
|
63
|
+
|| text.startsWith("TODO:")
|
|
64
|
+
|| text.startsWith("FIXME:")
|
|
65
|
+
|| text === "TODO"
|
|
66
|
+
|| text === "FIXME");
|
|
67
67
|
}
|
package/dist/completeCommon.js
CHANGED
|
@@ -40,9 +40,9 @@ export function isFirstLetterCapitalized(string) {
|
|
|
40
40
|
* `!Array.isArray(variable)`.
|
|
41
41
|
*/
|
|
42
42
|
export function isObject(variable) {
|
|
43
|
-
return (typeof variable === "object"
|
|
44
|
-
variable !== null
|
|
45
|
-
!Array.isArray(variable));
|
|
43
|
+
return (typeof variable === "object"
|
|
44
|
+
&& variable !== null
|
|
45
|
+
&& !Array.isArray(variable));
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
48
48
|
* Helper function to trim a prefix from a string, if it exists. Returns the trimmed string.
|
package/dist/completeSentence.js
CHANGED
|
@@ -160,28 +160,28 @@ function getIncompleteSentenceKind(sentence, isLoneSentence) {
|
|
|
160
160
|
// Ignore / whitelist some specific things.
|
|
161
161
|
if (
|
|
162
162
|
// Blank text.
|
|
163
|
-
text === ""
|
|
163
|
+
text === ""
|
|
164
164
|
// Sentences that do not contain any letters.
|
|
165
|
-
!/[A-Za-z]/.test(text)
|
|
165
|
+
|| !/[A-Za-z]/.test(text)
|
|
166
166
|
// Sentences with an arrow, like: "Alice --> Bob"
|
|
167
|
-
text.includes("-->")
|
|
167
|
+
|| text.includes("-->")
|
|
168
168
|
// Placeholder text.
|
|
169
|
-
text === "n/a"
|
|
169
|
+
|| text === "n/a"
|
|
170
170
|
// Special comments.
|
|
171
|
-
isSpecialComment(text)
|
|
171
|
+
|| isSpecialComment(text)
|
|
172
172
|
// Dates.
|
|
173
|
-
isDate(text)
|
|
173
|
+
|| isDate(text)
|
|
174
174
|
// URLS.
|
|
175
|
-
hasURL(text)
|
|
175
|
+
|| hasURL(text)
|
|
176
176
|
// Single JSDoc tags.
|
|
177
|
-
/^@\w+$/.test(text)
|
|
177
|
+
|| /^@\w+$/.test(text)
|
|
178
178
|
// Lists.
|
|
179
|
-
text.startsWith(LIST_ELEMENT_IDENTIFIER)
|
|
179
|
+
|| text.startsWith(LIST_ELEMENT_IDENTIFIER)
|
|
180
180
|
// Code blocks.
|
|
181
|
-
text.includes("```")
|
|
181
|
+
|| text.includes("```")
|
|
182
182
|
// Sentences that end with a number in parenthesis (which indicates some kind of expression).
|
|
183
183
|
// This must check the original text.
|
|
184
|
-
/ \(\d+\)$/.test(sentence.trimEnd())) {
|
|
184
|
+
|| / \(\d+\)$/.test(sentence.trimEnd())) {
|
|
185
185
|
return undefined;
|
|
186
186
|
}
|
|
187
187
|
// First, check for a double period.
|
|
@@ -191,9 +191,11 @@ function getIncompleteSentenceKind(sentence, isLoneSentence) {
|
|
|
191
191
|
return "doublePeriod";
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
|
-
if (isLoneSentence
|
|
194
|
+
if (isLoneSentence
|
|
195
195
|
// Single words, double words, and triple words.
|
|
196
|
-
|
|
196
|
+
&& (/^\S+$/.test(text)
|
|
197
|
+
|| /^\S+ \S+$/.test(text)
|
|
198
|
+
|| /^\S+ \S+ \S+$/.test(text))) {
|
|
197
199
|
return undefined;
|
|
198
200
|
}
|
|
199
201
|
if (/^[a-z]/.test(text) && !isCapitalizedWordException(text)) {
|
|
@@ -201,23 +203,23 @@ function getIncompleteSentenceKind(sentence, isLoneSentence) {
|
|
|
201
203
|
}
|
|
202
204
|
if (
|
|
203
205
|
// Allow normal end-of-line punctuation.
|
|
204
|
-
!text.endsWith(".")
|
|
205
|
-
!text.endsWith("!")
|
|
206
|
-
!text.endsWith("?")
|
|
206
|
+
!text.endsWith(".")
|
|
207
|
+
&& !text.endsWith("!")
|
|
208
|
+
&& !text.endsWith("?")
|
|
207
209
|
// Allow ending with a period inside of a single quote or double quote, since it is implied that
|
|
208
210
|
// this is a fully quoted sentence.
|
|
209
|
-
!text.endsWith('."')
|
|
210
|
-
!text.endsWith('!"')
|
|
211
|
-
!text.endsWith('?"')
|
|
212
|
-
!text.endsWith(".'")
|
|
213
|
-
!text.endsWith("!'")
|
|
214
|
-
!text.endsWith("?'")
|
|
211
|
+
&& !text.endsWith('."')
|
|
212
|
+
&& !text.endsWith('!"')
|
|
213
|
+
&& !text.endsWith('?"')
|
|
214
|
+
&& !text.endsWith(".'")
|
|
215
|
+
&& !text.endsWith("!'")
|
|
216
|
+
&& !text.endsWith("?'")
|
|
215
217
|
// Allow ending with a colon, since it is implied that there is an example of something on the
|
|
216
218
|
// subsequent block.
|
|
217
|
-
!text.endsWith(":")
|
|
219
|
+
&& !text.endsWith(":")
|
|
218
220
|
// Allow ending with anything if there is a colon in the middle of the sentence, since it is
|
|
219
221
|
// implied that this is an example of something.
|
|
220
|
-
!text.includes(": ")) {
|
|
222
|
+
&& !text.includes(": ")) {
|
|
221
223
|
return "missingPeriod";
|
|
222
224
|
}
|
|
223
225
|
return undefined;
|
|
@@ -246,20 +248,20 @@ function isDate(text) {
|
|
|
246
248
|
const match1 = text.match(/^(?<month>\w+) \d+(?<ordinal>\w+)$/);
|
|
247
249
|
if (match1 !== null && match1.groups !== undefined) {
|
|
248
250
|
const { month, ordinal } = match1.groups;
|
|
249
|
-
if (month !== undefined
|
|
250
|
-
MONTHS_SET.has(month)
|
|
251
|
-
ordinal !== undefined
|
|
252
|
-
ORDINALS_SET.has(ordinal)) {
|
|
251
|
+
if (month !== undefined
|
|
252
|
+
&& MONTHS_SET.has(month)
|
|
253
|
+
&& ordinal !== undefined
|
|
254
|
+
&& ORDINALS_SET.has(ordinal)) {
|
|
253
255
|
return true;
|
|
254
256
|
}
|
|
255
257
|
}
|
|
256
258
|
const match2 = text.match(/^(?<month>\w+) \d+(?<ordinal>\w+), \d+$/);
|
|
257
259
|
if (match2 !== null && match2.groups !== undefined) {
|
|
258
260
|
const { month, ordinal } = match2.groups;
|
|
259
|
-
if (month !== undefined
|
|
260
|
-
MONTHS_SET.has(month)
|
|
261
|
-
ordinal !== undefined
|
|
262
|
-
ORDINALS_SET.has(ordinal)) {
|
|
261
|
+
if (month !== undefined
|
|
262
|
+
&& MONTHS_SET.has(month)
|
|
263
|
+
&& ordinal !== undefined
|
|
264
|
+
&& ORDINALS_SET.has(ordinal)) {
|
|
263
265
|
return true;
|
|
264
266
|
}
|
|
265
267
|
}
|
package/dist/format.js
CHANGED
|
@@ -66,26 +66,26 @@ export function formatText(text, maxLength, shouldParseJSDocTags = true) {
|
|
|
66
66
|
// Append the blank line, but ignore multiple blank lines in a row (unless we are inside of a
|
|
67
67
|
// code block).
|
|
68
68
|
const lastCharacter = formattedText.at(-1);
|
|
69
|
-
if ((lastCharacter !== undefined && lastCharacter !== "\n")
|
|
70
|
-
insideCodeBlock) {
|
|
69
|
+
if ((lastCharacter !== undefined && lastCharacter !== "\n")
|
|
70
|
+
|| insideCodeBlock) {
|
|
71
71
|
formattedText += "\n";
|
|
72
72
|
}
|
|
73
73
|
insideList = undefined;
|
|
74
74
|
continue;
|
|
75
75
|
}
|
|
76
76
|
// Handle code blocks. This case is simple because we need to exactly preserve the text.
|
|
77
|
-
if (hasCodeBlock
|
|
78
|
-
previousLineHasCodeBlock
|
|
79
|
-
insideCodeBlock
|
|
80
|
-
insideExampleTagBlock) {
|
|
77
|
+
if (hasCodeBlock
|
|
78
|
+
|| previousLineHasCodeBlock
|
|
79
|
+
|| insideCodeBlock
|
|
80
|
+
|| insideExampleTagBlock) {
|
|
81
81
|
// Append the partial line that we were building, if any.
|
|
82
82
|
[formattedLine, formattedText] = appendLineToText(formattedLine, formattedText);
|
|
83
83
|
// Enforce newlines before the beginning of code blocks. (But not inside of an example code
|
|
84
84
|
// block, because there should not be newlines between tags.)
|
|
85
|
-
if (hasCodeBlock
|
|
86
|
-
!previousLineInsideCodeBlock
|
|
87
|
-
!previousLineWasBlank
|
|
88
|
-
!insideExampleTagBlock) {
|
|
85
|
+
if (hasCodeBlock
|
|
86
|
+
&& !previousLineInsideCodeBlock
|
|
87
|
+
&& !previousLineWasBlank
|
|
88
|
+
&& !insideExampleTagBlock) {
|
|
89
89
|
formattedText += "\n";
|
|
90
90
|
}
|
|
91
91
|
// Copy the line exactly.
|
|
@@ -94,10 +94,10 @@ export function formatText(text, maxLength, shouldParseJSDocTags = true) {
|
|
|
94
94
|
// because there should not be newlines between tags.)
|
|
95
95
|
const nextLine = lines[i + 1];
|
|
96
96
|
const nextLineIsBlank = nextLine === undefined || nextLine.trim() === "";
|
|
97
|
-
if (hasCodeBlock
|
|
98
|
-
previousLineInsideCodeBlock
|
|
99
|
-
!nextLineIsBlank
|
|
100
|
-
!insideExampleTagBlock) {
|
|
97
|
+
if (hasCodeBlock
|
|
98
|
+
&& previousLineInsideCodeBlock
|
|
99
|
+
&& !nextLineIsBlank
|
|
100
|
+
&& !insideExampleTagBlock) {
|
|
101
101
|
// Append the partial line that we were building, if any.
|
|
102
102
|
[formattedLine, formattedText] = appendLineToText(formattedLine, formattedText);
|
|
103
103
|
formattedText += "\n";
|
|
@@ -131,30 +131,30 @@ export function formatText(text, maxLength, shouldParseJSDocTags = true) {
|
|
|
131
131
|
}
|
|
132
132
|
// Lists and some other specific text elements indicate that we should always insert a new line,
|
|
133
133
|
// even if the text has no wrapped to the end of the ruler yet.
|
|
134
|
-
if (list !== undefined
|
|
135
|
-
lineHasURL
|
|
136
|
-
previousLineHadURL
|
|
137
|
-
hasExample
|
|
138
|
-
separatorLine
|
|
139
|
-
previousLineWasSeparatorLine
|
|
140
|
-
enumBlockLabel
|
|
141
|
-
previousLineWasEnumBlockLabel) {
|
|
134
|
+
if (list !== undefined
|
|
135
|
+
|| lineHasURL
|
|
136
|
+
|| previousLineHadURL
|
|
137
|
+
|| hasExample
|
|
138
|
+
|| separatorLine
|
|
139
|
+
|| previousLineWasSeparatorLine
|
|
140
|
+
|| enumBlockLabel
|
|
141
|
+
|| previousLineWasEnumBlockLabel) {
|
|
142
142
|
// Append the partial line that we were building, if any.
|
|
143
143
|
[formattedLine, formattedText] = appendLineToText(formattedLine, formattedText);
|
|
144
144
|
}
|
|
145
145
|
// Keep track of when we first encounter JSDoc tags. (JSDoc comments can be thought of as having
|
|
146
146
|
// an "description" or "introductory" section at the top, and then a list of JSDoc tags at the
|
|
147
147
|
// bottom.)
|
|
148
|
-
if (shouldParseJSDocTags
|
|
149
|
-
!encounteredJSDocTags
|
|
150
|
-
list !== undefined
|
|
151
|
-
list.kind === ListKind.JSDocTag) {
|
|
148
|
+
if (shouldParseJSDocTags
|
|
149
|
+
&& !encounteredJSDocTags
|
|
150
|
+
&& list !== undefined
|
|
151
|
+
&& list.kind === ListKind.JSDocTag) {
|
|
152
152
|
encounteredJSDocTags = true;
|
|
153
153
|
// Enforce a newline between a JSDoc description (i.e. introductory text) and the first JSDoc
|
|
154
154
|
// tag.
|
|
155
|
-
if (!stringContainsOnlyWhitespace(formattedText)
|
|
156
|
-
!previousLineWasBlank
|
|
157
|
-
!previousLineInsideExampleTagBlock) {
|
|
155
|
+
if (!stringContainsOnlyWhitespace(formattedText)
|
|
156
|
+
&& !previousLineWasBlank
|
|
157
|
+
&& !previousLineInsideExampleTagBlock) {
|
|
158
158
|
// Append the partial line that we were building, if any.
|
|
159
159
|
[formattedLine, formattedText] = appendLineToText(formattedLine, formattedText);
|
|
160
160
|
formattedText += "\n";
|
|
@@ -226,10 +226,10 @@ function appendLineToText(formattedLine, formattedText) {
|
|
|
226
226
|
}
|
|
227
227
|
function startsWithExample(text) {
|
|
228
228
|
const trimmedText = text.trimStart();
|
|
229
|
-
return (trimmedText.startsWith("e.g. ")
|
|
230
|
-
trimmedText.startsWith("(e.g. ")
|
|
231
|
-
trimmedText.startsWith("i.e. ")
|
|
232
|
-
trimmedText.startsWith("(i.e. "));
|
|
229
|
+
return (trimmedText.startsWith("e.g. ")
|
|
230
|
+
|| trimmedText.startsWith("(e.g. ")
|
|
231
|
+
|| trimmedText.startsWith("i.e. ")
|
|
232
|
+
|| trimmedText.startsWith("(i.e. "));
|
|
233
233
|
}
|
|
234
234
|
function stringContainsOnlyWhitespace(string) {
|
|
235
235
|
return string.trim() === "";
|
package/dist/jsdoc.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TSESTree } from "@typescript-eslint/utils";
|
|
2
2
|
export function getJSDocComments(comments) {
|
|
3
|
-
return comments.filter((comment) => comment.type === TSESTree.AST_TOKEN_TYPES.Block
|
|
4
|
-
comment.value.startsWith("*"));
|
|
3
|
+
return comments.filter((comment) => comment.type === TSESTree.AST_TOKEN_TYPES.Block // i.e. a "/*" comment
|
|
4
|
+
&& comment.value.startsWith("*"));
|
|
5
5
|
}
|
|
6
6
|
export function getTextFromJSDocComment(comment) {
|
|
7
7
|
comment = comment.trim();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { TSESTree } from "@typescript-eslint/utils";
|
|
2
2
|
import { isCommentOnOwnLine, isSeparatorLine } from "./comments.js";
|
|
3
3
|
export function getLeadingLineComments(sourceCode, comments) {
|
|
4
|
-
return comments.filter((comment) => comment.type === TSESTree.AST_TOKEN_TYPES.Line
|
|
5
|
-
comment.value.trim() !== ""
|
|
6
|
-
!comment.value.startsWith("/")
|
|
7
|
-
isCommentOnOwnLine(sourceCode, comment));
|
|
4
|
+
return comments.filter((comment) => comment.type === TSESTree.AST_TOKEN_TYPES.Line // i.e. a "//" comment
|
|
5
|
+
&& comment.value.trim() !== ""
|
|
6
|
+
&& !comment.value.startsWith("/") // Filter out triple slash directives
|
|
7
|
+
&& isCommentOnOwnLine(sourceCode, comment));
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* Returns an array of grouped comments. For example, the following code would return an array of
|
package/dist/list.js
CHANGED
|
@@ -60,9 +60,9 @@ function getList(line) {
|
|
|
60
60
|
}
|
|
61
61
|
/** e.g. "1. A bullet point can start with a number and a period." */
|
|
62
62
|
const numberPeriodMatch = line.match(/^(\d+)\. /);
|
|
63
|
-
if (numberPeriodMatch !== null
|
|
64
|
-
numberPeriodMatch[1] !== undefined
|
|
65
|
-
numberPeriodMatch[1] !== "0") {
|
|
63
|
+
if (numberPeriodMatch !== null
|
|
64
|
+
&& numberPeriodMatch[1] !== undefined
|
|
65
|
+
&& numberPeriodMatch[1] !== "0") {
|
|
66
66
|
return {
|
|
67
67
|
kind: ListKind.NumberPeriod,
|
|
68
68
|
numLeadingSpaces,
|
|
@@ -71,9 +71,9 @@ function getList(line) {
|
|
|
71
71
|
}
|
|
72
72
|
/** e.g. "1) A bullet point can start with a number and a parenthesis." */
|
|
73
73
|
const numberParenthesisMatch = line.match(/^(\d+)\) /);
|
|
74
|
-
if (numberParenthesisMatch !== null
|
|
75
|
-
numberParenthesisMatch[1] !== undefined
|
|
76
|
-
numberParenthesisMatch[1] !== "0") {
|
|
74
|
+
if (numberParenthesisMatch !== null
|
|
75
|
+
&& numberParenthesisMatch[1] !== undefined
|
|
76
|
+
&& numberParenthesisMatch[1] !== "0") {
|
|
77
77
|
return {
|
|
78
78
|
kind: ListKind.NumberParenthesis,
|
|
79
79
|
numLeadingSpaces,
|
|
@@ -133,8 +133,8 @@ export function reachedNewList(insideList, list) {
|
|
|
133
133
|
if (list === undefined) {
|
|
134
134
|
return false;
|
|
135
135
|
}
|
|
136
|
-
return (insideList === undefined
|
|
137
|
-
insideList.numLeadingSpaces !== list.numLeadingSpaces
|
|
138
|
-
insideList.jsDocTagName !== list.jsDocTagName // Going from a JSDoc to a different JSDoc tag
|
|
136
|
+
return (insideList === undefined // Going from a non-list to list
|
|
137
|
+
|| insideList.numLeadingSpaces !== list.numLeadingSpaces // Going from a list to a sub-list
|
|
138
|
+
|| insideList.jsDocTagName !== list.jsDocTagName // Going from a JSDoc to a different JSDoc tag
|
|
139
139
|
);
|
|
140
140
|
}
|
|
@@ -39,13 +39,13 @@ export const completeSentencesLineComments = createRule({
|
|
|
39
39
|
}
|
|
40
40
|
// Comments in-between "separator lines" are whitelisted.
|
|
41
41
|
const previousCommentBlock = commentBlocks[i - 1];
|
|
42
|
-
if (previousCommentBlock !== undefined
|
|
43
|
-
isSeparatorLine(previousCommentBlock.mergedText)) {
|
|
42
|
+
if (previousCommentBlock !== undefined
|
|
43
|
+
&& isSeparatorLine(previousCommentBlock.mergedText)) {
|
|
44
44
|
continue;
|
|
45
45
|
}
|
|
46
46
|
const nextCommentBlock = commentBlocks[i + 1];
|
|
47
|
-
if (nextCommentBlock !== undefined
|
|
48
|
-
isSeparatorLine(nextCommentBlock.mergedText)) {
|
|
47
|
+
if (nextCommentBlock !== undefined
|
|
48
|
+
&& isSeparatorLine(nextCommentBlock.mergedText)) {
|
|
49
49
|
continue;
|
|
50
50
|
}
|
|
51
51
|
// Unlike JSDoc comments, we want to whitelist comment blocks that begin with JavaScript
|
|
@@ -98,9 +98,9 @@ export const formatJSDocComments = createRule({
|
|
|
98
98
|
*/
|
|
99
99
|
function canFitOnSingleJSDocLine(text, effectiveMaxLength) {
|
|
100
100
|
const textLines = text.split("\n");
|
|
101
|
-
return (textLines.length === 1
|
|
102
|
-
text.length + EXTRA_NUM_CHARACTERS_TO_FIT_ON_JSDOC_SINGLE_LINE
|
|
103
|
-
effectiveMaxLength);
|
|
101
|
+
return (textLines.length === 1
|
|
102
|
+
&& text.length + EXTRA_NUM_CHARACTERS_TO_FIT_ON_JSDOC_SINGLE_LINE
|
|
103
|
+
<= effectiveMaxLength);
|
|
104
104
|
}
|
|
105
105
|
function getJSDocCommentSingleLine(text, leftWhitespace) {
|
|
106
106
|
return `${leftWhitespace}/** ${text} */`;
|
|
@@ -23,8 +23,8 @@ export const noEmptyLineComments = createRule({
|
|
|
23
23
|
*/
|
|
24
24
|
create(context) {
|
|
25
25
|
const comments = context.sourceCode.getAllComments();
|
|
26
|
-
const emptyLeadingLineComments = comments.filter((comment) => comment.type === TSESTree.AST_TOKEN_TYPES.Line
|
|
27
|
-
comment.value.trim() === "");
|
|
26
|
+
const emptyLeadingLineComments = comments.filter((comment) => comment.type === TSESTree.AST_TOKEN_TYPES.Line // i.e. a "//" comment
|
|
27
|
+
&& comment.value.trim() === "");
|
|
28
28
|
for (const comment of emptyLeadingLineComments) {
|
|
29
29
|
context.report({
|
|
30
30
|
loc: {
|
|
@@ -53,9 +53,9 @@ function getErrorMessageId(type) {
|
|
|
53
53
|
return undefined;
|
|
54
54
|
}
|
|
55
55
|
// Handle unwrapping promises.
|
|
56
|
-
if (typeName === "Promise"
|
|
57
|
-
isTypeReferenceType(type)
|
|
58
|
-
type.typeArguments !== undefined) {
|
|
56
|
+
if (typeName === "Promise"
|
|
57
|
+
&& isTypeReferenceType(type)
|
|
58
|
+
&& type.typeArguments !== undefined) {
|
|
59
59
|
const typeArgument = type.typeArguments[0];
|
|
60
60
|
if (typeArgument !== undefined) {
|
|
61
61
|
return getErrorMessageId(typeArgument);
|
|
@@ -46,14 +46,14 @@ export const noObjectMethodsWithMapSet = createRule({
|
|
|
46
46
|
}
|
|
47
47
|
// Second, check if the object is `Object`.
|
|
48
48
|
const { object } = callee;
|
|
49
|
-
if (object.type !== AST_NODE_TYPES.Identifier
|
|
50
|
-
object.name !== "Object") {
|
|
49
|
+
if (object.type !== AST_NODE_TYPES.Identifier
|
|
50
|
+
|| object.name !== "Object") {
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
53
|
// Third, check if this is one of the problem methods.
|
|
54
54
|
const { property } = callee;
|
|
55
|
-
if (property.type !== AST_NODE_TYPES.Identifier
|
|
56
|
-
!PROBLEM_METHODS.has(property.name)) {
|
|
55
|
+
if (property.type !== AST_NODE_TYPES.Identifier
|
|
56
|
+
|| !PROBLEM_METHODS.has(property.name)) {
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
59
59
|
const methodName = property.name;
|
|
@@ -24,8 +24,8 @@ export const noStringLength0 = createRule({
|
|
|
24
24
|
if (node.type !== AST_NODE_TYPES.MemberExpression) {
|
|
25
25
|
return false;
|
|
26
26
|
}
|
|
27
|
-
if (node.property.type !== AST_NODE_TYPES.Identifier
|
|
28
|
-
node.property.name !== "length") {
|
|
27
|
+
if (node.property.type !== AST_NODE_TYPES.Identifier
|
|
28
|
+
|| node.property.name !== "length") {
|
|
29
29
|
return false;
|
|
30
30
|
}
|
|
31
31
|
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node.object);
|
|
@@ -36,8 +36,8 @@ export const noStringLength0 = createRule({
|
|
|
36
36
|
}
|
|
37
37
|
return {
|
|
38
38
|
BinaryExpression(node) {
|
|
39
|
-
if ((is0(node.left) && isStringLength(node.right))
|
|
40
|
-
(is0(node.right) && isStringLength(node.left))) {
|
|
39
|
+
if ((is0(node.left) && isStringLength(node.right))
|
|
40
|
+
|| (is0(node.right) && isStringLength(node.left))) {
|
|
41
41
|
context.report({
|
|
42
42
|
node,
|
|
43
43
|
messageId: "noStringLength0",
|
|
@@ -23,8 +23,8 @@ export const noTemplateCurlyInStringFix = createRule({
|
|
|
23
23
|
create(context) {
|
|
24
24
|
return {
|
|
25
25
|
Literal(node) {
|
|
26
|
-
if (typeof node.value === "string"
|
|
27
|
-
ERRONEOUS_TEMPLATE_STRING_REGEX.test(node.value)) {
|
|
26
|
+
if (typeof node.value === "string"
|
|
27
|
+
&& ERRONEOUS_TEMPLATE_STRING_REGEX.test(node.value)) {
|
|
28
28
|
context.report({
|
|
29
29
|
node,
|
|
30
30
|
messageId: "unexpectedTemplateExpression",
|
|
@@ -97,8 +97,8 @@ export const noUnnecessaryAssignment = createRule({
|
|
|
97
97
|
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node);
|
|
98
98
|
const type = checker.getTypeAtLocation(tsNode);
|
|
99
99
|
const types = unionTypeParts(type);
|
|
100
|
-
return (types.some((t) => isFlagSet(t.flags, ts.TypeFlags.Null))
|
|
101
|
-
!types.some((t) => isFlagSet(t.flags, ts.TypeFlags.Undefined)));
|
|
100
|
+
return (types.some((t) => isFlagSet(t.flags, ts.TypeFlags.Null))
|
|
101
|
+
&& !types.some((t) => isFlagSet(t.flags, ts.TypeFlags.Undefined)));
|
|
102
102
|
}
|
|
103
103
|
function hasUndefinedAndNotNull(node) {
|
|
104
104
|
if (isUndefined(node)) {
|
|
@@ -107,8 +107,8 @@ export const noUnnecessaryAssignment = createRule({
|
|
|
107
107
|
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node);
|
|
108
108
|
const type = checker.getTypeAtLocation(tsNode);
|
|
109
109
|
const types = unionTypeParts(type);
|
|
110
|
-
return (types.some((t) => isFlagSet(t.flags, ts.TypeFlags.Undefined))
|
|
111
|
-
!types.some((t) => isFlagSet(t.flags, ts.TypeFlags.Null)));
|
|
110
|
+
return (types.some((t) => isFlagSet(t.flags, ts.TypeFlags.Undefined))
|
|
111
|
+
&& !types.some((t) => isFlagSet(t.flags, ts.TypeFlags.Null)));
|
|
112
112
|
}
|
|
113
113
|
function checkEqualSign(node) {
|
|
114
114
|
const leftTSNode = parserServices.esTreeNodeToTSNodeMap.get(node.left);
|
|
@@ -129,9 +129,9 @@ export const noUnnecessaryAssignment = createRule({
|
|
|
129
129
|
if (node.operator === "=") {
|
|
130
130
|
checkEqualSign(node);
|
|
131
131
|
}
|
|
132
|
-
else if (USELESS_ASSIGNMENT_OPERATORS_WITH_ZERO.has(node.operator)
|
|
133
|
-
isNumber(node.left)
|
|
134
|
-
isLiteralZero(node.right)) {
|
|
132
|
+
else if (USELESS_ASSIGNMENT_OPERATORS_WITH_ZERO.has(node.operator)
|
|
133
|
+
&& isNumber(node.left)
|
|
134
|
+
&& isLiteralZero(node.right)) {
|
|
135
135
|
context.report({
|
|
136
136
|
loc: node.loc,
|
|
137
137
|
messageId: "unnecessaryZero",
|
|
@@ -140,9 +140,9 @@ export const noUnnecessaryAssignment = createRule({
|
|
|
140
140
|
},
|
|
141
141
|
});
|
|
142
142
|
}
|
|
143
|
-
else if (node.operator === "+="
|
|
144
|
-
isString(node.left)
|
|
145
|
-
isLiteralEmptyString(node.right)) {
|
|
143
|
+
else if (node.operator === "+="
|
|
144
|
+
&& isString(node.left)
|
|
145
|
+
&& isLiteralEmptyString(node.right)) {
|
|
146
146
|
context.report({
|
|
147
147
|
loc: node.loc,
|
|
148
148
|
messageId: "unnecessaryEmptyString",
|
|
@@ -150,9 +150,9 @@ export const noUnnecessaryAssignment = createRule({
|
|
|
150
150
|
}
|
|
151
151
|
},
|
|
152
152
|
BinaryExpression(node) {
|
|
153
|
-
if (USELESS_OPERATORS_WITH_ZERO.has(node.operator)
|
|
154
|
-
((isNumber(node.left) && isLiteralZero(node.right))
|
|
155
|
-
(isNumber(node.right) && isLiteralZero(node.left)))) {
|
|
153
|
+
if (USELESS_OPERATORS_WITH_ZERO.has(node.operator)
|
|
154
|
+
&& ((isNumber(node.left) && isLiteralZero(node.right))
|
|
155
|
+
|| (isNumber(node.right) && isLiteralZero(node.left)))) {
|
|
156
156
|
context.report({
|
|
157
157
|
loc: node.loc,
|
|
158
158
|
messageId: "unnecessaryZero",
|
|
@@ -162,9 +162,9 @@ export const noUnnecessaryAssignment = createRule({
|
|
|
162
162
|
});
|
|
163
163
|
}
|
|
164
164
|
// Plus is the only operator valid for strings.
|
|
165
|
-
if (node.operator === "+"
|
|
166
|
-
((isString(node.left) && isLiteralEmptyString(node.right))
|
|
167
|
-
(isString(node.right) && isLiteralEmptyString(node.left)))) {
|
|
165
|
+
if (node.operator === "+"
|
|
166
|
+
&& ((isString(node.left) && isLiteralEmptyString(node.right))
|
|
167
|
+
|| (isString(node.right) && isLiteralEmptyString(node.left)))) {
|
|
168
168
|
context.report({
|
|
169
169
|
loc: node.loc,
|
|
170
170
|
messageId: "unnecessaryEmptyString",
|
|
@@ -173,13 +173,13 @@ export const noUnnecessaryAssignment = createRule({
|
|
|
173
173
|
},
|
|
174
174
|
LogicalExpression(node) {
|
|
175
175
|
const { parent } = node;
|
|
176
|
-
if (parent.type !== AST_NODE_TYPES.AssignmentExpression
|
|
177
|
-
parent.type !== AST_NODE_TYPES.VariableDeclarator) {
|
|
176
|
+
if (parent.type !== AST_NODE_TYPES.AssignmentExpression
|
|
177
|
+
&& parent.type !== AST_NODE_TYPES.VariableDeclarator) {
|
|
178
178
|
return;
|
|
179
179
|
}
|
|
180
|
-
if (node.operator === "||"
|
|
181
|
-
isBoolean(node.left)
|
|
182
|
-
isFalse(node.right)) {
|
|
180
|
+
if (node.operator === "||"
|
|
181
|
+
&& isBoolean(node.left)
|
|
182
|
+
&& isFalse(node.right)) {
|
|
183
183
|
context.report({
|
|
184
184
|
loc: node.loc,
|
|
185
185
|
messageId: "unnecessaryShortCircuit",
|
|
@@ -188,9 +188,9 @@ export const noUnnecessaryAssignment = createRule({
|
|
|
188
188
|
},
|
|
189
189
|
});
|
|
190
190
|
}
|
|
191
|
-
if (node.operator === "&&"
|
|
192
|
-
isBoolean(node.left)
|
|
193
|
-
isTrue(node.right)) {
|
|
191
|
+
if (node.operator === "&&"
|
|
192
|
+
&& isBoolean(node.left)
|
|
193
|
+
&& isTrue(node.right)) {
|
|
194
194
|
context.report({
|
|
195
195
|
loc: node.loc,
|
|
196
196
|
messageId: "unnecessaryShortCircuit",
|
|
@@ -199,9 +199,9 @@ export const noUnnecessaryAssignment = createRule({
|
|
|
199
199
|
},
|
|
200
200
|
});
|
|
201
201
|
}
|
|
202
|
-
if (node.operator === "||"
|
|
203
|
-
isNumber(node.left)
|
|
204
|
-
isZero(node.right)) {
|
|
202
|
+
if (node.operator === "||"
|
|
203
|
+
&& isNumber(node.left)
|
|
204
|
+
&& isZero(node.right)) {
|
|
205
205
|
context.report({
|
|
206
206
|
loc: node.loc,
|
|
207
207
|
messageId: "unnecessaryShortCircuit",
|
|
@@ -210,9 +210,9 @@ export const noUnnecessaryAssignment = createRule({
|
|
|
210
210
|
},
|
|
211
211
|
});
|
|
212
212
|
}
|
|
213
|
-
if (node.operator === "||"
|
|
214
|
-
isString(node.left)
|
|
215
|
-
isEmptyString(node.right)) {
|
|
213
|
+
if (node.operator === "||"
|
|
214
|
+
&& isString(node.left)
|
|
215
|
+
&& isEmptyString(node.right)) {
|
|
216
216
|
context.report({
|
|
217
217
|
loc: node.loc,
|
|
218
218
|
messageId: "unnecessaryShortCircuit",
|
|
@@ -221,9 +221,9 @@ export const noUnnecessaryAssignment = createRule({
|
|
|
221
221
|
},
|
|
222
222
|
});
|
|
223
223
|
}
|
|
224
|
-
if (node.operator === "??"
|
|
225
|
-
hasNullAndNotUndefined(node.left)
|
|
226
|
-
isNull(node.right)) {
|
|
224
|
+
if (node.operator === "??"
|
|
225
|
+
&& hasNullAndNotUndefined(node.left)
|
|
226
|
+
&& isNull(node.right)) {
|
|
227
227
|
context.report({
|
|
228
228
|
loc: node.loc,
|
|
229
229
|
messageId: "unnecessaryShortCircuit",
|
|
@@ -232,9 +232,9 @@ export const noUnnecessaryAssignment = createRule({
|
|
|
232
232
|
},
|
|
233
233
|
});
|
|
234
234
|
}
|
|
235
|
-
if (node.operator === "??"
|
|
236
|
-
hasUndefinedAndNotNull(node.left)
|
|
237
|
-
isUndefined(node.right)) {
|
|
235
|
+
if (node.operator === "??"
|
|
236
|
+
&& hasUndefinedAndNotNull(node.left)
|
|
237
|
+
&& isUndefined(node.right)) {
|
|
238
238
|
context.report({
|
|
239
239
|
loc: node.loc,
|
|
240
240
|
messageId: "unnecessaryShortCircuit",
|
|
@@ -23,9 +23,9 @@ export const noVoidReturnType = createRule({
|
|
|
23
23
|
const { parent } = node;
|
|
24
24
|
if (
|
|
25
25
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
26
|
-
parent !== undefined
|
|
27
|
-
(parent.type === AST_NODE_TYPES.ExportNamedDeclaration
|
|
28
|
-
parent.type === AST_NODE_TYPES.ExportDefaultDeclaration)) {
|
|
26
|
+
parent !== undefined
|
|
27
|
+
&& (parent.type === AST_NODE_TYPES.ExportNamedDeclaration
|
|
28
|
+
|| parent.type === AST_NODE_TYPES.ExportDefaultDeclaration)) {
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
31
|
const { returnType } = node;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-readonly-parameter-types.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-readonly-parameter-types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAY1E,KAAK,OAAO,GAAG;IACb;QACE,KAAK,CAAC,EAAE,oBAAoB,EAAE,CAAC;QAC/B,wBAAwB,CAAC,EAAE,OAAO,CAAC;QACnC,mBAAmB,CAAC,EAAE,OAAO,CAAC;QAC9B,sBAAsB,CAAC,EAAE,OAAO,CAAC;QACjC,wBAAwB,CAAC,EAAE,OAAO,CAAC;KACpC;CACF,CAAC;AAGF,eAAO,MAAM,4BAA4B,
|
|
1
|
+
{"version":3,"file":"prefer-readonly-parameter-types.d.ts","sourceRoot":"","sources":["../../src/rules/prefer-readonly-parameter-types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAY1E,KAAK,OAAO,GAAG;IACb;QACE,KAAK,CAAC,EAAE,oBAAoB,EAAE,CAAC;QAC/B,wBAAwB,CAAC,EAAE,OAAO,CAAC;QACnC,mBAAmB,CAAC,EAAE,OAAO,CAAC;QAC9B,sBAAsB,CAAC,EAAE,OAAO,CAAC;QACjC,wBAAwB,CAAC,EAAE,OAAO,CAAC;KACpC;CACF,CAAC;AAGF,eAAO,MAAM,4BAA4B,6MA6MvC,CAAC"}
|
|
@@ -71,16 +71,28 @@ export const preferReadonlyParameterTypes = createRule({
|
|
|
71
71
|
AST_NODE_TYPES.TSFunctionType,
|
|
72
72
|
AST_NODE_TYPES.TSMethodSignature,
|
|
73
73
|
].join(", ")](node) {
|
|
74
|
+
// Early return in the special case of a map method. (This would result in an unfixable lint
|
|
75
|
+
// error.)
|
|
76
|
+
if (node.type === AST_NODE_TYPES.ArrowFunctionExpression
|
|
77
|
+
|| node.type === AST_NODE_TYPES.FunctionExpression) {
|
|
78
|
+
const { parent } = node;
|
|
79
|
+
if (parent.type === AST_NODE_TYPES.CallExpression
|
|
80
|
+
&& parent.callee.type === AST_NODE_TYPES.MemberExpression
|
|
81
|
+
&& parent.callee.property.type === AST_NODE_TYPES.Identifier
|
|
82
|
+
&& parent.callee.property.name === "map") {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
74
86
|
for (const param of node.params) {
|
|
75
|
-
if (checkParameterProperties === false
|
|
76
|
-
param.type === AST_NODE_TYPES.TSParameterProperty) {
|
|
87
|
+
if (checkParameterProperties === false
|
|
88
|
+
&& param.type === AST_NODE_TYPES.TSParameterProperty) {
|
|
77
89
|
continue;
|
|
78
90
|
}
|
|
79
91
|
const actualParam = param.type === AST_NODE_TYPES.TSParameterProperty
|
|
80
92
|
? param.parameter
|
|
81
93
|
: param;
|
|
82
|
-
if (ignoreInferredTypes === true
|
|
83
|
-
actualParam.typeAnnotation === undefined) {
|
|
94
|
+
if (ignoreInferredTypes === true
|
|
95
|
+
&& actualParam.typeAnnotation === undefined) {
|
|
84
96
|
continue;
|
|
85
97
|
}
|
|
86
98
|
const type = services.getTypeAtLocation(actualParam);
|
|
@@ -89,10 +101,10 @@ export const preferReadonlyParameterTypes = createRule({
|
|
|
89
101
|
const parts = unionTypeParts(type);
|
|
90
102
|
const hasAllBasicDataStructures = parts.every((t) => {
|
|
91
103
|
const typeName = getTypeName(t);
|
|
92
|
-
return (typeName === "Array"
|
|
93
|
-
typeName === "Map"
|
|
94
|
-
typeName === "Set"
|
|
95
|
-
typeName === "Record");
|
|
104
|
+
return (typeName === "Array"
|
|
105
|
+
|| typeName === "Map"
|
|
106
|
+
|| typeName === "Set"
|
|
107
|
+
|| typeName === "Record");
|
|
96
108
|
});
|
|
97
109
|
if (!hasAllBasicDataStructures) {
|
|
98
110
|
continue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-variadic-function-argument.d.ts","sourceRoot":"","sources":["../../src/rules/require-variadic-function-argument.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAIvE,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAAG,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"require-variadic-function-argument.d.ts","sourceRoot":"","sources":["../../src/rules/require-variadic-function-argument.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAIvE,MAAM,MAAM,OAAO,GAAG,EAAE,CAAC;AACzB,MAAM,MAAM,UAAU,GAAG,YAAY,CAAC;AAatC,eAAO,MAAM,+BAA+B,0HA8D1C,CAAC"}
|
|
@@ -2,6 +2,14 @@ import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
|
|
|
2
2
|
import ts from "typescript";
|
|
3
3
|
import { createRule } from "../utils.js";
|
|
4
4
|
const JSDOC_EXCEPTION_TAG = "allowEmptyVariadic";
|
|
5
|
+
const LOGGER_METHOD_NAMES = new Set([
|
|
6
|
+
"trace",
|
|
7
|
+
"debug",
|
|
8
|
+
"info",
|
|
9
|
+
"warn",
|
|
10
|
+
"error",
|
|
11
|
+
"fatal",
|
|
12
|
+
]);
|
|
5
13
|
export const requireVariadicFunctionArgument = createRule({
|
|
6
14
|
name: "require-variadic-function-argument",
|
|
7
15
|
meta: {
|
|
@@ -34,8 +42,8 @@ export const requireVariadicFunctionArgument = createRule({
|
|
|
34
42
|
if (declaration === undefined) {
|
|
35
43
|
return;
|
|
36
44
|
}
|
|
37
|
-
if (isHardCodedException(node)
|
|
38
|
-
hasJSDocExceptionTag(checker, declaration)) {
|
|
45
|
+
if (isHardCodedException(node)
|
|
46
|
+
|| hasJSDocExceptionTag(checker, declaration)) {
|
|
39
47
|
return;
|
|
40
48
|
}
|
|
41
49
|
for (let i = 0; i < declaration.parameters.length; i++) {
|
|
@@ -43,8 +51,8 @@ export const requireVariadicFunctionArgument = createRule({
|
|
|
43
51
|
if (parameter === undefined) {
|
|
44
52
|
continue;
|
|
45
53
|
}
|
|
46
|
-
if (ts.isRestParameter(parameter)
|
|
47
|
-
node.arguments[i] === undefined) {
|
|
54
|
+
if (ts.isRestParameter(parameter)
|
|
55
|
+
&& node.arguments[i] === undefined) {
|
|
48
56
|
context.report({
|
|
49
57
|
loc: node.loc,
|
|
50
58
|
messageId: "noArgument",
|
|
@@ -57,7 +65,20 @@ export const requireVariadicFunctionArgument = createRule({
|
|
|
57
65
|
});
|
|
58
66
|
function isHardCodedException(node) {
|
|
59
67
|
const { callee } = node;
|
|
60
|
-
|
|
68
|
+
const methodName = getMethodName(callee) ?? "unknown";
|
|
69
|
+
return (isConsoleOrWindowOrLoggerFunction(callee)
|
|
70
|
+
|| isTimeoutFunction(callee)
|
|
71
|
+
|| LOGGER_METHOD_NAMES.has(methodName));
|
|
72
|
+
}
|
|
73
|
+
function getMethodName(node) {
|
|
74
|
+
if (node.type !== AST_NODE_TYPES.MemberExpression) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
const { property } = node;
|
|
78
|
+
if (property.type !== AST_NODE_TYPES.Identifier) {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
return property.name;
|
|
61
82
|
}
|
|
62
83
|
/**
|
|
63
84
|
* This rule has a false positive with any logger function. (Both `console.log` and logger functions
|
|
@@ -73,9 +94,9 @@ function isConsoleOrWindowOrLoggerFunction(callee) {
|
|
|
73
94
|
if (object.type !== AST_NODE_TYPES.Identifier) {
|
|
74
95
|
return false;
|
|
75
96
|
}
|
|
76
|
-
return (object.name === "console"
|
|
77
|
-
object.name === "window"
|
|
78
|
-
object.name === "logger");
|
|
97
|
+
return (object.name === "console"
|
|
98
|
+
|| object.name === "window"
|
|
99
|
+
|| object.name === "logger");
|
|
79
100
|
}
|
|
80
101
|
function isTimeoutFunction(callee) {
|
|
81
102
|
if (callee.type !== AST_NODE_TYPES.Identifier) {
|
|
@@ -60,9 +60,9 @@ export const strictArrayMethods = createRule({
|
|
|
60
60
|
for (const callSignature of callSignatures) {
|
|
61
61
|
const returnType = callSignature.getReturnType();
|
|
62
62
|
const returnTypeName = getTypeName(returnType);
|
|
63
|
-
if (returnTypeName !== "boolean"
|
|
64
|
-
returnTypeName !== "true"
|
|
65
|
-
returnTypeName !== "false") {
|
|
63
|
+
if (returnTypeName !== "boolean"
|
|
64
|
+
&& returnTypeName !== "true"
|
|
65
|
+
&& returnTypeName !== "false") {
|
|
66
66
|
return false;
|
|
67
67
|
}
|
|
68
68
|
}
|
|
@@ -70,8 +70,8 @@ export const strictArrayMethods = createRule({
|
|
|
70
70
|
}
|
|
71
71
|
return {
|
|
72
72
|
CallExpression(node) {
|
|
73
|
-
if (isArrayMethodInvocationWithBooleanFunction(node)
|
|
74
|
-
!firstArgumentHasBooleanReturnType(node)) {
|
|
73
|
+
if (isArrayMethodInvocationWithBooleanFunction(node)
|
|
74
|
+
&& !firstArgumentHasBooleanReturnType(node)) {
|
|
75
75
|
context.report({
|
|
76
76
|
loc: node.loc,
|
|
77
77
|
messageId: "conditionError",
|
|
@@ -3,10 +3,10 @@ import { ESLintUtils } from "@typescript-eslint/utils";
|
|
|
3
3
|
import ts from "typescript";
|
|
4
4
|
import { isSymbolFlagSet, isTypeFlagSet, unionTypeParts, } from "../typeUtils.js";
|
|
5
5
|
import { createRule } from "../utils.js";
|
|
6
|
-
const ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT = ts.TypeFlags.Any
|
|
7
|
-
ts.TypeFlags.Unknown
|
|
8
|
-
ts.TypeFlags.Number
|
|
9
|
-
ts.TypeFlags.String;
|
|
6
|
+
const ALLOWED_TYPES_FOR_ANY_ENUM_ARGUMENT = ts.TypeFlags.Any
|
|
7
|
+
| ts.TypeFlags.Unknown
|
|
8
|
+
| ts.TypeFlags.Number
|
|
9
|
+
| ts.TypeFlags.String;
|
|
10
10
|
export const strictEnums = createRule({
|
|
11
11
|
name: "strict-enums",
|
|
12
12
|
meta: {
|
|
@@ -187,8 +187,8 @@ export const strictEnums = createRule({
|
|
|
187
187
|
for (let i = 0; i < leftTypeArguments.length; i++) {
|
|
188
188
|
const leftTypeArgument = leftTypeArguments[i];
|
|
189
189
|
const rightTypeArgument = rightTypeArguments[i];
|
|
190
|
-
if (leftTypeArgument === undefined
|
|
191
|
-
rightTypeArgument === undefined) {
|
|
190
|
+
if (leftTypeArgument === undefined
|
|
191
|
+
|| rightTypeArgument === undefined) {
|
|
192
192
|
continue;
|
|
193
193
|
}
|
|
194
194
|
if (isAssigningNonEnumValueToEnumVariable(leftTypeArgument, rightTypeArgument)) {
|
|
@@ -235,8 +235,8 @@ export const strictEnums = createRule({
|
|
|
235
235
|
for (let i = 0; i < argumentTypeArguments.length; i++) {
|
|
236
236
|
const argumentTypeArgument = argumentTypeArguments[i];
|
|
237
237
|
const parameterTypeArgument = parameterTypeArguments[i];
|
|
238
|
-
if (argumentTypeArgument === undefined
|
|
239
|
-
parameterTypeArgument === undefined) {
|
|
238
|
+
if (argumentTypeArgument === undefined
|
|
239
|
+
|| parameterTypeArgument === undefined) {
|
|
240
240
|
continue;
|
|
241
241
|
}
|
|
242
242
|
if (isMismatchedEnumFunctionArgument(argumentTypeArgument, parameterTypeArgument)) {
|
|
@@ -286,10 +286,10 @@ export const strictEnums = createRule({
|
|
|
286
286
|
*/
|
|
287
287
|
const argumentSubTypes = unionTypeParts(argumentType);
|
|
288
288
|
for (const argumentSubType of argumentSubTypes) {
|
|
289
|
-
if (argumentSubType.isLiteral()
|
|
290
|
-
!isEnum(argumentSubType)
|
|
289
|
+
if (argumentSubType.isLiteral()
|
|
290
|
+
&& !isEnum(argumentSubType)
|
|
291
291
|
// Allow passing number literals if there are number literals in the actual function type.
|
|
292
|
-
!parameterSubTypes.includes(argumentSubType)) {
|
|
292
|
+
&& !parameterSubTypes.includes(argumentSubType)) {
|
|
293
293
|
return true;
|
|
294
294
|
}
|
|
295
295
|
}
|
|
@@ -429,11 +429,11 @@ function isEnum(type) {
|
|
|
429
429
|
return isTypeFlagSet(type, ts.TypeFlags.EnumLiteral);
|
|
430
430
|
}
|
|
431
431
|
function isNullOrUndefinedOrAnyOrUnknownOrNever(...types) {
|
|
432
|
-
return types.some((type) => isTypeFlagSet(type, ts.TypeFlags.Null
|
|
433
|
-
ts.TypeFlags.Undefined
|
|
434
|
-
ts.TypeFlags.Any
|
|
435
|
-
ts.TypeFlags.Unknown
|
|
436
|
-
ts.TypeFlags.Never));
|
|
432
|
+
return types.some((type) => isTypeFlagSet(type, ts.TypeFlags.Null
|
|
433
|
+
| ts.TypeFlags.Undefined
|
|
434
|
+
| ts.TypeFlags.Any
|
|
435
|
+
| ts.TypeFlags.Unknown
|
|
436
|
+
| ts.TypeFlags.Never));
|
|
437
437
|
}
|
|
438
438
|
function setHasAnyElementFromSet(set1, set2) {
|
|
439
439
|
for (const value of set2) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-complete",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"description": "An ESLint plugin that contains useful rules.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
"test": "jest"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@typescript-eslint/type-utils": "8.
|
|
48
|
-
"@typescript-eslint/utils": "8.
|
|
49
|
-
"typescript-eslint": "8.
|
|
47
|
+
"@typescript-eslint/type-utils": "8.25.0",
|
|
48
|
+
"@typescript-eslint/utils": "8.25.0",
|
|
49
|
+
"typescript-eslint": "8.25.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@babel/core": "7.26.9",
|
|
@@ -54,10 +54,10 @@
|
|
|
54
54
|
"@babel/preset-typescript": "7.26.0",
|
|
55
55
|
"@types/jest": "29.5.14",
|
|
56
56
|
"@types/node": "22.13.5",
|
|
57
|
-
"@typescript-eslint/rule-tester": "8.
|
|
58
|
-
"@typescript-eslint/types": "8.
|
|
59
|
-
"complete-common": "
|
|
60
|
-
"complete-node": "
|
|
57
|
+
"@typescript-eslint/rule-tester": "8.25.0",
|
|
58
|
+
"@typescript-eslint/types": "8.25.0",
|
|
59
|
+
"complete-common": "1.3.0",
|
|
60
|
+
"complete-node": "3.1.8",
|
|
61
61
|
"jest": "29.7.0",
|
|
62
62
|
"prettier": "3.5.2",
|
|
63
63
|
"typescript": "5.7.3"
|