8000 Merge branch 'main' into no-unreachable-loop · abrahamguo/typescript-eslint@8bf8fd3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8bf8fd3

Browse files
authored
Merge branch 'main' into no-unreachable-loop
2 parents 74bae9e + 58be99f commit 8bf8fd3

File tree

27 files changed

+980
-219
lines changed

27 files changed

+980
-219
lines changed

eslint.config.mjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ export default tseslint.config(
135135
{ allowConstantLoopConditions: true },
136136
],
137137
'@typescript-eslint/no-unnecessary-type-parameters': 'error',
138+
'@typescript-eslint/no-unused-expressions': 'error',
138139
'@typescript-eslint/no-var-requires': 'off',
139140
'@typescript-eslint/prefer-literal-enum-member': [
140141
'error',
@@ -206,12 +207,17 @@ export default tseslint.config(
206207
'error',
207208
{ commentPattern: '.*intentional fallthrough.*' },
208209
],
210+
'no-lonely-if': 'error',
209211
'no-unreachable-loop': 'error',
210212
'no-useless-call': 'error',
211213
'no-useless-computed-key': 'error',
214+
'no-useless-concat': 'error',
212215
'no-void': ['error', { allowAsStatement: true }],
213216
'one-var': ['error', 'never'],
217+
'operator-assignment': 'error',
214218
'prefer-arrow-callback': 'error',
219+
'prefer-const': 'error',
220+
'prefer-object-spread': 'error',
215221
'prefer-rest-params': 'error',
216222

217223
//

packages/eslint-plugin/docs/rules/strict-boolean-expressions.mdx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ The following nodes are considered boolean expressions and their type is checked
2121
- Operands of logical binary operators (`lhs || rhs` and `lhs && rhs`).
2222
- Right-hand side operand is ignored when it's not a descendant of another boolean expression.
2323
This is to allow usage of boolean operators for their short-circuiting behavior.
24+
- Asserted argument of an assertion function (`assert(arg)`).
2425

2526
## Examples
2627

@@ -55,6 +56,11 @@ let obj = {};
5556
while (obj) {
5657
obj = getObj();
5758
}
59+
60+
// assertion functions without an `is` are boolean contexts.
61+
declare function assert(value: unknown): asserts value;
62+
let maybeString = Math.random() > 0.5 ? '' : undefined;
63+
assert(maybeString);
5864
```
5965

6066
</TabItem>

packages/eslint-plugin/src/rules/ban-types.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,10 @@ export default createRule<Options, MessageIds>({
207207
create(context, [options]) {
208208
const extendDefaults = options.extendDefaults ?? true;
209209
const customTypes = options.types ?? {};
210-
const types = Object.assign(
211-
{},
212-
extendDefaults ? defaultTypes : {},
213-
customTypes,
214-
);
210+
const types = {
211+
...(extendDefaults && defaultTypes),
212+
...customTypes,
213+
};
215214
const bannedTypes = new Map(
216215
Object.entries(types).map(([type, data]) => [removeSpaces(type), data]),
217216
);

packages/eslint-plugin/src/rules/consistent-type-imports.ts

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -177,25 +177,23 @@ export default createRule<Options, MessageIds>({
177177
// definitely import type { TypeX }
178178
sourceImports.typeOnlyNamedImport = node;
179179
}
180-
} else {
181-
if (
182-
!sourceImports.valueOnlyNamedImport &&
183-
node.specifiers.length &&
184-
node.specifiers.every(
185-
specifier => specifier.type === AST_NODE_TYPES.ImportSpecifier,
186-
)
187-
) {
188-
sourceImports.valueOnlyNamedImport = node;
189-
sourceImports.valueImport = node;
190-
} else if (
191-
!sourceImports.valueImport &&
192-
node.specifiers.some(
193-
specifier =>
194- F438
specifier.type === AST_NODE_TYPES.ImportDefaultSpecifier,
195-
)
196-
) {
197-
sourceImports.valueImport = node;
198-
}
180+
} else if (
181+
!sourceImports.valueOnlyNamedImport &&
182+
node.specifiers.length &&
183+
node.specifiers.every(
184+
specifier => specifier.type === AST_NODE_TYPES.ImportSpecifier,
185+
)
186+
) {
187+
sourceImports.valueOnlyNamedImport = node;
188+
sourceImports.valueImport = node;
189+
} else if (
190+
!sourceImports.valueImport &&
191+
node.specifiers.some(
192+
specifier =>
193+
specifier.type === AST_NODE_TYPES.ImportDefaultSpecifier,
194+
)
195+
) {
196+
sourceImports.valueImport = node;
199197
}
200198

201199
const typeSpecifiers: TSESTree.ImportClause[] = [];
@@ -732,6 +730,7 @@ export default createRule<Options, MessageIds>({
732730
}
733731
} else {
734732
// The import is both default and named. Insert named on new line because can't mix default type import and named type imports
733+
// eslint-disable-next-line no-lonely-if
735734
if (fixStyle === 'inline-type-imports') {
736735
yield fixer.insertTextBefore(
737736
node,

packages/eslint-plugin/src/rules/func-call-spacing.ts

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -151,29 +151,27 @@ export default createRule<Options, MessageIds>({
151151
messageId: 'unexpectedWhitespace',
152152
});
153153
}
154-
} else {
155-
if (!hasWhitespace) {
156-
context.report({
157-
node,
158-
loc: lastCalleeToken.loc.start,
159-
messageId: 'missing',
160-
fix(fixer) {
161-
return fixer.insertTextBefore(openingParenToken, ' ');
162-
},
163-
});
164-
} else if (!config!.allowNewlines && hasNewline) {
165-
context.report({
166-
node,
167-
loc: lastCalleeToken.loc.start,
168-
messageId: 'unexpectedNewline',
169-
fix(fixer) {
170-
return fixer.replaceTextRange(
171-
[lastCalleeToken.range[1], openingParenToken.range[0]],
172-
' ',
173-
);
174-
},
175-
});
176-
}
154+
} else if (!hasWhitespace) {
155+
context.report({
156+
node,
157+
loc: lastCalleeToken.loc.start,
158+
messageId: 'missing',
159+
fix(fixer) {
160+
return fixer.insertTextBefore(openingParenToken, ' ');
161+
},
162+
});
163+
} else if (!config!.allowNewlines && hasNewline) {
164+
context.report({
165+
node,
166+
loc: lastCalleeToken.loc.start,
167+
messageId: 'unexpectedNewline',
168+
fix(fixer) {
169+
return fixer.replaceTextRange(
170+
[lastCalleeToken.range[1], openingParenToken.range[0]],
171+
' ',
172+
);
173+
},
174+
});
177175
}
178176
}
179177

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

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -181,16 +181,17 @@ export default createRule<Options, MessageIds>({
181181
} as TSESTree.PropertyDefinition;
182182
}
183183

184-
return Object.assign({}, rules, {
184+
return {
185+
...rules,
185186
// overwrite the base rule here so we can use our KNOWN_NODES list instead
186-
'*:exit'(node: TSESTree.Node) {
187+
'*:exit'(node: TSESTree.Node): void {
187188
// For nodes we care about, skip the default handling, because it just marks the node as ignored...
188189
if (!KNOWN_NODES.has(node.type)) {
189190
rules['*:exit'](node);
190191
}
191192
},
192193

193-
VariableDeclaration(node: TSESTree.VariableDeclaration) {
194+
VariableDeclaration(node: TSESTree.VariableDeclaration): void {
194195
// https://github.com/typescript-eslint/typescript-eslint/issues/441
195196
if (node.declarations.length === 0) {
196197
return;
@@ -199,7 +200,7 @@ export default createRule<Options, MessageIds>({
199200
return rules.VariableDeclaration(node);
200201
},
201202

202-
TSAsExpression(node: TSESTree.TSAsExpression) {
203+
TSAsExpression(node: TSESTree.TSAsExpression): void {
203204
// transform it to a BinaryExpression
204205
return rules['BinaryExpression, LogicalExpression']({
205206
type: AST_NODE_TYPES.BinaryExpression,
@@ -215,7 +216,7 @@ export default createRule<Options, MessageIds>({
215216
});
216217
},
217218

218-
TSConditionalType(node: TSESTree.TSConditionalType) {
219+
TSConditionalType(node: TSESTree.TSConditionalType): void {
219220
// transform it to a ConditionalExpression
220221
return rules.ConditionalExpression({
221222
type: AST_NODE_TYPES.ConditionalExpression,
@@ -245,7 +246,7 @@ export default createRule<Options, MessageIds>({
245246

246247
'TSEnumDeclaration, TSTypeLiteral'(
247248
node: TSESTree.TSEnumDeclaration | TSESTree.TSTypeLiteral,
248-
) {
249+
): void {
249250
// transform it to an ObjectExpression
250251
return rules['ObjectExpression, ObjectPattern']({
251252
type: AST_NODE_TYPES.ObjectExpression,
@@ -263,7 +264,9 @@ export default createRule<Options, MessageIds>({
263264
});
264265
},
265266

266-
TSImportEqualsDeclaration(node: TSESTree.TSImportEqualsDeclaration) {
267+
TSImportEqualsDeclaration(
268+
node: TSESTree.TSImportEqualsDeclaration,
269+
): void {
267270
// transform it to an VariableDeclaration
268271
// use VariableDeclaration instead of ImportDeclaration because it's essentially the same thing
269272
const { id, moduleReference } = node;
@@ -317,7 +320,7 @@ export default createRule<Options, MessageIds>({
317320
});
318321
},
319322

320-
TSIndexedAccessType(node: TSESTree.TSIndexedAccessType) {
323+
TSIndexedAccessType(node: TSESTree.TSIndexedAccessType): void {
321324
// convert to a MemberExpression
322325
return rules['MemberExpression, JSXMemberExpression, MetaProperty']({
323326
type: AST_NODE_TYPES.MemberExpression,
@@ -333,7 +336,7 @@ export default createRule<Options, MessageIds>({
333336
});
334337
},
335338

336-
TSInterfaceBody(node: TSESTree.TSInterfaceBody) {
339+
TSInterfaceBody(node: TSESTree.TSInterfaceBody): void {
337340
// transform it to an ClassBody
338341
return rules['BlockStatement, ClassBody']({
339342
type: AST_NODE_TYPES.ClassBody,
@@ -354,7 +357,7 @@ export default createRule<Options, MessageIds>({
354357

355358
'TSInterfaceDeclaration[extends.length > 0]'(
356359
node: TSESTree.TSInterfaceDeclaration,
357-
) {
360+
): void {
358361
// transform it to a ClassDeclaration
359362
return rules[
360363
'ClassDeclaration[superClass], ClassExpression[superClass]'
@@ -379,7 +382,7 @@ export default createRule<Options, MessageIds>({
379382
});
380383
},
381384

382-
TSMappedType(node: TSESTree.TSMappedType) {
385+
TSMappedType(node: TSESTree.TSMappedType): void {
383386
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
384387
const squareBracketStart = context.sourceCode.getTokenBefore(
385388
node.typeParameter,
@@ -423,7 +426,7 @@ export default createRule<Options, MessageIds>({
423426
});
424427
},
425428

426-
TSModuleBlock(node: TSESTree.TSModuleBlock) {
429+
TSModuleBlock(node: TSESTree.TSModuleBlock): void {
427430
// transform it to a BlockStatement
428431
return rules['BlockStatement, ClassBody']({
429432
type: AST_NODE_TYPES.BlockStatement,
@@ -436,7 +439,7 @@ export default createRule<Options, MessageIds>({
436439
});
437440
},
438441

439-
TSQualifiedName(node: TSESTree.TSQualifiedName) {
442+
TSQualifiedName(node: TSESTree.TSQualifiedName): void {
440443
return rules['MemberExpression, JSXMemberExpression, MetaProperty']({
441444
type: AST_NODE_TYPES.MemberExpression,
442445
object: node.left as any,
@@ -451,7 +454,7 @@ export default createRule<Options, MessageIds>({
451454
});
452455
},
453456

454-
TSTupleType(node: TSESTree.TSTupleType) {
457+
TSTupleType(node: TSESTree.TSTupleType): void {
455458
// transform it to an ArrayExpression
456459
return rules['ArrayExpression, ArrayPattern']({
457460
type: AST_NODE_TYPES.ArrayExpression,
@@ -464,7 +467,9 @@ export default createRule<Options, MessageIds>({
464467
});
465468
},
466469

467-
TSTypeParameterDeclaration(node: TSESTree.TSTypeParameterDeclaration) {
470+
TSTypeParameterDeclaration(
471+
node: TSESTree.TSTypeParameterDeclaration,
472+
): void {
468473
if (!node.params.length) {
469474
return;
470475
}
@@ -487,6 +492,6 @@ export default createRule<Options, MessageIds>({
487492
loc: node.loc,
488493
});
489494
},
490-
});
495+
};
491496
},
492497
});

packages/eslint-plugin/src/rules/member-delimiter-style.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,12 @@ export default createRule<Options, MessageIds>({
272272
missingDelimiter = true;
273273
messageId = 'unexpectedComma';
274274
}
275-
} else {
276-
if (optsSemi) {
277-
missingDelimiter = true;
278-
messageId = 'expectedSemi';
279-
} else if (optsComma) {
280-
missingDelimiter = true;
281-
messageId = 'expectedComma';
282-
}
275+
} else if (optsSemi) {
276+
missingDelimiter = true;
277+
messageId = 'expectedSemi';
278+
} else if (optsComma) {
279+
missingDelimiter = true;
280+
messageId = 'expectedComma';
283281
}
284282

285283
if (messageId) {

packages/eslint-plugin/src/rules/no-extra-parens.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,6 @@ export default createRule<Options, MessageIds>({
303303
}
304304
},
305305
};
306-
return Object.assign({}, rules, overrides);
306+
return { ...rules, ...overrides };
307307
},
308308
});

packages/eslint-plugin/src/rules/no-non-null-assertion.ts

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,18 @@ export default createRule<[], MessageIds>({
7979
},
8080
});
8181
}
82+
} else if (node.parent.computed) {
83+
// it is x!?.[y].z
84+
suggest.push({
85+
messageId: 'suggestOptionalChain',
86+
fix: removeToken(),
87+
});
8288
} else {
83-
if (node.parent.computed) {
84-
// it is x!?.[y].z
85-
suggest.push({
86-
messageId: 'suggestOptionalChain',
87-
fix: removeToken(),
88-
});
89-
} else {
90-
// it is x!?.y.z
91-
suggest.push({
92-
messageId: 'suggestOptionalChain',
93-
fix: removeToken(),
94-
});
95-
}
89+
// it is x!?.y.z
90+
suggest.push({
91+
messageId: 'suggestOptionalChain',
92+
fix: removeToken(),
93+
});
9694
}
9795
} else if (
9896
node.parent.type === AST_NODE_TYPES.CallExpression &&

packages/eslint-plugin/src/rules/no-unused-vars.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -267,14 +267,13 @@ export default createRule<Options, MessageIds>({
267267
) {
268268
continue;
269269
}
270-
} else {
271-
// skip ignored variables
272-
if (
273-
def.name.type === AST_NODE_TYPES.Identifier &&
274-
options.varsIgnorePattern?.test(def.name.name)
275-
) {
276-
continue;
277-
}
270+
}
271+
// skip ignored variables
272+
else if (
273+
def.name.type === AST_NODE_TYPES.Identifier &&
274+
options.varsIgnorePattern?.test(def.name.name)
275+
) {
276+
continue;
278277
}
279278

280279
if (hasRestSpreadSibling(variable)) {

0 commit comments

Comments
 (0)
0