Skip to content

Commit 7ef4cf7

Browse files
authored
fix: remove unnecessary semicolon from fixes (#19857)
1 parent 7dabc38 commit 7ef4cf7

File tree

3 files changed

+138
-0
lines changed

3 files changed

+138
-0
lines changed

lib/rules/utils/ast-utils.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,35 @@ let needsPrecedingSemicolon;
11931193
"WithStatement",
11941194
]);
11951195

1196+
const TS_TYPE_NODE_TYPES = new Set([
1197+
"TSAsExpression",
1198+
"TSSatisfiesExpression",
1199+
"TSTypeAliasDeclaration",
1200+
"TSTypeAnnotation",
1201+
]);
1202+
1203+
/**
1204+
* Determines whether a specified node is inside a TypeScript type context.
1205+
* @param {ASTNode} node The node to check.
1206+
* @returns {boolean} Whether the node is inside a TypeScript type context.
1207+
*/
1208+
function isInType(node) {
1209+
for (let currNode = node; ; ) {
1210+
const { parent } = currNode;
1211+
if (!parent) {
1212+
break;
1213+
}
1214+
if (
1215+
TS_TYPE_NODE_TYPES.has(parent.type) &&
1216+
currNode === parent.typeAnnotation
1217+
) {
1218+
return true;
1219+
}
1220+
currNode = parent;
1221+
}
1222+
return false;
1223+
}
1224+
11961225
needsPrecedingSemicolon = function (sourceCode, node) {
11971226
const prevToken = sourceCode.getTokenBefore(node);
11981227

@@ -1206,6 +1235,16 @@ let needsPrecedingSemicolon;
12061235

12071236
const prevNode = sourceCode.getNodeByRangeIndex(prevToken.range[0]);
12081237

1238+
if (
1239+
prevNode.type === "TSDeclareFunction" ||
1240+
prevNode.parent.type === "TSImportEqualsDeclaration" ||
1241+
prevNode.parent.parent?.type === "TSImportEqualsDeclaration" ||
1242+
TS_TYPE_NODE_TYPES.has(prevNode.type) ||
1243+
isInType(prevNode)
1244+
) {
1245+
return false;
1246+
}
1247+
12091248
if (isClosingParenToken(prevToken)) {
12101249
return !STATEMENTS.has(prevNode.type);
12111250
}
@@ -1222,6 +1261,12 @@ let needsPrecedingSemicolon;
12221261
}
12231262

12241263
if (IDENTIFIER_OR_KEYWORD.has(prevToken.type)) {
1264+
if (
1265+
prevNode.parent.type === "VariableDeclarator" &&
1266+
!prevNode.parent.init
1267+
) {
1268+
return false;
1269+
}
12251270
if (BREAK_OR_CONTINUE.has(prevNode.parent.type)) {
12261271
return false;
12271272
}

tests/lib/rules/no-array-constructor.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,18 @@ ruleTester.run("no-array-constructor", rule, {
491491
break yield
492492
new Array();
493493
}
494+
`,
495+
},
496+
{
497+
code: `
498+
var foo
499+
Array()
500+
`,
501+
},
502+
{
503+
code: `
504+
let bar
505+
Array()
494506
`,
495507
},
496508
].map(props => ({
@@ -972,5 +984,74 @@ ruleTesterTypeScript.run("no-array-constructor", rule, {
972984
},
973985
],
974986
},
987+
988+
// No semicolon required after TypeScript syntax
989+
...[
990+
"type T = Foo",
991+
"type T = Foo<Bar>",
992+
"type T = (A | B)",
993+
"type T = -1",
994+
"type T = 'foo'",
995+
"const foo",
996+
"declare const foo",
997+
"function foo()",
998+
"declare function foo()",
999+
"function foo(): []",
1000+
"declare function foo(): []",
1001+
"function foo(): (Foo)",
1002+
"declare function foo(): (Foo)",
1003+
"let foo: bar",
1004+
"import Foo = require('foo')",
1005+
"import Foo = Bar",
1006+
"import Foo = Bar.Baz.Qux",
1007+
].map(code => ({
1008+
code: `${code}\nArray(0, 1)`,
1009+
output: `${code}\n[0, 1]`,
1010+
errors: [{ messageId: "preferLiteral" }],
1011+
})),
1012+
{
1013+
code: `
1014+
(function () {
1015+
Fn
1016+
Array() // ";" required
1017+
}) as Fn
1018+
Array() // ";" not required
1019+
`,
1020+
output: `
1021+
(function () {
1022+
Fn
1023+
;[] // ";" required
1024+
}) as Fn
1025+
[] // ";" not required
1026+
`,
1027+
errors: [
1028+
{ messageId: "preferLiteral" },
1029+
{ messageId: "preferLiteral" },
1030+
],
1031+
},
1032+
{
1033+
code: `
1034+
({
1035+
foo() {
1036+
Object
1037+
Array() // ";" required
1038+
}
1039+
}) as Object
1040+
Array() // ";" not required
1041+
`,
1042+
output: `
1043+
({
1044+
foo() {
1045+
Object
1046+
;[] // ";" required
1047+
}
1048+
}) as Object
1049+
[] // ";" not required
1050+
`,
1051+
errors: [
1052+
{ messageId: "preferLiteral" },
1053+
{ messageId: "preferLiteral" },
1054+
],
1055+
},
9751056
],
9761057
});

tests/lib/rules/no-object-constructor.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,18 @@ ruleTester.run("no-object-constructor", rule, {
377377
break yield
378378
new Object();
379379
}
380+
`,
381+
},
382+
{
383+
code: `
384+
var foo
385+
Object()
386+
`,
387+
},
388+
{
389+
code: `
390+
let bar
391+
Object()
380392
`,
381393
},
382394
].map(props => ({

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy