@sarj/eslint-plugin 16.32.0 → 16.32.3
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/{_docs-DU-K223M.d.cts → _docs-Bq5OCcWF.d.cts} +4 -4
- package/dist/{_docs-DU-K223M.d.ts → _docs-Bq5OCcWF.d.ts} +4 -4
- package/dist/index.cjs +975 -416
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +975 -416
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,61 @@
|
|
|
1
1
|
// src/rules/no-redundant-consumer-union.ts
|
|
2
2
|
import { AST_NODE_TYPES as AST_NODE_TYPES6, ESLintUtils as ESLintUtils2 } from "@typescript-eslint/utils";
|
|
3
|
-
import
|
|
3
|
+
import ts7 from "typescript";
|
|
4
4
|
|
|
5
|
-
// src/rules/
|
|
5
|
+
// src/rules/_checked-native-source.ts
|
|
6
6
|
import ts from "typescript";
|
|
7
|
+
var CHECKED = /* @__PURE__ */ new WeakMap();
|
|
8
|
+
var SINGLE_LINE_DIRECTIVE = /^\/\/\/?\s*@(?:ts-expect-error|ts-ignore)/u;
|
|
9
|
+
var MULTI_LINE_DIRECTIVE = /^[/*]*\s*@(?:ts-expect-error|ts-ignore)/u;
|
|
10
|
+
var SINGLE_LINE_PRAGMA = /^\/\/\/?\s*@([^\s:]+)(?:(?:[^\S\r\n]|:).*)?$/mu;
|
|
11
|
+
function currentNativeSource(sourceCode, services) {
|
|
12
|
+
const source = services.esTreeNodeToTSNodeMap.get(sourceCode.ast);
|
|
13
|
+
return ts.isSourceFile(source) && services.program.getSourceFile(source.fileName) === source && source.text === sourceCode.text ? source : null;
|
|
14
|
+
}
|
|
15
|
+
function checkedNativeSource(program, source) {
|
|
16
|
+
let files = CHECKED.get(program);
|
|
17
|
+
if (!files) {
|
|
18
|
+
files = /* @__PURE__ */ new WeakMap();
|
|
19
|
+
CHECKED.set(program, files);
|
|
20
|
+
}
|
|
21
|
+
const known2 = files.get(source);
|
|
22
|
+
if (known2 !== void 0) return known2;
|
|
23
|
+
const available = !program.getCompilerOptions().noCheck && !source.isDeclarationFile && (source.flags & (ts.NodeFlags.JavaScriptFile | ts.NodeFlags.JsonFile)) === 0 && !program.getProjectReferences()?.length && !program.getResolvedProjectReferences()?.length && program.getSourceFile(source.fileName) === source && !program.isSourceFileFromExternalLibrary(source) && !program.isSourceFileDefaultLibrary(source) && !program.getSyntacticDiagnostics(source).some((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error && diagnostic.file === source) && !checkingSuppressed(source) && !program.getSemanticDiagnostics(source).some((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error && diagnostic.file === source);
|
|
24
|
+
files.set(source, available);
|
|
25
|
+
return available;
|
|
26
|
+
}
|
|
27
|
+
function checkingSuppressed(source) {
|
|
28
|
+
if (!/@ts-/iu.test(source.text)) return false;
|
|
29
|
+
if (ts.getLeadingCommentRanges(source.text, 0)?.some((comment) => comment.kind === ts.SyntaxKind.SingleLineCommentTrivia && SINGLE_LINE_PRAGMA.exec(source.text.slice(comment.pos, comment.end))?.[1]?.toLowerCase() === "ts-nocheck")) return true;
|
|
30
|
+
const pending = [source];
|
|
31
|
+
while (pending.length) {
|
|
32
|
+
const node = pending.pop();
|
|
33
|
+
if (!node || ts.isJsxText(node) || ts.isJSDoc(node) || (node.flags & ts.NodeFlags.JSDoc) !== 0) continue;
|
|
34
|
+
if (!ts.isToken(node)) {
|
|
35
|
+
for (const child of node.getChildren(source)) pending.push(child);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (tokenTriviaSuppressesChecking(node, source)) return true;
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
function tokenTriviaSuppressesChecking(node, source) {
|
|
43
|
+
const start = node.getStart(source);
|
|
44
|
+
for (const comment of [...ts.getLeadingCommentRanges(source.text, node.pos) ?? [], ...ts.getTrailingCommentRanges(source.text, node.pos) ?? []]) {
|
|
45
|
+
if (comment.pos < node.pos || comment.end > start) continue;
|
|
46
|
+
if (commentSuppressesChecking(source.text.slice(comment.pos, comment.end), comment.kind)) return true;
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
function commentSuppressesChecking(text, kind) {
|
|
51
|
+
if (kind === ts.SyntaxKind.SingleLineCommentTrivia) return SINGLE_LINE_DIRECTIVE.test(text);
|
|
52
|
+
let lastLine = text.length;
|
|
53
|
+
while (lastLine > 0 && !ts.isLineBreak(text.charCodeAt(lastLine - 1))) lastLine--;
|
|
54
|
+
return MULTI_LINE_DIRECTIVE.test(text.slice(lastLine).trimStart());
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/rules/_closed-object-contract.ts
|
|
58
|
+
import ts2 from "typescript";
|
|
7
59
|
function closedObjectContract(type, checker) {
|
|
8
60
|
return visitContract(type, { checker, active: /* @__PURE__ */ new Set(), completed: /* @__PURE__ */ new WeakMap() });
|
|
9
61
|
}
|
|
@@ -19,32 +71,32 @@ function visitContract(type, proof) {
|
|
|
19
71
|
}
|
|
20
72
|
function completeObject(type, proof) {
|
|
21
73
|
if (!ordinaryObject(type, proof.checker)) return false;
|
|
22
|
-
const declarations = type.getSymbol()?.getDeclarations()?.filter((declaration) =>
|
|
74
|
+
const declarations = type.getSymbol()?.getDeclarations()?.filter((declaration) => ts2.isInterfaceDeclaration(declaration) || ts2.isTypeLiteralNode(declaration));
|
|
23
75
|
if (!declarations?.length) return false;
|
|
24
76
|
return declarations.every((declaration) => completeDeclaration(declaration, proof));
|
|
25
77
|
}
|
|
26
78
|
function ordinaryObject(type, checker) {
|
|
27
|
-
if ((type.flags &
|
|
79
|
+
if ((type.flags & ts2.TypeFlags.Object) === 0 || type.isUnion() || checker.getIndexInfosOfType(type).length > 0) return false;
|
|
28
80
|
const object = type;
|
|
29
|
-
if ((object.objectFlags & (
|
|
30
|
-
if ((object.objectFlags &
|
|
31
|
-
return checker.getSignaturesOfType(type,
|
|
81
|
+
if ((object.objectFlags & (ts2.ObjectFlags.Class | ts2.ObjectFlags.Mapped)) !== 0) return false;
|
|
82
|
+
if ((object.objectFlags & ts2.ObjectFlags.Reference) !== 0 && checker.getTypeArguments(type).some((argument) => (argument.flags & (ts2.TypeFlags.Any | ts2.TypeFlags.Unknown | ts2.TypeFlags.TypeParameter)) !== 0)) return false;
|
|
83
|
+
return checker.getSignaturesOfType(type, ts2.SignatureKind.Call).length === 0 && checker.getSignaturesOfType(type, ts2.SignatureKind.Construct).length === 0;
|
|
32
84
|
}
|
|
33
85
|
function completeDeclaration(declaration, proof) {
|
|
34
86
|
if (!declaration.members.every((member3) => finiteMember(member3, proof.checker))) return false;
|
|
35
|
-
if (!
|
|
87
|
+
if (!ts2.isInterfaceDeclaration(declaration)) return true;
|
|
36
88
|
if (declaration.typeParameters?.length) return false;
|
|
37
89
|
return (declaration.heritageClauses ?? []).every((heritage) => heritage.types.every((base) => visitContract(proof.checker.getTypeAtLocation(base), proof)));
|
|
38
90
|
}
|
|
39
91
|
function finiteMember(member3, checker) {
|
|
40
|
-
if (
|
|
41
|
-
if (!member3.name || !
|
|
42
|
-
return (checker.getTypeAtLocation(member3.name.expression).flags & (
|
|
92
|
+
if (ts2.isIndexSignatureDeclaration(member3)) return false;
|
|
93
|
+
if (!member3.name || !ts2.isComputedPropertyName(member3.name)) return true;
|
|
94
|
+
return (checker.getTypeAtLocation(member3.name.expression).flags & (ts2.TypeFlags.StringLiteral | ts2.TypeFlags.NumberLiteral | ts2.TypeFlags.UniqueESSymbol)) !== 0;
|
|
43
95
|
}
|
|
44
96
|
|
|
45
97
|
// src/rules/_private-consumer-fix.ts
|
|
46
98
|
import { AST_NODE_TYPES as AST_NODE_TYPES2 } from "@typescript-eslint/utils";
|
|
47
|
-
import
|
|
99
|
+
import ts3 from "typescript";
|
|
48
100
|
|
|
49
101
|
// src/rules/_type-binding.ts
|
|
50
102
|
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
@@ -89,7 +141,7 @@ function insideTypeRange(node, range) {
|
|
|
89
141
|
}
|
|
90
142
|
|
|
91
143
|
// src/rules/_private-consumer-fix.ts
|
|
92
|
-
var UNSAFE =
|
|
144
|
+
var UNSAFE = ts3.TypeFlags.Any | ts3.TypeFlags.Unknown | ts3.TypeFlags.Never | ts3.TypeFlags.TypeParameter | ts3.TypeFlags.Conditional | ts3.TypeFlags.IndexedAccess | ts3.TypeFlags.Substitution;
|
|
93
145
|
function validConsumerFixCalls(node, parameter, sourceCode, services) {
|
|
94
146
|
if (sourceCode.getAllComments().some((comment) => /@ts-(?:expect-error|ignore|nocheck)\b/u.test(comment.value))) return false;
|
|
95
147
|
const owner = node.type === AST_NODE_TYPES2.FunctionDeclaration ? node : node.parent;
|
|
@@ -486,58 +538,75 @@ function commentLineEnd(sourceText, start) {
|
|
|
486
538
|
|
|
487
539
|
// src/rules/_private-scalar-consumer.ts
|
|
488
540
|
import { AST_NODE_TYPES as AST_NODE_TYPES5 } from "@typescript-eslint/utils";
|
|
541
|
+
import ts6 from "typescript";
|
|
542
|
+
|
|
543
|
+
// src/rules/_scalar-parameter-view.ts
|
|
544
|
+
import ts5 from "typescript";
|
|
545
|
+
|
|
546
|
+
// src/rules/_native-const-value.ts
|
|
489
547
|
import ts4 from "typescript";
|
|
548
|
+
function constInitializer(declaration) {
|
|
549
|
+
if (!declaration || !ts4.isVariableDeclaration(declaration) || !ts4.isVariableDeclarationList(declaration.parent) || (declaration.parent.flags & ts4.NodeFlags.BlockScoped) !== ts4.NodeFlags.Const) return void 0;
|
|
550
|
+
let initializer = declaration.initializer;
|
|
551
|
+
while (initializer && ts4.isParenthesizedExpression(initializer)) initializer = initializer.expression;
|
|
552
|
+
return initializer;
|
|
553
|
+
}
|
|
554
|
+
function unassertedValue(node) {
|
|
555
|
+
let value = node;
|
|
556
|
+
while (ts4.isParenthesizedExpression(value) || ts4.isAsExpression(value) || ts4.isTypeAssertionExpression(value) || ts4.isNonNullExpression(value) || ts4.isSatisfiesExpression(value)) value = value.expression;
|
|
557
|
+
return value;
|
|
558
|
+
}
|
|
490
559
|
|
|
491
560
|
// src/rules/_scalar-parameter-view.ts
|
|
492
|
-
import ts3 from "typescript";
|
|
493
561
|
var SCALAR_OPERATORS = /* @__PURE__ */ new Set([
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
562
|
+
ts5.SyntaxKind.PlusToken,
|
|
563
|
+
ts5.SyntaxKind.MinusToken,
|
|
564
|
+
ts5.SyntaxKind.AsteriskToken,
|
|
565
|
+
ts5.SyntaxKind.SlashToken,
|
|
566
|
+
ts5.SyntaxKind.PercentToken,
|
|
567
|
+
ts5.SyntaxKind.AsteriskAsteriskToken,
|
|
568
|
+
ts5.SyntaxKind.LessThanToken,
|
|
569
|
+
ts5.SyntaxKind.LessThanEqualsToken,
|
|
570
|
+
ts5.SyntaxKind.GreaterThanToken,
|
|
571
|
+
ts5.SyntaxKind.GreaterThanEqualsToken,
|
|
572
|
+
ts5.SyntaxKind.EqualsEqualsEqualsToken,
|
|
573
|
+
ts5.SyntaxKind.ExclamationEqualsEqualsToken,
|
|
574
|
+
ts5.SyntaxKind.EqualsEqualsToken,
|
|
575
|
+
ts5.SyntaxKind.ExclamationEqualsToken,
|
|
576
|
+
ts5.SyntaxKind.AmpersandAmpersandToken,
|
|
577
|
+
ts5.SyntaxKind.BarBarToken,
|
|
578
|
+
ts5.SyntaxKind.QuestionQuestionToken
|
|
511
579
|
]);
|
|
512
|
-
var SCALAR_PREFIXES = /* @__PURE__ */ new Set([
|
|
580
|
+
var SCALAR_PREFIXES = /* @__PURE__ */ new Set([ts5.SyntaxKind.PlusToken, ts5.SyntaxKind.MinusToken, ts5.SyntaxKind.ExclamationToken, ts5.SyntaxKind.TildeToken]);
|
|
581
|
+
var RETURNED_OPERANDS = /* @__PURE__ */ new Set([ts5.SyntaxKind.AmpersandAmpersandToken, ts5.SyntaxKind.BarBarToken, ts5.SyntaxKind.QuestionQuestionToken]);
|
|
513
582
|
function scalarParameterView(parameter, body3, checker) {
|
|
514
583
|
return parameterReads(parameter, body3, checker, true);
|
|
515
584
|
}
|
|
516
|
-
function scalarParameterReads(parameter, body3, checker) {
|
|
517
|
-
return parameterReads(parameter, body3, checker, false);
|
|
585
|
+
function scalarParameterReads(parameter, body3, checker, callProgram) {
|
|
586
|
+
return parameterReads(parameter, body3, checker, false, callProgram);
|
|
518
587
|
}
|
|
519
|
-
function parameterReads(parameter, body3, checker, jsx) {
|
|
520
|
-
if (parameter.dotDotDotToken || parameter.initializer ||
|
|
521
|
-
const root =
|
|
522
|
-
if (
|
|
588
|
+
function parameterReads(parameter, body3, checker, jsx, callProgram) {
|
|
589
|
+
if (parameter.dotDotDotToken || parameter.initializer || ts5.isArrayBindingPattern(parameter.name)) return null;
|
|
590
|
+
const root = ts5.isIdentifier(parameter.name) ? checker.getSymbolAtLocation(parameter.name) : void 0;
|
|
591
|
+
if (ts5.isIdentifier(parameter.name) && !root) return null;
|
|
523
592
|
const reads = /* @__PURE__ */ new Set();
|
|
524
593
|
const aliases = parameterAliases(parameter.name, checker, reads);
|
|
525
594
|
if (!aliases) return null;
|
|
526
595
|
const expression = returnedExpression(body3);
|
|
527
|
-
const view = { checker, props: checker.getTypeAtLocation(parameter), root, aliases, reads,
|
|
528
|
-
return expression && scalarView(expression, view) ? reads : null;
|
|
596
|
+
const view = { checker, props: checker.getTypeAtLocation(parameter), root, aliases, reads, callProgram };
|
|
597
|
+
return expression && scalarView(expression, view, jsx) ? reads : null;
|
|
529
598
|
}
|
|
530
599
|
function scalarType(type, allowUndefined = true) {
|
|
531
600
|
if (type.isUnion()) return type.types.every((part) => scalarType(part, allowUndefined));
|
|
532
|
-
const flags =
|
|
533
|
-
return (type.flags & (allowUndefined ? flags |
|
|
601
|
+
const flags = ts5.TypeFlags.StringLike | ts5.TypeFlags.NumberLike | ts5.TypeFlags.BooleanLike | ts5.TypeFlags.BigIntLike | ts5.TypeFlags.Null;
|
|
602
|
+
return (type.flags & (allowUndefined ? flags | ts5.TypeFlags.Undefined : flags)) !== 0;
|
|
534
603
|
}
|
|
535
604
|
function parameterAliases(name, checker, reads) {
|
|
536
605
|
const aliases = /* @__PURE__ */ new Map();
|
|
537
|
-
if (
|
|
606
|
+
if (ts5.isIdentifier(name)) return aliases;
|
|
538
607
|
for (const element of name.elements) {
|
|
539
608
|
const key = element.propertyName ?? element.name;
|
|
540
|
-
if (element.dotDotDotToken || element.initializer || !
|
|
609
|
+
if (element.dotDotDotToken || element.initializer || !ts5.isIdentifier(element.name) || !ts5.isIdentifier(key) && !ts5.isStringLiteralLike(key) && !ts5.isNumericLiteral(key)) return null;
|
|
541
610
|
const binding3 = checker.getSymbolAtLocation(element.name);
|
|
542
611
|
if (!binding3) return null;
|
|
543
612
|
reads.add(key.text);
|
|
@@ -546,31 +615,56 @@ function parameterAliases(name, checker, reads) {
|
|
|
546
615
|
return aliases;
|
|
547
616
|
}
|
|
548
617
|
function returnedExpression(body3) {
|
|
549
|
-
if (!
|
|
618
|
+
if (!ts5.isBlock(body3)) return body3;
|
|
550
619
|
const statement = body3.statements.length === 1 ? body3.statements[0] : void 0;
|
|
551
|
-
return statement &&
|
|
620
|
+
return statement && ts5.isReturnStatement(statement) ? statement.expression : void 0;
|
|
552
621
|
}
|
|
553
|
-
function scalarView(node, view) {
|
|
622
|
+
function scalarView(node, view, jsx = false) {
|
|
554
623
|
if (scalarLiteral(node)) return true;
|
|
555
|
-
if (
|
|
624
|
+
if (ts5.isCallExpression(node)) return !jsx && scalarCall(node, view);
|
|
625
|
+
if (ts5.isJsxExpression(node)) return !node.dotDotDotToken && (!node.expression || scalarView(node.expression, view, jsx));
|
|
626
|
+
if (ts5.isIdentifier(node)) {
|
|
556
627
|
const binding3 = view.checker.getSymbolAtLocation(node);
|
|
557
628
|
const key = binding3 && view.aliases.get(binding3);
|
|
558
629
|
return key !== void 0 && readField(node, key, view);
|
|
559
630
|
}
|
|
560
|
-
if (
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
if (
|
|
565
|
-
if (
|
|
566
|
-
return view.jsx &&
|
|
631
|
+
if (ts5.isPropertyAccessExpression(node) || ts5.isElementAccessExpression(node)) return memberRead(node, view);
|
|
632
|
+
return scalarOperation(node, view, jsx);
|
|
633
|
+
}
|
|
634
|
+
function scalarOperation(node, view, jsx) {
|
|
635
|
+
if (ts5.isParenthesizedExpression(node) || ts5.isNonNullExpression(node)) return scalarView(node.expression, view, jsx);
|
|
636
|
+
if (ts5.isTypeOfExpression(node)) return scalarView(node.expression, view);
|
|
637
|
+
if (ts5.isConditionalExpression(node)) return scalarView(node.condition, view) && scalarView(node.whenTrue, view, jsx) && scalarView(node.whenFalse, view, jsx);
|
|
638
|
+
if (ts5.isBinaryExpression(node)) return binaryView(node, view, jsx);
|
|
639
|
+
if (ts5.isPrefixUnaryExpression(node)) return SCALAR_PREFIXES.has(node.operator) && scalarView(node.operand, view);
|
|
640
|
+
if (ts5.isTemplateExpression(node)) return node.templateSpans.every((span) => scalarView(span.expression, view));
|
|
641
|
+
return jsx && jsxView(node, view);
|
|
642
|
+
}
|
|
643
|
+
function scalarCall(node, view) {
|
|
644
|
+
if (!view.callProgram || node.questionDotToken || node.typeArguments?.length || !ts5.isIdentifier(node.expression) || !node.arguments.length || node.arguments.some(ts5.isSpreadElement)) return false;
|
|
645
|
+
const declarations = view.checker.getSymbolAtLocation(node.expression)?.declarations;
|
|
646
|
+
const declaration = declarations?.length === 1 ? declarations[0] : void 0;
|
|
647
|
+
const helper = declaration && localHelper(declaration);
|
|
648
|
+
if (!helper || helper.getSourceFile() !== node.getSourceFile() || helper.typeParameters?.length || !helper.type || !node.arguments.every((argument) => scalarView(argument, view))) return false;
|
|
649
|
+
if (!checkedNativeSource(view.callProgram, node.getSourceFile())) return false;
|
|
650
|
+
const signature = view.checker.getResolvedSignature(node);
|
|
651
|
+
return signature?.declaration === helper && !view.checker.getTypePredicateOfSignature(signature) && scalarType(view.checker.getTypeAtLocation(node));
|
|
652
|
+
}
|
|
653
|
+
function localHelper(node) {
|
|
654
|
+
if (ts5.isFunctionDeclaration(node)) return node.body && ts5.isSourceFile(node.parent) ? node : void 0;
|
|
655
|
+
if (!ts5.isVariableDeclaration(node) || node.type || !node.initializer || constInitializer(node) !== node.initializer || !ts5.isArrowFunction(node.initializer) || !ts5.isVariableStatement(node.parent.parent) || !ts5.isSourceFile(node.parent.parent.parent)) return void 0;
|
|
656
|
+
return node.initializer;
|
|
657
|
+
}
|
|
658
|
+
function binaryView(node, view, jsx) {
|
|
659
|
+
const returned2 = jsx && RETURNED_OPERANDS.has(node.operatorToken.kind);
|
|
660
|
+
return SCALAR_OPERATORS.has(node.operatorToken.kind) && scalarView(node.left, view, returned2) && scalarView(node.right, view, returned2);
|
|
567
661
|
}
|
|
568
662
|
function scalarLiteral(node) {
|
|
569
|
-
return
|
|
663
|
+
return ts5.isStringLiteralLike(node) || ts5.isNumericLiteral(node) || ts5.isBigIntLiteral(node) || ts5.isJsxText(node) || node.kind === ts5.SyntaxKind.TrueKeyword || node.kind === ts5.SyntaxKind.FalseKeyword || node.kind === ts5.SyntaxKind.NullKeyword;
|
|
570
664
|
}
|
|
571
665
|
function memberRead(node, view) {
|
|
572
|
-
if (!view.root || !
|
|
573
|
-
const key =
|
|
666
|
+
if (!view.root || !ts5.isIdentifier(node.expression) || view.checker.getSymbolAtLocation(node.expression) !== view.root) return false;
|
|
667
|
+
const key = ts5.isPropertyAccessExpression(node) ? node.name.text : node.argumentExpression && (ts5.isStringLiteralLike(node.argumentExpression) || ts5.isNumericLiteral(node.argumentExpression)) ? node.argumentExpression.text : void 0;
|
|
574
668
|
return key !== void 0 && readField(node, key, view);
|
|
575
669
|
}
|
|
576
670
|
function readField(node, key, view) {
|
|
@@ -579,15 +673,14 @@ function readField(node, key, view) {
|
|
|
579
673
|
return true;
|
|
580
674
|
}
|
|
581
675
|
function jsxView(node, view) {
|
|
582
|
-
if (
|
|
583
|
-
if (
|
|
584
|
-
if (
|
|
585
|
-
if (!
|
|
586
|
-
if (!ts3.isIdentifier(node.tagName) || !/^[a-z][A-Za-z0-9]*$/u.test(node.tagName.text)) return false;
|
|
676
|
+
if (ts5.isJsxFragment(node)) return node.children.every((child) => scalarView(child, view, true));
|
|
677
|
+
if (ts5.isJsxElement(node)) return jsxView(node.openingElement, view) && node.children.every((child) => scalarView(child, view, true));
|
|
678
|
+
if (!ts5.isJsxOpeningElement(node) && !ts5.isJsxSelfClosingElement(node)) return false;
|
|
679
|
+
if (!ts5.isIdentifier(node.tagName) || !/^[a-z][A-Za-z0-9]*$/u.test(node.tagName.text)) return false;
|
|
587
680
|
return node.attributes.properties.every((attribute) => intrinsicAttribute(attribute, view));
|
|
588
681
|
}
|
|
589
682
|
function intrinsicAttribute(attribute, view) {
|
|
590
|
-
return
|
|
683
|
+
return ts5.isJsxAttribute(attribute) && ts5.isIdentifier(attribute.name) && attribute.name.text !== "is" && (!attribute.initializer || scalarView(attribute.initializer, view));
|
|
591
684
|
}
|
|
592
685
|
|
|
593
686
|
// src/rules/_stable-value-binding.ts
|
|
@@ -640,7 +733,7 @@ function directEval(node) {
|
|
|
640
733
|
return callee.type === AST_NODE_TYPES5.Identifier && callee.name === "eval";
|
|
641
734
|
}
|
|
642
735
|
function primitiveKeyword(node) {
|
|
643
|
-
return node !== void 0 && (node.kind ===
|
|
736
|
+
return node !== void 0 && (node.kind === ts6.SyntaxKind.StringKeyword || node.kind === ts6.SyntaxKind.NumberKeyword || node.kind === ts6.SyntaxKind.BooleanKeyword || node.kind === ts6.SyntaxKind.BigIntKeyword);
|
|
644
737
|
}
|
|
645
738
|
function consumerAnnotation(node) {
|
|
646
739
|
if (node.params.length !== 1) return void 0;
|
|
@@ -649,31 +742,31 @@ function consumerAnnotation(node) {
|
|
|
649
742
|
}
|
|
650
743
|
function exportedSymbols(source, checker) {
|
|
651
744
|
const symbol = checker.getSymbolAtLocation(source);
|
|
652
|
-
return new Set(symbol ? checker.getExportsOfModule(symbol).map((entry) => (entry.flags &
|
|
745
|
+
return new Set(symbol ? checker.getExportsOfModule(symbol).map((entry) => (entry.flags & ts6.SymbolFlags.Alias) !== 0 ? checker.getAliasedSymbol(entry) : entry) : []);
|
|
653
746
|
}
|
|
654
|
-
function privateScalarConsumer(node, sourceCode, services, exports) {
|
|
747
|
+
function privateScalarConsumer(node, sourceCode, services, exports, scalarCalls = false) {
|
|
655
748
|
const native = services.esTreeNodeToTSNodeMap.get(node);
|
|
656
|
-
if (!
|
|
749
|
+
if (!ts6.isFunctionDeclaration(native) && !ts6.isArrowFunction(native) || !native.body || !independentSignature(native)) return null;
|
|
657
750
|
const checker = services.program.getTypeChecker();
|
|
658
|
-
if (!
|
|
751
|
+
if (!ts6.isExternalModule(native.getSourceFile()) || !services.program.getCompilerOptions().strict) return null;
|
|
659
752
|
const parameter = native.parameters[0];
|
|
660
753
|
if (!parameter) return null;
|
|
661
754
|
const binding3 = callableBinding(node, sourceCode);
|
|
662
755
|
if (!binding3 || binding3.defs.length !== 1) return null;
|
|
663
|
-
const name =
|
|
756
|
+
const name = ts6.isFunctionDeclaration(native) ? native.name : ts6.isVariableDeclaration(native.parent) ? native.parent.name : void 0;
|
|
664
757
|
const symbol = name && checker.getSymbolAtLocation(name);
|
|
665
758
|
if (!symbol || symbol.declarations?.length !== 1 || exports.has(symbol) || !directCalls(binding3)) return null;
|
|
666
759
|
const signature = checker.getSignatureFromDeclaration(native);
|
|
667
760
|
if (!signature || signature.typeParameters?.length || checker.getTypePredicateOfSignature(signature)) return null;
|
|
668
761
|
const expression = returnedExpression(native.body);
|
|
669
762
|
if (!expression || !checker.isTypeAssignableTo(checker.getTypeAtLocation(expression), checker.getReturnTypeOfSignature(signature))) return null;
|
|
670
|
-
const reads = scalarParameterReads(parameter, native.body, checker);
|
|
763
|
+
const reads = scalarParameterReads(parameter, native.body, checker, scalarCalls ? services.program : void 0);
|
|
671
764
|
return reads?.size ? { parameter, reads } : null;
|
|
672
765
|
}
|
|
673
766
|
function independentSignature(native) {
|
|
674
767
|
if (native.parameters.length !== 1 || native.typeParameters?.length || native.asteriskToken || native.modifiers?.length || !primitiveKeyword(native.type)) return false;
|
|
675
768
|
const parameter = native.parameters[0];
|
|
676
|
-
return parameter !== void 0 && parameter.type !== void 0 && !parameter.modifiers?.length && !parameter.questionToken && !parameter.initializer && !parameter.dotDotDotToken && (!
|
|
769
|
+
return parameter !== void 0 && parameter.type !== void 0 && !parameter.modifiers?.length && !parameter.questionToken && !parameter.initializer && !parameter.dotDotDotToken && (!ts6.isIdentifier(parameter.name) || parameter.name.text !== "this");
|
|
677
770
|
}
|
|
678
771
|
function callableBinding(node, sourceCode) {
|
|
679
772
|
if (node.type === AST_NODE_TYPES5.FunctionDeclaration) {
|
|
@@ -723,8 +816,8 @@ function scalarFields(type, checker) {
|
|
|
723
816
|
const fields = /* @__PURE__ */ new Map();
|
|
724
817
|
for (const property of type.getProperties()) {
|
|
725
818
|
const declarations = property.getDeclarations();
|
|
726
|
-
if (!declarations?.length || !declarations.every((member3) =>
|
|
727
|
-
fields.set(property.name, (property.flags &
|
|
819
|
+
if (!declarations?.length || !declarations.every((member3) => ts7.isPropertySignature(member3) && member3.name && (ts7.isIdentifier(member3.name) || ts7.isStringLiteralLike(member3.name)) && member3.modifiers?.length === 1 && member3.modifiers[0]?.kind === ts7.SyntaxKind.ReadonlyKeyword && primitiveKeyword(member3.type))) return null;
|
|
820
|
+
fields.set(property.name, (property.flags & ts7.SymbolFlags.Optional) === 0);
|
|
728
821
|
}
|
|
729
822
|
return fields.size ? fields : null;
|
|
730
823
|
}
|
|
@@ -758,8 +851,10 @@ var no_redundant_consumer_union_default = createRule({
|
|
|
758
851
|
"Program:exit"() {
|
|
759
852
|
if (dynamic || !candidates.length) return;
|
|
760
853
|
const services = ESLintUtils2.getParserServices(context);
|
|
854
|
+
const source = currentNativeSource(context.sourceCode, services);
|
|
855
|
+
if (!source) return;
|
|
761
856
|
const checker = services.program.getTypeChecker();
|
|
762
|
-
const exports = exportedSymbols(
|
|
857
|
+
const exports = exportedSymbols(source, checker);
|
|
763
858
|
const candidateAnnotations = candidates.flatMap((node) => {
|
|
764
859
|
const annotation = consumerAnnotation(node);
|
|
765
860
|
return annotation ? [annotation] : [];
|
|
@@ -772,7 +867,7 @@ var no_redundant_consumer_union_default = createRule({
|
|
|
772
867
|
for (const candidate2 of candidates) {
|
|
773
868
|
const consumer = privateScalarConsumer(candidate2, context.sourceCode, services, exports);
|
|
774
869
|
const annotation = consumer?.parameter.type;
|
|
775
|
-
if (!consumer || !annotation || !
|
|
870
|
+
if (!consumer || !annotation || !ts7.isUnionTypeNode(annotation) || annotation.types.length !== 2) continue;
|
|
776
871
|
const leftNode = annotation.types[0];
|
|
777
872
|
const rightNode = annotation.types[1];
|
|
778
873
|
if (!leftNode || !rightNode) continue;
|
|
@@ -804,9 +899,10 @@ var no_redundant_consumer_union_default = createRule({
|
|
|
804
899
|
|
|
805
900
|
// src/rules/prefer-minimal-parameter-contract.ts
|
|
806
901
|
import { AST_NODE_TYPES as AST_NODE_TYPES7, ESLintUtils as ESLintUtils3 } from "@typescript-eslint/utils";
|
|
807
|
-
import
|
|
902
|
+
import ts8 from "typescript";
|
|
808
903
|
var CONFIG2 = { path: "tsconfig.json", source: '{"compilerOptions":{"strict":true,"target":"ESNext","module":"ESNext","moduleResolution":"Bundler"}}' };
|
|
809
904
|
var EXAMPLE2 = 'export {}; const account = {name: "Ada", email: "a"}; function label(user: {readonly email: string; readonly name: string}): string {return user.name;} label(account);';
|
|
905
|
+
var HELPER_EXAMPLE = 'export {}; const account = {name: "Ada", email: "a"}; function formatName(name: string): string {return name.toUpperCase();} function label(user: {email: string; name: string}): string {return formatName(user.name);} label(account);';
|
|
810
906
|
var PREFER_MINIMAL_PARAMETER_CONTRACT_DOCUMENTATION = {
|
|
811
907
|
defaultLevel: "warning",
|
|
812
908
|
summary: "Prefer the proven read-only subset for a private consumer parameter.",
|
|
@@ -817,18 +913,20 @@ var PREFER_MINIMAL_PARAMETER_CONTRACT_DOCUMENTATION = {
|
|
|
817
913
|
limitations: [
|
|
818
914
|
"Automatic fixes additionally require every existing identifier caller to be natively assignable to the original contract, without Any, unknown, error or unresolved types on the relevant surface. Comments inside the annotation and TypeScript suppression directives keep the finding manual. Only unread required property signatures are removed; every read or optional member, modifier and terminator token is preserved. Edits that would merge distinct CR and LF terminators remain manual.",
|
|
819
915
|
"Requires parser-owned TypeScript information and a strict external module. Only top-level private function declarations and raw const arrows with exactly one explicit parameter and an independent broad primitive return annotation are supported. Every callable reference must be a direct call with one identifier argument; exports including type-only exports, typeof queries, callbacks, storage, constructors, contextual signatures, overloads, generics, decorators, async functions and direct eval prevent findings.",
|
|
820
|
-
"Only anonymous inline contracts made of
|
|
821
|
-
"The single return expression may use only fixed scalar field reads, flat destructuring, literals, operators and
|
|
916
|
+
"Only anonymous inline contracts made of broad string, number, boolean or bigint property types are supported. Fields may be plain or readonly; the consumer body must still prove read-only usage. Retained field modifiers and optional members are preserved. Named domain contracts, brands, literal discriminants, classes, methods, callbacks, indexes, mapped types and imported parameter contracts are excluded. At least one read required field and one unread required field must be established; all-optional reduced contracts can reject existing callers through weak-type checks.",
|
|
917
|
+
"The single return expression may use only fixed scalar field reads, flat destructuring, literals, operators, templates and scalar calls to same-file implemented top-level functions or raw const arrows with an explicit return annotation. These calls require one native resolved declaration, no generic or predicate signature, scalar arguments/result and complete active native checking of the local implementation file. Their helper bodies need not be pure because only scalar values cross the call and only an erased parameter annotation changes. Imported, aliased, ambient, overloaded, optional, spread and member calls remain unsupported. Bound destructured fields count as reads even when their local aliases are unused. Whole-object escape, identity, mutation, closures, reflection, serialization, dynamic keys, implicit Object capabilities and JSX are unsupported. Unknown semantic information causes abstention. Findings outside the fix proof remain manual; this is not a requirement to minimize every object or discard useful producer fields."
|
|
822
918
|
],
|
|
823
919
|
examples: [
|
|
824
920
|
{ id: "unused-required-field", title: "A private name consumer unnecessarily requires email", outcome: "match", files: [{ path: "src/case.ts", source: EXAMPLE2 }, CONFIG2], focusPath: "src/case.ts", expectedCount: 1, public: true, fixedFiles: [{ path: "src/case.ts", source: EXAMPLE2.replace("readonly email: string;", "") }] },
|
|
825
|
-
{ id: "used-fields", title: "Every required dependency is read", outcome: "no-match", files: [{ path: "src/case.ts", source: EXAMPLE2.replace("return user.name;", "return user.name + user.email;") }, CONFIG2], focusPath: "src/case.ts", expectedCount: 0, public: true }
|
|
921
|
+
{ id: "used-fields", title: "Every required dependency is read", outcome: "no-match", files: [{ path: "src/case.ts", source: EXAMPLE2.replace("return user.name;", "return user.name + user.email;") }, CONFIG2], focusPath: "src/case.ts", expectedCount: 0, public: true },
|
|
922
|
+
{ id: "scalar-helper", scenarioId: "local-scalar-helper", title: "Only the name crosses a local scalar helper call", outcome: "match", files: [{ path: "src/case.ts", source: HELPER_EXAMPLE }, CONFIG2], focusPath: "src/case.ts", expectedCount: 1, public: true, fixedFiles: [{ path: "src/case.ts", source: HELPER_EXAMPLE.replace("email: string;", "") }] },
|
|
923
|
+
{ id: "helper-and-other-field", scenarioId: "local-scalar-helper", title: "The consumer still requires a separately read field", outcome: "no-match", files: [{ path: "src/case.ts", source: HELPER_EXAMPLE.replace("return formatName(user.name);", "return formatName(user.name) + user.email;") }, CONFIG2], focusPath: "src/case.ts", expectedCount: 0, public: true }
|
|
826
924
|
]
|
|
827
925
|
};
|
|
828
926
|
function inlineFields(node) {
|
|
829
927
|
const fields = /* @__PURE__ */ new Map();
|
|
830
928
|
for (const member3 of node.members) {
|
|
831
|
-
if (!
|
|
929
|
+
if (!ts8.isPropertySignature(member3) || !member3.name || !ts8.isIdentifier(member3.name) && !ts8.isStringLiteralLike(member3.name) || (member3.modifiers?.length ?? 0) > 1 || member3.modifiers?.some((modifier) => modifier.kind !== ts8.SyntaxKind.ReadonlyKeyword) || !primitiveKeyword(member3.type)) return null;
|
|
832
930
|
const key = member3.name.text;
|
|
833
931
|
if (fields.has(key)) return null;
|
|
834
932
|
fields.set(key, !member3.questionToken);
|
|
@@ -839,7 +937,7 @@ var prefer_minimal_parameter_contract_default = createRule({
|
|
|
839
937
|
name: "prefer-minimal-parameter-contract",
|
|
840
938
|
documentation: PREFER_MINIMAL_PARAMETER_CONTRACT_DOCUMENTATION,
|
|
841
939
|
meta: { type: "suggestion", fixable: "code", docs: { description: PREFER_MINIMAL_PARAMETER_CONTRACT_DOCUMENTATION.summary }, schema: [], messages: {
|
|
842
|
-
minimal: "This private consumer reads only {{used}} but also requires {{unused}}. Review a smaller
|
|
940
|
+
minimal: "This private consumer reads only {{used}} but also requires {{unused}}. Review a smaller consumer contract; preserve the original runtime object and producer type."
|
|
843
941
|
} },
|
|
844
942
|
defaultOptions: [],
|
|
845
943
|
create(context) {
|
|
@@ -858,18 +956,20 @@ var prefer_minimal_parameter_contract_default = createRule({
|
|
|
858
956
|
"Program:exit"() {
|
|
859
957
|
if (dynamic || !candidates.length) return;
|
|
860
958
|
const services = ESLintUtils3.getParserServices(context);
|
|
959
|
+
const source = currentNativeSource(context.sourceCode, services);
|
|
960
|
+
if (!source) return;
|
|
861
961
|
const checker = services.program.getTypeChecker();
|
|
862
|
-
const exports = exportedSymbols(
|
|
962
|
+
const exports = exportedSymbols(source, checker);
|
|
863
963
|
for (const candidate2 of candidates) {
|
|
864
|
-
const consumer = privateScalarConsumer(candidate2, context.sourceCode, services, exports);
|
|
964
|
+
const consumer = privateScalarConsumer(candidate2, context.sourceCode, services, exports, true);
|
|
865
965
|
const annotation = consumer?.parameter.type;
|
|
866
|
-
if (!consumer || !annotation || !
|
|
966
|
+
if (!consumer || !annotation || !ts8.isTypeLiteralNode(annotation)) continue;
|
|
867
967
|
const fields = inlineFields(annotation);
|
|
868
968
|
if (!fields || [...consumer.reads].some((key) => !fields.has(key)) || ![...consumer.reads].some((key) => fields.get(key))) continue;
|
|
869
969
|
const unused = [...fields].filter(([key, required]) => required && !consumer.reads.has(key)).map(([key]) => key).sort();
|
|
870
970
|
if (!unused.length) continue;
|
|
871
971
|
const reportNode = services.tsNodeToESTreeNodeMap.get(annotation);
|
|
872
|
-
const removed = annotation.members.filter((member3) =>
|
|
972
|
+
const removed = annotation.members.filter((member3) => ts8.isPropertySignature(member3) && member3.name && (ts8.isIdentifier(member3.name) || ts8.isStringLiteralLike(member3.name)) && unused.includes(member3.name.text)).map((member3) => ({ start: member3.getStart(), end: member3.getEnd() }));
|
|
873
973
|
const fix = validConsumerFixCalls(candidate2, consumer.parameter, context.sourceCode, services) ? minimalConsumerFix(context.sourceCode, reportNode, removed) : null;
|
|
874
974
|
context.report({ node: reportNode, messageId: "minimal", data: { used: [...consumer.reads].sort().join(", "), unused: unused.join(", ") }, fix });
|
|
875
975
|
}
|
|
@@ -880,7 +980,282 @@ var prefer_minimal_parameter_contract_default = createRule({
|
|
|
880
980
|
|
|
881
981
|
// src/rules/no-excess-jsx-props.ts
|
|
882
982
|
import { AST_NODE_TYPES as AST_NODE_TYPES8, ESLintUtils as ESLintUtils4 } from "@typescript-eslint/utils";
|
|
883
|
-
import
|
|
983
|
+
import ts10 from "typescript";
|
|
984
|
+
|
|
985
|
+
// src/rules/_ordinary-object-effects.ts
|
|
986
|
+
import ts9 from "typescript";
|
|
987
|
+
var ANALYSES = /* @__PURE__ */ new WeakMap();
|
|
988
|
+
var MAX_ALIAS_DEPTH = 64;
|
|
989
|
+
var MAX_SOURCE_GRAPH = 128;
|
|
990
|
+
var GLOBAL_IDENTITIES = [["Object", "object"], ["Reflect", "reflect"], ["globalThis", "globalThis"], ["eval", "dynamic"], ["Function", "dynamic"]];
|
|
991
|
+
var OBJECT_REFLECTION = /* @__PURE__ */ new Set([
|
|
992
|
+
"assign",
|
|
993
|
+
"defineProperty",
|
|
994
|
+
"defineProperties",
|
|
995
|
+
"freeze",
|
|
996
|
+
"seal",
|
|
997
|
+
"preventExtensions",
|
|
998
|
+
"setPrototypeOf",
|
|
999
|
+
"getPrototypeOf",
|
|
1000
|
+
"getOwnPropertyDescriptor",
|
|
1001
|
+
"getOwnPropertyDescriptors"
|
|
1002
|
+
]);
|
|
1003
|
+
function ordinaryObjectEffects(program, source) {
|
|
1004
|
+
let analysis = ANALYSES.get(program);
|
|
1005
|
+
if (!analysis) {
|
|
1006
|
+
analysis = programFacts(program);
|
|
1007
|
+
ANALYSES.set(program, analysis);
|
|
1008
|
+
}
|
|
1009
|
+
const known2 = analysis.roots.get(source);
|
|
1010
|
+
if (known2 !== void 0) return known2;
|
|
1011
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1012
|
+
const queue = [source];
|
|
1013
|
+
while (queue.length) {
|
|
1014
|
+
const current = queue.pop();
|
|
1015
|
+
if (!current || visited.has(current)) continue;
|
|
1016
|
+
if (analysis.roots.get(current) || visited.size >= MAX_SOURCE_GRAPH) {
|
|
1017
|
+
analysis.roots.set(source, true);
|
|
1018
|
+
return true;
|
|
1019
|
+
}
|
|
1020
|
+
visited.add(current);
|
|
1021
|
+
const facts = fileFacts(current, analysis);
|
|
1022
|
+
if (facts.unsafe || facts.jsx && !standardJSXRuntime(current, analysis) || analysis.aliasValues.has(current) && !checkedNativeSource(program, current)) {
|
|
1023
|
+
analysis.roots.set(source, true);
|
|
1024
|
+
return true;
|
|
1025
|
+
}
|
|
1026
|
+
queue.push(...facts.imports, ...analysis.importers.get(current) ?? []);
|
|
1027
|
+
}
|
|
1028
|
+
for (const file of visited) analysis.roots.set(file, false);
|
|
1029
|
+
return false;
|
|
1030
|
+
}
|
|
1031
|
+
function programFacts(program) {
|
|
1032
|
+
const checker = program.getTypeChecker();
|
|
1033
|
+
const globals = /* @__PURE__ */ new Map();
|
|
1034
|
+
for (const [name, identity2] of GLOBAL_IDENTITIES) {
|
|
1035
|
+
const symbol = checker.resolveName(name, void 0, ts9.SymbolFlags.Value, false);
|
|
1036
|
+
if (symbol) globals.set(symbol, identity2);
|
|
1037
|
+
}
|
|
1038
|
+
const importers = /* @__PURE__ */ new Map();
|
|
1039
|
+
const analysis = { program, checker, globals, importers, aliasValues: /* @__PURE__ */ new WeakSet(), jsxRuntimes: /* @__PURE__ */ new WeakMap(), files: /* @__PURE__ */ new WeakMap(), roots: /* @__PURE__ */ new WeakMap() };
|
|
1040
|
+
for (const source of program.getSourceFiles()) {
|
|
1041
|
+
for (const dependency of fileFacts(source, analysis).imports) {
|
|
1042
|
+
let parents = importers.get(dependency);
|
|
1043
|
+
if (!parents) {
|
|
1044
|
+
parents = /* @__PURE__ */ new Set();
|
|
1045
|
+
importers.set(dependency, parents);
|
|
1046
|
+
}
|
|
1047
|
+
parents.add(source);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
return analysis;
|
|
1051
|
+
}
|
|
1052
|
+
function fileFacts(source, analysis) {
|
|
1053
|
+
let facts = analysis.files.get(source);
|
|
1054
|
+
if (!facts) {
|
|
1055
|
+
facts = sourceFacts(source, analysis);
|
|
1056
|
+
analysis.files.set(source, facts);
|
|
1057
|
+
}
|
|
1058
|
+
return facts;
|
|
1059
|
+
}
|
|
1060
|
+
function sourceFacts(source, analysis) {
|
|
1061
|
+
if (source.isDeclarationFile) return { unsafe: true, imports: [], jsx: false };
|
|
1062
|
+
const references = [];
|
|
1063
|
+
const imports = [];
|
|
1064
|
+
let unsafe = analysis.program.isSourceFileFromExternalLibrary(source);
|
|
1065
|
+
let jsx = false;
|
|
1066
|
+
const visit = (node) => {
|
|
1067
|
+
if (ts9.isInterfaceDeclaration(node) || ts9.isTypeAliasDeclaration(node) || ts9.isTypeLiteralNode(node) || ts9.isTypeQueryNode(node) || ts9.isTypeReferenceNode(node) || ts9.isImportTypeNode(node) || ts9.isTypeParameterDeclaration(node) || ts9.isHeritageClause(node) && node.token === ts9.SyntaxKind.ImplementsKeyword) return;
|
|
1068
|
+
jsx ||= ts9.isJsxElement(node) || ts9.isJsxSelfClosingElement(node) || ts9.isJsxFragment(node);
|
|
1069
|
+
const dependency = moduleEffect(node, imports, analysis);
|
|
1070
|
+
if (dependency !== void 0) unsafe ||= dependency;
|
|
1071
|
+
if (ts9.isImportDeclaration(node) || ts9.isExportDeclaration(node) && (node.isTypeOnly || node.moduleSpecifier) || ts9.isExportSpecifier(node) && node.isTypeOnly) return;
|
|
1072
|
+
if (!unsafe) {
|
|
1073
|
+
if (ts9.isIdentifier(node) || ts9.isPropertyAccessExpression(node) || ts9.isElementAccessExpression(node)) references.push(node);
|
|
1074
|
+
unsafe ||= runtimeEffect(node, analysis);
|
|
1075
|
+
}
|
|
1076
|
+
ts9.forEachChild(node, visit);
|
|
1077
|
+
};
|
|
1078
|
+
visit(source);
|
|
1079
|
+
if (unsafe) return { unsafe, imports, jsx };
|
|
1080
|
+
for (const node of references) {
|
|
1081
|
+
if (reflectiveMember(node, analysis)) unsafe = true;
|
|
1082
|
+
const value = identity(node, analysis);
|
|
1083
|
+
if (value === "incomplete" || value === "dynamic" || protectedIdentity(value) && !containedUse(node)) unsafe = true;
|
|
1084
|
+
}
|
|
1085
|
+
return { unsafe, imports, jsx };
|
|
1086
|
+
}
|
|
1087
|
+
function moduleEffect(node, imports, analysis) {
|
|
1088
|
+
if (ts9.isImportDeclaration(node) || ts9.isExportDeclaration(node)) return !moduleDependency(node, imports, analysis);
|
|
1089
|
+
if (!ts9.isCallExpression(node) || node.expression.kind !== ts9.SyntaxKind.ImportKeyword) return void 0;
|
|
1090
|
+
const specifier = node.arguments[0];
|
|
1091
|
+
const resolved = specifier && ts9.isStringLiteralLike(specifier) && resolvedDependency(specifier, imports, analysis);
|
|
1092
|
+
return node.arguments.length !== 1 || !resolved;
|
|
1093
|
+
}
|
|
1094
|
+
function runtimeEffect(node, analysis) {
|
|
1095
|
+
if (node.kind === ts9.SyntaxKind.ThisKeyword || node.kind === ts9.SyntaxKind.SuperKeyword || ts9.isMetaProperty(node)) return true;
|
|
1096
|
+
if (ts9.isVariableDeclaration(node)) return !node.initializer;
|
|
1097
|
+
if (ts9.isFunctionDeclaration(node)) return !node.body;
|
|
1098
|
+
if (ts9.isForOfStatement(node) || ts9.isForInStatement(node) || ts9.isNewExpression(node) || ts9.isTaggedTemplateExpression(node)) return true;
|
|
1099
|
+
if (!ts9.isCallExpression(node)) return mutationEffect(node, analysis);
|
|
1100
|
+
return node.expression.kind !== ts9.SyntaxKind.ImportKeyword;
|
|
1101
|
+
}
|
|
1102
|
+
function mutationEffect(node, analysis) {
|
|
1103
|
+
if (ts9.isBinaryExpression(node) && node.operatorToken.kind >= ts9.SyntaxKind.FirstAssignment && node.operatorToken.kind <= ts9.SyntaxKind.LastAssignment) return unsafeTarget(node.left, analysis);
|
|
1104
|
+
if (ts9.isDeleteExpression(node)) return unsafeTarget(node.expression, analysis);
|
|
1105
|
+
return (ts9.isPrefixUnaryExpression(node) || ts9.isPostfixUnaryExpression(node)) && (node.operator === ts9.SyntaxKind.PlusPlusToken || node.operator === ts9.SyntaxKind.MinusMinusToken) && unsafeTarget(node.operand, analysis);
|
|
1106
|
+
}
|
|
1107
|
+
function identity(node, analysis, active = /* @__PURE__ */ new Set()) {
|
|
1108
|
+
const value = unassertedValue(node);
|
|
1109
|
+
if (active.has(value) || active.size >= MAX_ALIAS_DEPTH) return "incomplete";
|
|
1110
|
+
active.add(value);
|
|
1111
|
+
let result = "unknown";
|
|
1112
|
+
if (ts9.isObjectLiteralExpression(value) || ts9.isArrayLiteralExpression(value)) result = "fresh";
|
|
1113
|
+
else if (ts9.isIdentifier(value)) result = identifierIdentity(value, analysis, active);
|
|
1114
|
+
else if (ts9.isPropertyAccessExpression(value) || ts9.isElementAccessExpression(value)) result = memberIdentity(value, analysis, active);
|
|
1115
|
+
active.delete(value);
|
|
1116
|
+
return result;
|
|
1117
|
+
}
|
|
1118
|
+
function identifierIdentity(value, analysis, active) {
|
|
1119
|
+
const parent = value.parent;
|
|
1120
|
+
if (nonValueName(value)) return "unknown";
|
|
1121
|
+
let symbol = ts9.isShorthandPropertyAssignment(parent) && parent.name === value ? analysis.checker.getShorthandAssignmentValueSymbol(parent) : analysis.checker.getSymbolAtLocation(value);
|
|
1122
|
+
const alias = symbol !== void 0 && (symbol.flags & ts9.SymbolFlags.Alias) !== 0;
|
|
1123
|
+
if (symbol && alias) symbol = analysis.checker.getAliasedSymbol(symbol);
|
|
1124
|
+
if (symbol && analysis.checker.isUnknownSymbol(symbol)) return "incomplete";
|
|
1125
|
+
if (!symbol || (symbol.flags & ts9.SymbolFlags.Value) === 0) {
|
|
1126
|
+
const erasedBinding = ts9.isModuleDeclaration(parent) && parent.name === value || ts9.isExportSpecifier(parent) && symbol !== void 0 && (symbol.flags & (ts9.SymbolFlags.Type | ts9.SymbolFlags.Namespace)) !== 0;
|
|
1127
|
+
return erasedBinding ? "unknown" : "incomplete";
|
|
1128
|
+
}
|
|
1129
|
+
if (alias) analysis.aliasValues.add(value.getSourceFile());
|
|
1130
|
+
return runtimeBindingIdentity(value, symbol, alias, analysis, active);
|
|
1131
|
+
}
|
|
1132
|
+
function runtimeBindingIdentity(value, symbol, alias, analysis, active) {
|
|
1133
|
+
const parent = value.parent;
|
|
1134
|
+
if (symbol.declarations?.some(ts9.isModuleDeclaration)) {
|
|
1135
|
+
return ts9.isModuleDeclaration(parent) && parent.name === value && (ts9.getCombinedModifierFlags(parent) & ts9.ModifierFlags.Ambient) === 0 ? "unknown" : "incomplete";
|
|
1136
|
+
}
|
|
1137
|
+
if ((symbol.flags & ts9.SymbolFlags.Property) !== 0) return "unknown";
|
|
1138
|
+
if ((symbol.flags & ts9.SymbolFlags.ConstEnum) !== 0) return "incomplete";
|
|
1139
|
+
const global = analysis.globals.get(symbol);
|
|
1140
|
+
if (global !== void 0) return global;
|
|
1141
|
+
const declaration = symbol.valueDeclaration;
|
|
1142
|
+
if (declaration && !alias && declaration.getSourceFile() !== value.getSourceFile()) return "incomplete";
|
|
1143
|
+
if (declaration && (declaration.getSourceFile().isDeclarationFile || (ts9.getCombinedModifierFlags(declaration) & ts9.ModifierFlags.Ambient) !== 0)) return "incomplete";
|
|
1144
|
+
const initializer = constInitializer(declaration);
|
|
1145
|
+
return initializer ? identity(initializer, analysis, active) : "unknown";
|
|
1146
|
+
}
|
|
1147
|
+
function nonValueName(value) {
|
|
1148
|
+
const parent = value.parent;
|
|
1149
|
+
if ((ts9.isPropertyAccessExpression(parent) || ts9.isPropertyAssignment(parent) || ts9.isJsxAttribute(parent) || ts9.isEnumDeclaration(parent) || ts9.isEnumMember(parent)) && parent.name === value) return true;
|
|
1150
|
+
if (ts9.isBindingElement(parent) && parent.propertyName === value) return true;
|
|
1151
|
+
if ((ts9.isLabeledStatement(parent) || ts9.isBreakStatement(parent) || ts9.isContinueStatement(parent)) && parent.label === value) return true;
|
|
1152
|
+
if (ts9.isJsxNamespacedName(parent)) return true;
|
|
1153
|
+
return (ts9.isJsxOpeningElement(parent) || ts9.isJsxSelfClosingElement(parent) || ts9.isJsxClosingElement(parent)) && parent.tagName === value && (/^[a-z]/u.test(value.text) || value.text.includes("-"));
|
|
1154
|
+
}
|
|
1155
|
+
function memberIdentity(value, analysis, active) {
|
|
1156
|
+
const base = identity(value.expression, analysis, active);
|
|
1157
|
+
if (base === "incomplete") return base;
|
|
1158
|
+
const key = memberKey(value);
|
|
1159
|
+
if (base === "object" && key === "prototype") return "prototype";
|
|
1160
|
+
if (base !== "globalThis" || key === void 0) return "unknown";
|
|
1161
|
+
const symbol = analysis.checker.resolveName(key, void 0, ts9.SymbolFlags.Value, false);
|
|
1162
|
+
return symbol && analysis.globals.get(symbol) || "incomplete";
|
|
1163
|
+
}
|
|
1164
|
+
function memberKey(node) {
|
|
1165
|
+
if (ts9.isPropertyAccessExpression(node)) return node.name.text;
|
|
1166
|
+
const key = node.argumentExpression && unassertedValue(node.argumentExpression);
|
|
1167
|
+
return key && (ts9.isStringLiteralLike(key) || ts9.isNumericLiteral(key)) ? key.text : void 0;
|
|
1168
|
+
}
|
|
1169
|
+
function protectedIdentity(value) {
|
|
1170
|
+
return value === "object" || value === "reflect" || value === "prototype" || value === "globalThis" || value === "dynamic";
|
|
1171
|
+
}
|
|
1172
|
+
function containedUse(node) {
|
|
1173
|
+
const value = expressionUse(node);
|
|
1174
|
+
const parent = value.parent;
|
|
1175
|
+
if (!parent) return false;
|
|
1176
|
+
if ((ts9.isPropertyAccessExpression(parent) || ts9.isElementAccessExpression(parent)) && parent.expression === value) return memberKey(parent) !== void 0;
|
|
1177
|
+
if (ts9.isVariableDeclaration(parent) && parent.name === value) return true;
|
|
1178
|
+
if (ts9.isVariableDeclaration(parent) && parent.initializer === value) {
|
|
1179
|
+
const statement = parent.parent.parent;
|
|
1180
|
+
return constInitializer(parent) !== void 0 && ts9.isIdentifier(parent.name) && (!ts9.isVariableStatement(statement) || !statement.modifiers?.some((modifier) => modifier.kind === ts9.SyntaxKind.ExportKeyword));
|
|
1181
|
+
}
|
|
1182
|
+
return false;
|
|
1183
|
+
}
|
|
1184
|
+
function expressionUse(node) {
|
|
1185
|
+
let value = node;
|
|
1186
|
+
while (value.parent && unassertedValue(value.parent) === unassertedValue(value)) value = value.parent;
|
|
1187
|
+
return value;
|
|
1188
|
+
}
|
|
1189
|
+
function unsafeTarget(node, analysis) {
|
|
1190
|
+
const value = unassertedValue(node);
|
|
1191
|
+
if (ts9.isIdentifier(value)) return protectedIdentity(identity(value, analysis));
|
|
1192
|
+
if (ts9.isPropertyAccessExpression(value) || ts9.isElementAccessExpression(value)) return identity(value.expression, analysis) !== "fresh";
|
|
1193
|
+
return true;
|
|
1194
|
+
}
|
|
1195
|
+
function reflectiveMember(node, analysis) {
|
|
1196
|
+
if (!ts9.isPropertyAccessExpression(node) && !ts9.isElementAccessExpression(node)) return false;
|
|
1197
|
+
const base = identity(node.expression, analysis);
|
|
1198
|
+
const key = memberKey(node);
|
|
1199
|
+
return base === "reflect" || base === "object" && (key === void 0 || OBJECT_REFLECTION.has(key));
|
|
1200
|
+
}
|
|
1201
|
+
function moduleDependency(node, imports, analysis) {
|
|
1202
|
+
if (ts9.isImportDeclaration(node) && node.importClause?.isTypeOnly || ts9.isExportDeclaration(node) && node.isTypeOnly) return true;
|
|
1203
|
+
const clause = ts9.isImportDeclaration(node) ? node.importClause?.namedBindings : node.exportClause;
|
|
1204
|
+
const erasesNamedBindings = !analysis.program.getCompilerOptions().verbatimModuleSyntax;
|
|
1205
|
+
if (erasesNamedBindings && ts9.isImportDeclaration(node) && clause && ts9.isNamedImports(clause) && !node.importClause?.name && clause.elements.length && clause.elements.every((item) => item.isTypeOnly)) return true;
|
|
1206
|
+
if (erasesNamedBindings && clause && ts9.isNamedExports(clause) && clause.elements.length && clause.elements.every((item) => item.isTypeOnly)) return true;
|
|
1207
|
+
if (!node.moduleSpecifier) return true;
|
|
1208
|
+
return resolvedDependency(node.moduleSpecifier, imports, analysis);
|
|
1209
|
+
}
|
|
1210
|
+
function resolvedDependency(specifier, imports, analysis) {
|
|
1211
|
+
const symbol = analysis.checker.getSymbolAtLocation(specifier);
|
|
1212
|
+
const declarations = symbol?.declarations;
|
|
1213
|
+
if (!declarations?.length) return false;
|
|
1214
|
+
let resolved = true;
|
|
1215
|
+
for (const declaration of declarations) {
|
|
1216
|
+
if (!ts9.isSourceFile(declaration)) {
|
|
1217
|
+
resolved = false;
|
|
1218
|
+
continue;
|
|
1219
|
+
}
|
|
1220
|
+
imports.push(declaration);
|
|
1221
|
+
if (declaration.isDeclarationFile || analysis.program.isSourceFileFromExternalLibrary(declaration)) resolved = false;
|
|
1222
|
+
}
|
|
1223
|
+
return resolved;
|
|
1224
|
+
}
|
|
1225
|
+
function standardJSXRuntime(source, analysis) {
|
|
1226
|
+
const known2 = analysis.jsxRuntimes.get(source);
|
|
1227
|
+
if (known2 !== void 0) return known2;
|
|
1228
|
+
const standard = analysis.program.getSourceFile(source.fileName) === source && declaredJSXRuntime(source, analysis);
|
|
1229
|
+
analysis.jsxRuntimes.set(source, standard);
|
|
1230
|
+
return standard;
|
|
1231
|
+
}
|
|
1232
|
+
function declaredJSXRuntime(source, analysis) {
|
|
1233
|
+
const mode = analysis.program.getCompilerOptions().jsx;
|
|
1234
|
+
const name = mode === ts9.JsxEmit.ReactJSX ? "react/jsx-runtime" : mode === ts9.JsxEmit.ReactJSXDev ? "react/jsx-dev-runtime" : void 0;
|
|
1235
|
+
if (name === void 0) return false;
|
|
1236
|
+
const specifier = implicitJSXImport(source, name);
|
|
1237
|
+
const declarations = specifier && analysis.checker.getSymbolAtLocation(specifier)?.declarations;
|
|
1238
|
+
return declarations !== void 0 && declarations.length > 0 && declarations.every((declaration) => declaredReactRuntime(declaration, name, analysis.program));
|
|
1239
|
+
}
|
|
1240
|
+
function implicitJSXImport(source, name) {
|
|
1241
|
+
const imports = source.imports;
|
|
1242
|
+
if (!Array.isArray(imports)) return void 0;
|
|
1243
|
+
let selected;
|
|
1244
|
+
for (const node of imports) {
|
|
1245
|
+
if (!node || !ts9.isStringLiteral(node) || node.text !== name || !node.parent || !ts9.isImportDeclaration(node.parent) || node.parent.moduleSpecifier !== node || node.parent.parent !== source || source.statements.includes(node.parent) || node.getSourceFile() !== source) continue;
|
|
1246
|
+
if (selected) return void 0;
|
|
1247
|
+
selected = node;
|
|
1248
|
+
}
|
|
1249
|
+
return selected;
|
|
1250
|
+
}
|
|
1251
|
+
function declaredReactRuntime(declaration, name, program) {
|
|
1252
|
+
const source = declaration.getSourceFile();
|
|
1253
|
+
if (!source.isDeclarationFile || program.getSourceFile(source.fileName) !== source) return false;
|
|
1254
|
+
if (ts9.isSourceFile(declaration)) return program.isSourceFileFromExternalLibrary(source);
|
|
1255
|
+
return ts9.isModuleDeclaration(declaration) && declaration.parent === source && ts9.isStringLiteral(declaration.name) && declaration.name.text === name;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
// src/rules/no-excess-jsx-props.ts
|
|
884
1259
|
var EXAMPLE_TSCONFIG = { path: "tsconfig.json", source: '{"compilerOptions":{"strict":true,"target":"ESNext","module":"ESNext","moduleResolution":"Bundler","jsx":"react-jsx"}}' };
|
|
885
1260
|
var EXAMPLE_JSX = { path: "jsx.d.ts", source: 'declare module "react/jsx-runtime" { export namespace JSX { interface Element {} interface IntrinsicElements {span: {children?: unknown}} } }' };
|
|
886
1261
|
var NO_EXCESS_JSX_PROPS_DOCUMENTATION = {
|
|
@@ -891,23 +1266,58 @@ var NO_EXCESS_JSX_PROPS_DOCUMENTATION = {
|
|
|
891
1266
|
defaultLevel: "warning",
|
|
892
1267
|
autofix: "none",
|
|
893
1268
|
limitations: [
|
|
1269
|
+
"The created JSX value must initialize a private actual const binding. Only unused values or same-function-scope fixed reads of already proven consumed scalar props are supported. Enclosing invocations must have no runtime argument or arguments-object dependency, async/generator suspension, or unproved captured values. Unused simple arguments and captured scalar data reuse the existing provenance proof; destructured/default/rest arguments remain unsupported. Exported, returned, aliased, captured, aggregated or forwarded elements, whole-props access, opaque calls, type observations and writes abstain. A caller can mutate production React props after creation even when development React freezes them; initial source provenance alone is insufficient. This restriction intentionally excludes ordinary exported and rendered elements until their consumers can be proved.",
|
|
1270
|
+
"The rule abstains when the receiving or calling project runtime dependency context contains a known ordinary Object-prototype effect or exposure, native eval/Function capabilities, any explicit call, constructor or tagged-template invocation, for-of or for-in iteration, an ambient or uninitialized value declaration or a declaration-file value read, an unresolved lexical value (including a shorthand or a type-only name used as a value), an erased const-enum value without a runtime binding proof, an opaque globalThis member, an implicit this/super/module-metadata capability, an extracted reflective method, or a member-write target not proven to be a fresh unrelated object/array literal. Callable and class metadata writes, including through erased const aliases, abstain: runtime metadata can observe omitted fields even when it is absent from the native JSX contract. Native shorthand value symbols preserve global capability identity instead of trusting a newly created property symbol. Property keys, control-flow labels, intrinsic JSX names and erased type positions do not evaluate lexical values; their missing symbols or Any types do not alone veto a finding. Native ESM imports/re-exports and literal dynamic imports are followed in both dependency and known-importer directions, including other dependencies of those importers and resolved bare path aliases; whole-clause import type/export type forms are skipped. Import-equals and other loader forms are unsupported. Per-specifier type imports/exports retain their runtime edges when native verbatimModuleSyntax emit keeps an empty import/export. Unresolved runtime imports and declaration-only or external-library runtime imports abstain. Literal dynamic imports retain their module-resolution proof. External code outside the analyzed project context and standard library implementations remain opaque; standard ordinary Object built-ins are assumed. Connected runtime dependency contexts beyond 128 files or const-alias proofs beyond 64 steps abstain. Safe reflective code may therefore be excluded. This finite known-effect exclusion does not prove universal prototype pristineness.",
|
|
894
1271
|
"Requires parser-owned TypeScript information, a strict module implementation, a complete Object base, a self-closing identifier tag with one plain object-literal spread and no other attributes, and one nongeneric implemented synchronous arrow receiver with a resolved finite props surface. Sibling attributes or children could override the proven source values. Unknown, opaque, union, overloaded, generic, intrinsic and class receivers are excluded.",
|
|
895
1272
|
"Mapped types, index signatures, namespace/value-derived contracts, unresolved inherited or computed receiver keys, nonliteral computed source keys, nested spreads, accessors and explicit __proto__ keys are excluded. Source type properties alone do not prove enumerable own runtime keys. key, ref, React's __self/__source development metadata and TypeScript's hyphenated JSX attribute names are preserved.",
|
|
896
1273
|
"Native member lookup includes inherited, optional, readonly and implicit Object capabilities. The rule reports runtime keys outside the contract; it does not infer unused component fields, demand smaller public APIs, or erase producer type information.",
|
|
897
|
-
"
|
|
1274
|
+
"Runtime alias references require active native checking of each reached local implementation, with no located syntax or semantic errors. Checking disabled by noCheck or native-shaped TypeScript suppression directives is unavailable evidence. JavaScript, declaration/default/external-library files, foreign SourceFile objects and project-reference programs are unsupported for this alias proof. Importer indexing does not request full semantic checks; reached files reuse the parser-owned Program's diagnostic caches. Unlocated/global diagnostics are not treated as a clean project or as proof of runtime binding presence. Namespace value reads, including merged and const-enum-only namespace carriers, abstain because a ValueModule symbol can survive erased runtime output without a native error. Pure type namespaces and nonambient namespace declaration names remain non-value positions; explicit ambient namespace declarations retain their existing exclusion. A non-import-alias value declared in another source also abstains: inclusion in the type Program does not establish that a script/global implementation executes or that an ambient binding is supplied as a data property. Native standard global identities retain their existing assumptions.",
|
|
1275
|
+
"Requires a single returned view made from intrinsic JSX, literals and scalar parameter reads/operators. JSX objects may be rendered as children or returned branches, but cannot be operands of scalar coercions or intrinsic attribute values. Free runtime values, helper calls, callbacks, object-valued consumed fields, custom tags, rest/spread, reflection and dynamic access prevent a finding; indirect element.props aliases cannot be inferred safe. Every inspected or destructured root field must be an own source-literal key; an omitted field could invoke an inherited getter. Bound/read source values require concrete scalar types without undefined, Any or unknown and runtime primitive provenance: literals, operators/templates with proven primitive operands, proven conditional tests and branches, or local immutable const initializers after removing assertions. Direct own fields of a same-file const object literal are supported only when every object reference is a fixed field value in a direct object initializer, inline JSX spread, JSX expression or local binding, with no direct eval. Mutation, accessors, method receivers, dynamic keys, reflection, whole-object aliases and exports abstain. Opaque calls, getters, parameters, mutable bindings and imported source values abstain even when annotated as scalars. Unproven source paths beyond 64 expressions abstain as an analysis resource limit. Only successful value proofs are memoized. An alias or assertion cannot turn an object into a primitive; undefined can activate runtime defaults. Opaque HOC and declaration-file signatures remain unsupported.",
|
|
898
1276
|
"The actual tag must resolve through immutable identifier aliases to a const arrow initializer. Constructible ordinary functions, mutable, member, proxy, call-produced and asserted receiver values are excluded even when their callable type resembles a known implementation; inherited runtime metadata can change ordinary function dispatch. Exactly one actual parameter and no explicit this parameter are supported.",
|
|
1277
|
+
"Reached files containing actual JSX additionally require their compiler-owned implicit runtime import and the native module symbol's declaration owners. Known non-declaration runtime implementations are unsupported even when their bodies have no ordinary Object effects: a custom factory can reinterpret forwarded fields. External declaration files and owned top-level ambient module declarations in declaration files retain the explicit standard-React library assumption; those declarations do not prove the actual runtime JavaScript identity. Missing or ambiguous internal import metadata, missing native symbols, foreign owners and local nonambient declaration-module sources abstain. Non-JSX dependencies do not acquire a runtime edge merely because the compiler records an unused synthetic JSX import. Runtime rebinding outside the compiler-visible module context remains opaque, not validated by this proof.",
|
|
899
1278
|
"Requires target ES2015 or newer, explicit native ES-module output and the standard React automatic JSX runtime (react-jsx or react-jsxdev). Downlevel arrows become constructible functions; CommonJS exports remain mutable. Preserve/classic JSX, custom factories, namespaces, import sources and per-file JSX directives are unsupported. Imported library implementations and cross-project source redirects are opaque; relative imports within this program remain supported."
|
|
900
1279
|
],
|
|
901
1280
|
references: ["https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-props-no-spreading.md"],
|
|
902
1281
|
examples: [
|
|
903
1282
|
{ id: "excess-runtime-field", title: "An unrelated field is forwarded at runtime", outcome: "match", files: [EXAMPLE_JSX, { path: "src/avatar.tsx", source: "export {}; const Avatar = ({ displayName }: { displayName: string }) => <span>{displayName}</span>;\nconst avatar = <Avatar {...{ displayName: 'Ada', email: 'ada@example.test' }} />;" }, EXAMPLE_TSCONFIG], focusPath: "src/avatar.tsx", expectedCount: 1, public: true },
|
|
904
|
-
{ id: "explicit-fields", title: "Forward only the declared field", outcome: "no-match", files: [EXAMPLE_JSX, { path: "src/avatar.tsx", source: "export {}; const Avatar = ({ displayName }: { displayName: string }) => <span>{displayName}</span>;\nconst avatar = <Avatar displayName='Ada' />;" }, EXAMPLE_TSCONFIG], focusPath: "src/avatar.tsx", expectedCount: 0, public: true }
|
|
1283
|
+
{ id: "explicit-fields", title: "Forward only the declared field", outcome: "no-match", files: [EXAMPLE_JSX, { path: "src/avatar.tsx", source: "export {}; const Avatar = ({ displayName }: { displayName: string }) => <span>{displayName}</span>;\nconst avatar = <Avatar displayName='Ada' />;" }, EXAMPLE_TSCONFIG], focusPath: "src/avatar.tsx", expectedCount: 0, public: true },
|
|
1284
|
+
{ id: "asserted-source-alias", scenarioId: "source-provenance", title: "An asserted alias can still observe forwarded data", outcome: "no-match", files: [EXAMPLE_JSX, { path: "src/avatar.tsx", source: "export {}; let element: any; const opaque = {toString() {return element.props.email;}}; const name = opaque as unknown as string; const Avatar = ({displayName}: {displayName: string}) => <span>{`${displayName}`}</span>; element = <Avatar {...{displayName: name, email: 'needed'}}/>;" }, EXAMPLE_TSCONFIG], focusPath: "src/avatar.tsx", expectedCount: 0, public: true },
|
|
1285
|
+
{ id: "literal-source-alias", scenarioId: "source-provenance", title: "A proven primitive alias preserves the finding", outcome: "match", files: [EXAMPLE_JSX, { path: "src/avatar.tsx", source: "export {}; const name = 'Ada'; const Avatar = ({displayName}: {displayName: string}) => <span>{`${displayName}`}</span>; const element = <Avatar {...{displayName: name, email: 'unused'}}/>;" }, EXAMPLE_TSCONFIG], focusPath: "src/avatar.tsx", expectedCount: 1, public: true },
|
|
1286
|
+
{ id: "inherited-runtime-hook", scenarioId: "prototype-effects", title: "An inherited runtime hook can observe forwarded data", outcome: "no-match", files: [EXAMPLE_JSX, { path: "src/avatar.tsx", source: "export {}; let element: any; const Avatar = ({displayName}: {displayName: string}) => <span>{displayName}</span>; element = <Avatar {...{displayName: 'Ada', email: 'needed'}}/>; Object.defineProperty(Object.prototype, 'ref', {configurable: true, get() {Object.defineProperty(this, 'children', {configurable: true, value: element.props.email}); return null;}});" }, EXAMPLE_TSCONFIG], focusPath: "src/avatar.tsx", expectedCount: 0, public: true },
|
|
1287
|
+
{ id: "unrelated-runtime-object", scenarioId: "prototype-effects", title: "An unrelated own-property write preserves the finding", outcome: "match", files: [EXAMPLE_JSX, { path: "src/avatar.tsx", source: "export {}; const target = {ref: null}; target.ref = null; const Avatar = ({displayName}: {displayName: string}) => <span>{displayName}</span>; const element = <Avatar {...{displayName: 'Ada', email: 'unused'}}/>;" }, EXAMPLE_TSCONFIG], focusPath: "src/avatar.tsx", expectedCount: 1, public: true },
|
|
1288
|
+
{ id: "erased-callable-metadata", scenarioId: "callable-metadata", title: "Runtime metadata can observe an omitted field", outcome: "no-match", files: [EXAMPLE_JSX, { path: "src/avatar.tsx", source: "export {}; const target = {ref: 0}; const Avatar = ({displayName}: {displayName: string}) => <span>{displayName}</span>; (Avatar as unknown as {defaultProps: {email: string}}).defaultProps = {get email() {target.ref = 1; return 'fallback';}}; const element = <Avatar {...{displayName: 'Ada', email: 'needed'}}/>; const observation = target.ref; export {observation};" }, EXAMPLE_TSCONFIG], focusPath: "src/avatar.tsx", expectedCount: 0, public: true },
|
|
1289
|
+
{ id: "unrelated-object-metadata", scenarioId: "callable-metadata", title: "An unrelated data object's metadata preserves the finding", outcome: "match", files: [EXAMPLE_JSX, { path: "src/avatar.tsx", source: "export {}; const settings = {defaultProps: {email: 'fallback'}}; settings.defaultProps = {email: 'updated'}; const Avatar = ({displayName}: {displayName: string}) => <span>{displayName}</span>; const element = <Avatar {...{displayName: 'Ada', email: 'unused'}}/>;" }, EXAMPLE_TSCONFIG], focusPath: "src/avatar.tsx", expectedCount: 1, public: true },
|
|
1290
|
+
{ id: "consumed-scalar-inspection", scenarioId: "created-value", title: "A private element exposes only its consumed scalar", outcome: "match", files: [EXAMPLE_JSX, { path: "src/avatar.tsx", source: "export {}; const Avatar = ({displayName}: {displayName: string}) => <span>{displayName}</span>; const element = <Avatar {...{displayName: 'Ada', email: 'unused'}}/>; const summary = {displayName: (element as {props: {displayName: string}}).props.displayName}; export {summary};" }, EXAMPLE_TSCONFIG], focusPath: "src/avatar.tsx", expectedCount: 1, public: true },
|
|
1291
|
+
{ id: "opaque-element-consumer", scenarioId: "created-value", title: "An opaque consumer can observe or mutate element props", outcome: "no-match", files: [EXAMPLE_JSX, { path: "src/avatar.tsx", source: "export {}; declare function inspect(value: unknown): void; const Avatar = ({displayName}: {displayName: string}) => <span>{displayName}</span>; const element = <Avatar {...{displayName: 'Ada', email: 'needed'}}/>; inspect(element);" }, EXAMPLE_TSCONFIG], focusPath: "src/avatar.tsx", expectedCount: 0, public: true }
|
|
905
1292
|
]
|
|
906
1293
|
};
|
|
907
1294
|
var RESERVED_PROPS = /* @__PURE__ */ new Set(["key", "ref", "__self", "__source"]);
|
|
908
|
-
var ESM_MODULES = /* @__PURE__ */ new Set([
|
|
1295
|
+
var ESM_MODULES = /* @__PURE__ */ new Set([ts10.ModuleKind.ES2015, ts10.ModuleKind.ES2020, ts10.ModuleKind.ES2022, ts10.ModuleKind.ESNext]);
|
|
909
1296
|
var JSX_DIRECTIVE = /@jsx(?:ImportSource|Runtime|Frag)?(?:\s|$)/iu;
|
|
910
|
-
|
|
1297
|
+
var MAX_VALUE_DEPTH = 64;
|
|
1298
|
+
var PRIMITIVE_OPERATORS = /* @__PURE__ */ new Set([
|
|
1299
|
+
ts10.SyntaxKind.PlusToken,
|
|
1300
|
+
ts10.SyntaxKind.MinusToken,
|
|
1301
|
+
ts10.SyntaxKind.AsteriskToken,
|
|
1302
|
+
ts10.SyntaxKind.SlashToken,
|
|
1303
|
+
ts10.SyntaxKind.PercentToken,
|
|
1304
|
+
ts10.SyntaxKind.AsteriskAsteriskToken,
|
|
1305
|
+
ts10.SyntaxKind.LessThanToken,
|
|
1306
|
+
ts10.SyntaxKind.LessThanEqualsToken,
|
|
1307
|
+
ts10.SyntaxKind.GreaterThanToken,
|
|
1308
|
+
ts10.SyntaxKind.GreaterThanEqualsToken,
|
|
1309
|
+
ts10.SyntaxKind.EqualsEqualsEqualsToken,
|
|
1310
|
+
ts10.SyntaxKind.ExclamationEqualsEqualsToken,
|
|
1311
|
+
ts10.SyntaxKind.EqualsEqualsToken,
|
|
1312
|
+
ts10.SyntaxKind.ExclamationEqualsToken,
|
|
1313
|
+
ts10.SyntaxKind.AmpersandToken,
|
|
1314
|
+
ts10.SyntaxKind.BarToken,
|
|
1315
|
+
ts10.SyntaxKind.CaretToken,
|
|
1316
|
+
ts10.SyntaxKind.LessThanLessThanToken,
|
|
1317
|
+
ts10.SyntaxKind.GreaterThanGreaterThanToken,
|
|
1318
|
+
ts10.SyntaxKind.GreaterThanGreaterThanGreaterThanToken
|
|
1319
|
+
]);
|
|
1320
|
+
function plainLiteralFields(node) {
|
|
911
1321
|
const fields = /* @__PURE__ */ new Map();
|
|
912
1322
|
for (const property of node.properties) {
|
|
913
1323
|
if (property.type !== AST_NODE_TYPES8.Property || property.kind !== "init") return null;
|
|
@@ -917,20 +1327,27 @@ function literalFields(node) {
|
|
|
917
1327
|
else if (key.type === AST_NODE_TYPES8.Literal && (typeof key.value === "string" || typeof key.value === "number")) name = String(key.value);
|
|
918
1328
|
else return null;
|
|
919
1329
|
if (name === "__proto__") return null;
|
|
920
|
-
|
|
1330
|
+
fields.set(name, property);
|
|
1331
|
+
}
|
|
1332
|
+
return fields;
|
|
1333
|
+
}
|
|
1334
|
+
function literalFields(node) {
|
|
1335
|
+
const fields = plainLiteralFields(node);
|
|
1336
|
+
if (fields) {
|
|
1337
|
+
for (const name of fields.keys()) if (RESERVED_PROPS.has(name) || name.includes("-")) fields.delete(name);
|
|
921
1338
|
}
|
|
922
1339
|
return fields;
|
|
923
1340
|
}
|
|
924
1341
|
function receiverReads(signature, checker) {
|
|
925
1342
|
const declaration = signature.getDeclaration();
|
|
926
|
-
if (!declaration || !
|
|
1343
|
+
if (!declaration || !ts10.isArrowFunction(declaration) || declaration.modifiers?.some((modifier) => modifier.kind === ts10.SyntaxKind.AsyncKeyword) || signature.thisParameter || declaration.parameters.length !== 1) return null;
|
|
927
1344
|
const parameter = declaration.parameters[0];
|
|
928
1345
|
return parameter ? scalarParameterView(parameter, declaration.body, checker) : null;
|
|
929
1346
|
}
|
|
930
1347
|
function stableReceiver(tag, signature, checker, program, overrides) {
|
|
931
|
-
if (!
|
|
1348
|
+
if (!ts10.isIdentifier(tag)) return false;
|
|
932
1349
|
const initializer = immutableInitializer(tag, checker);
|
|
933
|
-
if (!initializer || initializer !== signature.getDeclaration() || !
|
|
1350
|
+
if (!initializer || initializer !== signature.getDeclaration() || !ts10.isArrowFunction(initializer)) return false;
|
|
934
1351
|
return supportedImplementation(initializer.getSourceFile(), tag.getSourceFile(), program, overrides);
|
|
935
1352
|
}
|
|
936
1353
|
function immutableInitializer(tag, checker) {
|
|
@@ -938,37 +1355,31 @@ function immutableInitializer(tag, checker) {
|
|
|
938
1355
|
const seen = /* @__PURE__ */ new Set();
|
|
939
1356
|
while (symbol && !seen.has(symbol)) {
|
|
940
1357
|
seen.add(symbol);
|
|
941
|
-
if ((symbol.flags &
|
|
1358
|
+
if ((symbol.flags & ts10.SymbolFlags.Alias) !== 0) {
|
|
942
1359
|
symbol = checker.getAliasedSymbol(symbol);
|
|
943
1360
|
continue;
|
|
944
1361
|
}
|
|
945
1362
|
const initializer = constInitializer(symbol.valueDeclaration);
|
|
946
|
-
if (!initializer || !
|
|
1363
|
+
if (!initializer || !ts10.isIdentifier(initializer)) return initializer;
|
|
947
1364
|
symbol = checker.getSymbolAtLocation(initializer);
|
|
948
1365
|
}
|
|
949
1366
|
return void 0;
|
|
950
1367
|
}
|
|
951
|
-
function constInitializer(declaration) {
|
|
952
|
-
if (!declaration || !ts7.isVariableDeclaration(declaration) || !ts7.isVariableDeclarationList(declaration.parent) || (declaration.parent.flags & ts7.NodeFlags.Const) === 0) return void 0;
|
|
953
|
-
let initializer = declaration.initializer;
|
|
954
|
-
while (initializer && ts7.isParenthesizedExpression(initializer)) initializer = initializer.expression;
|
|
955
|
-
return initializer;
|
|
956
|
-
}
|
|
957
1368
|
function supportedImplementation(source, caller, program, overrides) {
|
|
958
|
-
if (!
|
|
1369
|
+
if (!ts10.isExternalModule(source) || source.impliedNodeFormat === ts10.ModuleKind.CommonJS || program.isSourceFileFromExternalLibrary(source)) return false;
|
|
959
1370
|
if (source === caller) return true;
|
|
960
1371
|
if (program.getProjectReferences()?.length) return false;
|
|
961
|
-
if (!overrides.has(source)) overrides.set(source, (
|
|
1372
|
+
if (!overrides.has(source)) overrides.set(source, (ts10.getLeadingCommentRanges(source.text, 0) ?? []).some((range) => JSX_DIRECTIVE.test(source.text.slice(range.pos, range.end))));
|
|
962
1373
|
return !overrides.get(source);
|
|
963
1374
|
}
|
|
964
1375
|
function supportedJSX(options, comments) {
|
|
965
|
-
return (options.target ??
|
|
1376
|
+
return (options.target ?? ts10.ScriptTarget.ES5) >= ts10.ScriptTarget.ES2015 && ESM_MODULES.has(options.module ?? ts10.ModuleKind.None) && (options.jsx === ts10.JsxEmit.ReactJSX || options.jsx === ts10.JsxEmit.ReactJSXDev) && !options.jsxFactory && !options.reactNamespace && (!options.jsxImportSource || options.jsxImportSource === "react") && !comments.some((comment) => JSX_DIRECTIVE.test(comment.value));
|
|
966
1377
|
}
|
|
967
1378
|
function receivingContract(opening, services, checker, contracts) {
|
|
968
1379
|
const native = services.esTreeNodeToTSNodeMap.get(opening);
|
|
969
|
-
if (!
|
|
1380
|
+
if (!ts10.isJsxOpeningElement(native) && !ts10.isJsxSelfClosingElement(native)) return null;
|
|
970
1381
|
const receiver = checker.getTypeAtLocation(native.tagName);
|
|
971
|
-
const signatures = checker.getSignaturesOfType(receiver,
|
|
1382
|
+
const signatures = checker.getSignaturesOfType(receiver, ts10.SignatureKind.Call);
|
|
972
1383
|
const signature = signatures[0];
|
|
973
1384
|
if (receiver.isUnion() || signatures.length !== 1 || !signature || signature.typeParameters?.length) return null;
|
|
974
1385
|
const props = checker.getContextualType(native.attributes);
|
|
@@ -976,19 +1387,132 @@ function receivingContract(opening, services, checker, contracts) {
|
|
|
976
1387
|
if (!contracts.has(props)) contracts.set(props, closedObjectContract(props, checker));
|
|
977
1388
|
return contracts.get(props) ? { tag: native.tagName, signature, props } : null;
|
|
978
1389
|
}
|
|
979
|
-
function ownScalarReads(fields, reads,
|
|
1390
|
+
function ownScalarReads(fields, reads, proof) {
|
|
980
1391
|
for (const key of reads) {
|
|
981
1392
|
const field = fields.get(key);
|
|
982
1393
|
if (!field) return false;
|
|
983
|
-
|
|
984
|
-
if (!scalarType(checker.getTypeAtLocation(value), false)) return false;
|
|
1394
|
+
if (!primitiveValue(proof.services.esTreeNodeToTSNodeMap.get(field.value), proof, /* @__PURE__ */ new Set())) return false;
|
|
985
1395
|
}
|
|
986
1396
|
return true;
|
|
987
1397
|
}
|
|
988
|
-
function
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
return
|
|
1398
|
+
function primitiveValue(node, proof, active) {
|
|
1399
|
+
const value = unassertedValue(node);
|
|
1400
|
+
if (proof.values.has(value)) return true;
|
|
1401
|
+
if (active.has(value) || active.size >= MAX_VALUE_DEPTH) return false;
|
|
1402
|
+
active.add(value);
|
|
1403
|
+
const result = scalarType(proof.checker.getTypeAtLocation(value), false) && primitiveResult(value, proof, active);
|
|
1404
|
+
active.delete(value);
|
|
1405
|
+
if (result) proof.values.add(value);
|
|
1406
|
+
return result;
|
|
1407
|
+
}
|
|
1408
|
+
function primitiveResult(value, proof, active) {
|
|
1409
|
+
if (ts10.isStringLiteralLike(value) || ts10.isNumericLiteral(value) || ts10.isBigIntLiteral(value) || value.kind === ts10.SyntaxKind.TrueKeyword || value.kind === ts10.SyntaxKind.FalseKeyword || value.kind === ts10.SyntaxKind.NullKeyword) return true;
|
|
1410
|
+
if (ts10.isTemplateExpression(value)) return value.templateSpans.every((span) => primitiveValue(span.expression, proof, active));
|
|
1411
|
+
if (ts10.isTypeOfExpression(value)) return primitiveValue(value.expression, proof, active);
|
|
1412
|
+
if (ts10.isPrefixUnaryExpression(value)) return (value.operator === ts10.SyntaxKind.PlusToken || value.operator === ts10.SyntaxKind.MinusToken || value.operator === ts10.SyntaxKind.ExclamationToken || value.operator === ts10.SyntaxKind.TildeToken) && primitiveValue(value.operand, proof, active);
|
|
1413
|
+
if (ts10.isConditionalExpression(value)) return primitiveValue(value.condition, proof, active) && primitiveValue(value.whenTrue, proof, active) && primitiveValue(value.whenFalse, proof, active);
|
|
1414
|
+
if (ts10.isBinaryExpression(value)) {
|
|
1415
|
+
return (PRIMITIVE_OPERATORS.has(value.operatorToken.kind) || RETURNED_OPERANDS.has(value.operatorToken.kind) || value.operatorToken.kind === ts10.SyntaxKind.CommaToken) && primitiveValue(value.left, proof, active) && primitiveValue(value.right, proof, active);
|
|
1416
|
+
}
|
|
1417
|
+
if (ts10.isPropertyAccessExpression(value) || ts10.isElementAccessExpression(value)) return primitiveMember(value, proof, active);
|
|
1418
|
+
if (!ts10.isIdentifier(value)) return false;
|
|
1419
|
+
const symbol = ts10.isShorthandPropertyAssignment(value.parent) ? proof.checker.getShorthandAssignmentValueSymbol(value.parent) : proof.checker.getSymbolAtLocation(value);
|
|
1420
|
+
const initializer = symbol && (symbol.flags & ts10.SymbolFlags.Alias) === 0 ? constInitializer(symbol.valueDeclaration) : void 0;
|
|
1421
|
+
return initializer !== void 0 && initializer.getSourceFile() === value.getSourceFile() && primitiveValue(initializer, proof, active);
|
|
1422
|
+
}
|
|
1423
|
+
function primitiveMember(node, proof, active) {
|
|
1424
|
+
if (!proof.staticScope || !ts10.isIdentifier(node.expression)) return false;
|
|
1425
|
+
const key = ts10.isPropertyAccessExpression(node) ? node.name.text : node.argumentExpression && (ts10.isStringLiteralLike(node.argumentExpression) || ts10.isNumericLiteral(node.argumentExpression)) ? node.argumentExpression.text : void 0;
|
|
1426
|
+
const symbol = proof.checker.getSymbolAtLocation(node.expression);
|
|
1427
|
+
if (!symbol || key === void 0 || (symbol.flags & ts10.SymbolFlags.Alias) !== 0) return false;
|
|
1428
|
+
if (!proof.objects.has(symbol)) proof.objects.set(symbol, localObjectFields(symbol, node.getSourceFile(), proof));
|
|
1429
|
+
const field = proof.objects.get(symbol)?.get(key);
|
|
1430
|
+
return field !== void 0 && primitiveValue(proof.services.esTreeNodeToTSNodeMap.get(field.value), proof, active);
|
|
1431
|
+
}
|
|
1432
|
+
function localObjectFields(symbol, source, proof) {
|
|
1433
|
+
const native = symbol.valueDeclaration;
|
|
1434
|
+
const initial = constInitializer(native);
|
|
1435
|
+
const initializer = initial && unassertedValue(initial);
|
|
1436
|
+
if (!native || native.getSourceFile() !== source || !initializer || !ts10.isObjectLiteralExpression(initializer)) return null;
|
|
1437
|
+
const declaration = proof.services.tsNodeToESTreeNodeMap.get(native);
|
|
1438
|
+
const literal2 = proof.services.tsNodeToESTreeNodeMap.get(initializer);
|
|
1439
|
+
if (declaration.type !== AST_NODE_TYPES8.VariableDeclarator || declaration.parent.kind !== "const" || declaration.id.type !== AST_NODE_TYPES8.Identifier || literal2.type !== AST_NODE_TYPES8.ObjectExpression || declaration.parent.parent.type === AST_NODE_TYPES8.ExportNamedDeclaration) return null;
|
|
1440
|
+
const fields = plainLiteralFields(literal2);
|
|
1441
|
+
const binding3 = proof.sourceCode.getDeclaredVariables(declaration).find((variable) => variable.defs.some((definition) => definition.type === "Variable" && definition.node === declaration));
|
|
1442
|
+
if (!fields || !binding3 || binding3.defs.length !== 1 || !stableValueBinding(binding3, (reference) => {
|
|
1443
|
+
if (!reference.isReadOnly() || reference.isTypeReference) return false;
|
|
1444
|
+
const member3 = reference.identifier.parent;
|
|
1445
|
+
return member3.type === AST_NODE_TYPES8.MemberExpression && member3.object === reference.identifier && readonlyFieldValue(member3, fields);
|
|
1446
|
+
})) return null;
|
|
1447
|
+
return fields;
|
|
1448
|
+
}
|
|
1449
|
+
function staticMemberKey(member3) {
|
|
1450
|
+
const property = member3.property;
|
|
1451
|
+
return !member3.computed && property.type === AST_NODE_TYPES8.Identifier ? property.name : property.type === AST_NODE_TYPES8.Literal && (typeof property.value === "string" || typeof property.value === "number") ? String(property.value) : void 0;
|
|
1452
|
+
}
|
|
1453
|
+
function readonlyFieldValue(member3, fields) {
|
|
1454
|
+
const key = staticMemberKey(member3);
|
|
1455
|
+
if (key === void 0 || !fields.has(key)) return false;
|
|
1456
|
+
const parent = member3.parent;
|
|
1457
|
+
if (parent.type === AST_NODE_TYPES8.Property && parent.value === member3 && parent.parent.type === AST_NODE_TYPES8.ObjectExpression) {
|
|
1458
|
+
const object = parent.parent;
|
|
1459
|
+
const owner = object.parent;
|
|
1460
|
+
return owner.type === AST_NODE_TYPES8.JSXSpreadAttribute && owner.argument === object || owner.type === AST_NODE_TYPES8.VariableDeclarator && owner.init === object;
|
|
1461
|
+
}
|
|
1462
|
+
return parent.type === AST_NODE_TYPES8.JSXExpressionContainer && parent.expression === member3 || parent.type === AST_NODE_TYPES8.VariableDeclarator && parent.init === member3;
|
|
1463
|
+
}
|
|
1464
|
+
function privateElementDeclaration(opening) {
|
|
1465
|
+
const value = outerExpression(opening.parent);
|
|
1466
|
+
const declaration = value.parent;
|
|
1467
|
+
return declaration.type === AST_NODE_TYPES8.VariableDeclarator && declaration.init === value && declaration.id.type === AST_NODE_TYPES8.Identifier && declaration.parent.kind === "const" && declaration.parent.parent.type !== AST_NODE_TYPES8.ExportNamedDeclaration ? declaration : null;
|
|
1468
|
+
}
|
|
1469
|
+
function closedElementValue(opening, declaration, fields, reads, proof) {
|
|
1470
|
+
if (!proof.staticScope || !closedInvocation(opening, proof) || !constInitializer(proof.services.esTreeNodeToTSNodeMap.get(declaration))) return false;
|
|
1471
|
+
const binding3 = proof.sourceCode.getDeclaredVariables(declaration).find((variable) => variable.defs.some((definition) => definition.type === "Variable" && definition.node === declaration));
|
|
1472
|
+
const symbol = proof.checker.getSymbolAtLocation(proof.services.esTreeNodeToTSNodeMap.get(declaration.id));
|
|
1473
|
+
if (!symbol || proof.exports.has(symbol)) return false;
|
|
1474
|
+
return binding3 !== void 0 && binding3.defs.length === 1 && stableValueBinding(binding3, (reference) => {
|
|
1475
|
+
if (!reference.isReadOnly() || reference.isTypeReference || reference.from.variableScope !== binding3.scope.variableScope) return false;
|
|
1476
|
+
return consumedElementRead(reference.identifier, fields, reads);
|
|
1477
|
+
});
|
|
1478
|
+
}
|
|
1479
|
+
function closedInvocation(node, proof) {
|
|
1480
|
+
for (let scope = proof.sourceCode.getScope(node); scope; scope = scope.upper) {
|
|
1481
|
+
if (scope.type !== "function") continue;
|
|
1482
|
+
let closed = proof.invocations.get(scope);
|
|
1483
|
+
if (closed === void 0) {
|
|
1484
|
+
closed = independentInvocation(scope, proof);
|
|
1485
|
+
proof.invocations.set(scope, closed);
|
|
1486
|
+
}
|
|
1487
|
+
if (!closed) return false;
|
|
1488
|
+
}
|
|
1489
|
+
return true;
|
|
1490
|
+
}
|
|
1491
|
+
function independentInvocation(scope, proof) {
|
|
1492
|
+
const block = scope.block;
|
|
1493
|
+
if (block.type !== AST_NODE_TYPES8.ArrowFunctionExpression && block.type !== AST_NODE_TYPES8.FunctionDeclaration && block.type !== AST_NODE_TYPES8.FunctionExpression) return false;
|
|
1494
|
+
if (block.async || block.generator || scope.set.get("arguments")?.references.some((reference) => !typeOnlyReference(reference))) return false;
|
|
1495
|
+
for (const parameter of block.params) {
|
|
1496
|
+
if (parameter.type !== AST_NODE_TYPES8.Identifier || parameter.name === "this") return false;
|
|
1497
|
+
const binding3 = scope.set.get(parameter.name);
|
|
1498
|
+
if (!binding3 || binding3.references.some((reference) => !typeOnlyReference(reference))) return false;
|
|
1499
|
+
}
|
|
1500
|
+
return scope.through.every((reference) => {
|
|
1501
|
+
if (typeOnlyReference(reference)) return true;
|
|
1502
|
+
const value = outerExpression(reference.identifier);
|
|
1503
|
+
const parent = value.parent;
|
|
1504
|
+
const read = parent?.type === AST_NODE_TYPES8.MemberExpression && parent.object === value ? parent : value;
|
|
1505
|
+
return primitiveValue(proof.services.esTreeNodeToTSNodeMap.get(read), proof, /* @__PURE__ */ new Set());
|
|
1506
|
+
});
|
|
1507
|
+
}
|
|
1508
|
+
function consumedElementRead(node, fields, reads) {
|
|
1509
|
+
const identifier = outerExpression(node);
|
|
1510
|
+
const props = identifier.parent;
|
|
1511
|
+
if (!props || props.type !== AST_NODE_TYPES8.MemberExpression || props.object !== identifier || props.optional || staticMemberKey(props) !== "props") return false;
|
|
1512
|
+
const member3 = props.parent;
|
|
1513
|
+
if (member3.type !== AST_NODE_TYPES8.MemberExpression || member3.object !== props || member3.optional) return false;
|
|
1514
|
+
const key = staticMemberKey(member3);
|
|
1515
|
+
return key !== void 0 && reads.has(key) && readonlyFieldValue(member3, fields);
|
|
992
1516
|
}
|
|
993
1517
|
var no_excess_jsx_props_default = createRule({
|
|
994
1518
|
name: "no-excess-jsx-props",
|
|
@@ -1007,33 +1531,63 @@ var no_excess_jsx_props_default = createRule({
|
|
|
1007
1531
|
const contracts = /* @__PURE__ */ new WeakMap();
|
|
1008
1532
|
const receivers = /* @__PURE__ */ new WeakMap();
|
|
1009
1533
|
const overrides = /* @__PURE__ */ new WeakMap();
|
|
1534
|
+
let proof;
|
|
1535
|
+
let dynamic = false;
|
|
1536
|
+
const candidates = [];
|
|
1010
1537
|
let standardJSX;
|
|
1538
|
+
const evaluate = (node, declaration, fields) => {
|
|
1539
|
+
const keys = [...fields.keys()];
|
|
1540
|
+
const opening = node.parent;
|
|
1541
|
+
services ??= ESLintUtils4.getParserServices(context);
|
|
1542
|
+
standardJSX ??= supportedJSX(services.program.getCompilerOptions(), context.sourceCode.getAllComments());
|
|
1543
|
+
if (!standardJSX) return;
|
|
1544
|
+
const checker = services.program.getTypeChecker();
|
|
1545
|
+
if (objectContract2 === void 0) {
|
|
1546
|
+
const object = checker.resolveName("Object", void 0, ts10.SymbolFlags.Type, false);
|
|
1547
|
+
objectContract2 = object !== void 0 && closedObjectContract(checker.getDeclaredTypeOfSymbol(object), checker);
|
|
1548
|
+
}
|
|
1549
|
+
if (!objectContract2) return;
|
|
1550
|
+
const contract = receivingContract(opening, services, checker, contracts);
|
|
1551
|
+
if (!contract) return;
|
|
1552
|
+
const excess = keys.filter((key) => checker.getPropertyOfType(contract.props, key) === void 0).sort();
|
|
1553
|
+
if (!excess.length || !stableReceiver(contract.tag, contract.signature, checker, services.program, overrides)) return;
|
|
1554
|
+
const signature = contract.signature;
|
|
1555
|
+
if (!receivers.has(signature)) receivers.set(signature, receiverReads(signature, checker));
|
|
1556
|
+
const reads = receivers.get(signature);
|
|
1557
|
+
proof ??= {
|
|
1558
|
+
checker,
|
|
1559
|
+
services,
|
|
1560
|
+
sourceCode: context.sourceCode,
|
|
1561
|
+
staticScope: !dynamic,
|
|
1562
|
+
exports: exportedSymbols(services.esTreeNodeToTSNodeMap.get(context.sourceCode.ast), checker),
|
|
1563
|
+
values: /* @__PURE__ */ new WeakSet(),
|
|
1564
|
+
objects: /* @__PURE__ */ new WeakMap(),
|
|
1565
|
+
invocations: /* @__PURE__ */ new WeakMap()
|
|
1566
|
+
};
|
|
1567
|
+
if (!reads || !ownScalarReads(fields, reads, proof) || !closedElementValue(opening, declaration, fields, reads, proof)) return;
|
|
1568
|
+
const implementation = signature.getDeclaration();
|
|
1569
|
+
if (!implementation || ordinaryObjectEffects(services.program, contract.tag.getSourceFile()) || ordinaryObjectEffects(services.program, implementation.getSourceFile())) return;
|
|
1570
|
+
context.report({ node, messageId: "excess", data: { fields: excess.join(", ") } });
|
|
1571
|
+
};
|
|
1011
1572
|
return {
|
|
1012
1573
|
JSXSpreadAttribute(node) {
|
|
1013
1574
|
if (node.argument.type !== AST_NODE_TYPES8.ObjectExpression) return;
|
|
1014
|
-
const fields = literalFields(node.argument);
|
|
1015
|
-
if (!fields?.size) return;
|
|
1016
|
-
const keys = [...fields.keys()];
|
|
1017
1575
|
const opening = node.parent;
|
|
1018
1576
|
if (!opening.selfClosing || opening.attributes.length !== 1 || opening.name.type !== AST_NODE_TYPES8.JSXIdentifier || /^[a-z]/u.test(opening.name.name)) return;
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
if (!
|
|
1030
|
-
|
|
1031
|
-
if (!
|
|
1032
|
-
const
|
|
1033
|
-
if (!receivers.has(signature)) receivers.set(signature, receiverReads(signature, checker));
|
|
1034
|
-
const reads = receivers.get(signature);
|
|
1035
|
-
if (!reads || !ownScalarReads(fields, reads, services, checker)) return;
|
|
1036
|
-
context.report({ node, messageId: "excess", data: { fields: excess.join(", ") } });
|
|
1577
|
+
const declaration = privateElementDeclaration(opening);
|
|
1578
|
+
if (!declaration) return;
|
|
1579
|
+
const fields = literalFields(node.argument);
|
|
1580
|
+
if (!fields?.size) return;
|
|
1581
|
+
candidates.push({ node, declaration, fields });
|
|
1582
|
+
},
|
|
1583
|
+
CallExpression(node) {
|
|
1584
|
+
if (directEval(node)) dynamic = true;
|
|
1585
|
+
},
|
|
1586
|
+
"Program:exit"() {
|
|
1587
|
+
if (!candidates.length) return;
|
|
1588
|
+
services = ESLintUtils4.getParserServices(context);
|
|
1589
|
+
if (!currentNativeSource(context.sourceCode, services)) return;
|
|
1590
|
+
for (const { node, declaration, fields } of candidates) evaluate(node, declaration, fields);
|
|
1037
1591
|
}
|
|
1038
1592
|
};
|
|
1039
1593
|
}
|
|
@@ -1533,7 +2087,7 @@ function isSearchParamReceiver(call, services) {
|
|
|
1533
2087
|
// package.json
|
|
1534
2088
|
var package_default = {
|
|
1535
2089
|
name: "@sarj/eslint-plugin",
|
|
1536
|
-
version: "16.32.
|
|
2090
|
+
version: "16.32.3",
|
|
1537
2091
|
packageManager: "npm@12.2.1",
|
|
1538
2092
|
description: "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
|
|
1539
2093
|
type: "module",
|
|
@@ -1659,29 +2213,29 @@ import {
|
|
|
1659
2213
|
AST_NODE_TYPES as AST_NODE_TYPES14,
|
|
1660
2214
|
ESLintUtils as ESLintUtils6
|
|
1661
2215
|
} from "@typescript-eslint/utils";
|
|
1662
|
-
import * as
|
|
2216
|
+
import * as ts12 from "typescript";
|
|
1663
2217
|
|
|
1664
2218
|
// src/rules/_closed-nominal-inheritance-fix.ts
|
|
1665
2219
|
import {
|
|
1666
2220
|
AST_NODE_TYPES as AST_NODE_TYPES13,
|
|
1667
2221
|
ASTUtils as ASTUtils4
|
|
1668
2222
|
} from "@typescript-eslint/utils";
|
|
1669
|
-
import
|
|
2223
|
+
import ts11 from "typescript";
|
|
1670
2224
|
function closedNominalInheritanceFix(sourceCode, call, consumer, implementation, contract) {
|
|
1671
2225
|
const source = call.getSourceFile();
|
|
1672
2226
|
if (source.text !== sourceCode.text || source.statements.length !== 5 || sourceCode.getAllComments().length > 0 || [consumer, implementation, contract].some(
|
|
1673
2227
|
(node) => node.getSourceFile() !== source
|
|
1674
2228
|
))
|
|
1675
2229
|
return null;
|
|
1676
|
-
const markers = source.statements.filter(
|
|
2230
|
+
const markers = source.statements.filter(ts11.isExportDeclaration);
|
|
1677
2231
|
if (markers.length !== 1 || markers[0] === void 0 || !emptyModuleMarker(markers[0]))
|
|
1678
2232
|
return null;
|
|
1679
2233
|
const statements = source.statements.filter(
|
|
1680
|
-
(node) => !
|
|
2234
|
+
(node) => !ts11.isExportDeclaration(node)
|
|
1681
2235
|
);
|
|
1682
|
-
if (statements[0] !== contract || statements[1] !== consumer || statements[2] !== implementation || statements[3] === void 0 || !
|
|
2236
|
+
if (statements[0] !== contract || statements[1] !== consumer || statements[2] !== implementation || statements[3] === void 0 || !ts11.isExpressionStatement(statements[3]) || statements[3].expression !== call)
|
|
1683
2237
|
return null;
|
|
1684
|
-
if (!plainClass(contract,
|
|
2238
|
+
if (!plainClass(contract, ts11.SyntaxKind.AbstractKeyword) || !plainClass(consumer, null) || !plainClass(implementation, null) || contract.name === void 0 || consumer.name === void 0 || implementation.name === void 0 || (/* @__PURE__ */ new Set([contract.name.text, consumer.name.text, implementation.name.text])).size !== 3)
|
|
1685
2239
|
return null;
|
|
1686
2240
|
const method = emptyContractMethod(contract);
|
|
1687
2241
|
if (method === null || !emptyImplementation(implementation, method) || !exactConsumer(sourceCode, consumer, contract.name.text) || !exactConstruction(call, consumer.name.text, implementation.name.text))
|
|
@@ -1694,47 +2248,47 @@ function closedNominalInheritanceFix(sourceCode, call, consumer, implementation,
|
|
|
1694
2248
|
);
|
|
1695
2249
|
}
|
|
1696
2250
|
function emptyModuleMarker(node) {
|
|
1697
|
-
return !node.isTypeOnly && node.moduleSpecifier === void 0 && node.attributes === void 0 && node.exportClause !== void 0 &&
|
|
2251
|
+
return !node.isTypeOnly && node.moduleSpecifier === void 0 && node.attributes === void 0 && node.exportClause !== void 0 && ts11.isNamedExports(node.exportClause) && node.exportClause.elements.length === 0;
|
|
1698
2252
|
}
|
|
1699
2253
|
function plainClass(node, modifier) {
|
|
1700
|
-
const modifiers =
|
|
1701
|
-
return node.name !== void 0 && node.typeParameters === void 0 && node.heritageClauses === void 0 && (
|
|
2254
|
+
const modifiers = ts11.getModifiers(node) ?? [];
|
|
2255
|
+
return node.name !== void 0 && node.typeParameters === void 0 && node.heritageClauses === void 0 && (ts11.getDecorators(node)?.length ?? 0) === 0 && modifiers.length === (modifier === null ? 0 : 1) && (modifier === null || modifiers[0]?.kind === modifier);
|
|
1702
2256
|
}
|
|
1703
2257
|
function emptyContractMethod(node) {
|
|
1704
2258
|
const method = node.members[0];
|
|
1705
|
-
if (node.members.length !== 1 || method === void 0 || !
|
|
2259
|
+
if (node.members.length !== 1 || method === void 0 || !ts11.isMethodDeclaration(method) || !ts11.isIdentifier(method.name) || method.name.text === "constructor" || method.parameters.length !== 0 || method.typeParameters !== void 0 || method.questionToken !== void 0 || method.asteriskToken !== void 0 || method.body !== void 0 || method.type?.kind !== ts11.SyntaxKind.VoidKeyword || method.modifiers?.length !== 1 || method.modifiers[0]?.kind !== ts11.SyntaxKind.AbstractKeyword)
|
|
1706
2260
|
return null;
|
|
1707
2261
|
return method.name.text;
|
|
1708
2262
|
}
|
|
1709
2263
|
function emptyImplementation(node, key) {
|
|
1710
2264
|
const method = node.members[0];
|
|
1711
|
-
return node.members.length === 1 && method !== void 0 &&
|
|
2265
|
+
return node.members.length === 1 && method !== void 0 && ts11.isMethodDeclaration(method) && ts11.isIdentifier(method.name) && method.name.text === key && method.parameters.length === 0 && method.typeParameters === void 0 && method.questionToken === void 0 && method.asteriskToken === void 0 && method.modifiers === void 0 && (method.type === void 0 || method.type.kind === ts11.SyntaxKind.VoidKeyword) && method.body?.statements.length === 0;
|
|
1712
2266
|
}
|
|
1713
2267
|
function exactConsumer(sourceCode, consumer, base) {
|
|
1714
2268
|
const constructor = consumer.members[0];
|
|
1715
|
-
if (consumer.members.length !== 1 || constructor === void 0 || !
|
|
2269
|
+
if (consumer.members.length !== 1 || constructor === void 0 || !ts11.isConstructorDeclaration(constructor) || constructor.modifiers !== void 0 || constructor.parameters.length !== 1 || constructor.body?.statements.length !== 1)
|
|
1716
2270
|
return false;
|
|
1717
2271
|
const parameter = constructor.parameters[0];
|
|
1718
|
-
if (parameter === void 0 || !
|
|
2272
|
+
if (parameter === void 0 || !ts11.isIdentifier(parameter.name) || parameter.name.text === base || parameter.initializer !== void 0 || parameter.questionToken !== void 0 || parameter.dotDotDotToken !== void 0 || parameter.modifiers?.length !== 1 || parameter.modifiers[0]?.kind !== ts11.SyntaxKind.ReadonlyKeyword || parameter.type === void 0 || !ts11.isTypeReferenceNode(parameter.type) || !ts11.isIdentifier(parameter.type.typeName) || parameter.type.typeName.text !== base || parameter.type.typeArguments !== void 0)
|
|
1719
2273
|
return false;
|
|
1720
2274
|
const guard = constructor.body.statements[0];
|
|
1721
|
-
if (guard === void 0 || !
|
|
2275
|
+
if (guard === void 0 || !ts11.isIfStatement(guard) || guard.elseStatement !== void 0)
|
|
1722
2276
|
return false;
|
|
1723
2277
|
const condition2 = unparenthesized(guard.expression);
|
|
1724
|
-
if (!
|
|
2278
|
+
if (!ts11.isPrefixUnaryExpression(condition2) || condition2.operator !== ts11.SyntaxKind.ExclamationToken)
|
|
1725
2279
|
return false;
|
|
1726
2280
|
const comparison2 = unparenthesized(condition2.operand);
|
|
1727
|
-
return
|
|
2281
|
+
return ts11.isBinaryExpression(comparison2) && comparison2.operatorToken.kind === ts11.SyntaxKind.InstanceOfKeyword && ts11.isIdentifier(comparison2.left) && comparison2.left.text === parameter.name.text && ts11.isIdentifier(comparison2.right) && comparison2.right.text === base && exactRejection(sourceCode, guard.thenStatement);
|
|
1728
2282
|
}
|
|
1729
2283
|
function unparenthesized(node) {
|
|
1730
2284
|
let expression = node;
|
|
1731
|
-
while (
|
|
2285
|
+
while (ts11.isParenthesizedExpression(expression))
|
|
1732
2286
|
expression = expression.expression;
|
|
1733
2287
|
return expression;
|
|
1734
2288
|
}
|
|
1735
2289
|
function exactRejection(sourceCode, statement) {
|
|
1736
|
-
const rejected =
|
|
1737
|
-
if (rejected === void 0 || !
|
|
2290
|
+
const rejected = ts11.isBlock(statement) && statement.statements.length === 1 ? statement.statements[0] : statement;
|
|
2291
|
+
if (rejected === void 0 || !ts11.isThrowStatement(rejected) || rejected.expression === void 0 || !ts11.isNewExpression(rejected.expression) || !ts11.isIdentifier(rejected.expression.expression) || rejected.expression.expression.text !== "TypeError" || rejected.expression.typeArguments !== void 0 || rejected.expression.arguments?.length !== 1 || rejected.expression.arguments[0] === void 0 || !ts11.isStringLiteral(rejected.expression.arguments[0]))
|
|
1738
2292
|
return false;
|
|
1739
2293
|
const identifier = sourceCode.getNodeByRangeIndex(
|
|
1740
2294
|
rejected.expression.expression.getStart()
|
|
@@ -1742,14 +2296,15 @@ function exactRejection(sourceCode, statement) {
|
|
|
1742
2296
|
return identifier?.type === AST_NODE_TYPES13.Identifier && identifier.name === "TypeError" && (ASTUtils4.findVariable(sourceCode.getScope(identifier), identifier.name)?.defs.length ?? 0) === 0;
|
|
1743
2297
|
}
|
|
1744
2298
|
function exactConstruction(node, consumer, implementation) {
|
|
1745
|
-
if (!
|
|
2299
|
+
if (!ts11.isIdentifier(node.expression) || node.expression.text !== consumer || node.typeArguments !== void 0 || node.arguments?.length !== 1)
|
|
1746
2300
|
return false;
|
|
1747
2301
|
const argument = node.arguments[0];
|
|
1748
|
-
return argument !== void 0 &&
|
|
2302
|
+
return argument !== void 0 && ts11.isNewExpression(argument) && ts11.isIdentifier(argument.expression) && argument.expression.text === implementation && argument.typeArguments === void 0 && argument.arguments?.length === 0;
|
|
1749
2303
|
}
|
|
1750
2304
|
|
|
1751
2305
|
// src/rules/require-explicit-contract-implementation.ts
|
|
1752
2306
|
var ESCAPED_CLASSES = /* @__PURE__ */ new WeakMap();
|
|
2307
|
+
var PROTOTYPE_MUTATIONS = /* @__PURE__ */ new WeakMap();
|
|
1753
2308
|
var REQUIRE_EXPLICIT_CONTRACT_IMPLEMENTATION_DOCUMENTATION = {
|
|
1754
2309
|
defaultLevel: "error",
|
|
1755
2310
|
summary: "Require nominal inheritance when an injected abstract class is rejected by an instanceof guard.",
|
|
@@ -1814,19 +2369,23 @@ var REQUIRE_EXPLICIT_CONTRACT_IMPLEMENTATION_DOCUMENTATION = {
|
|
|
1814
2369
|
]
|
|
1815
2370
|
};
|
|
1816
2371
|
function hasPrototypeMutation(source) {
|
|
2372
|
+
const cached = PROTOTYPE_MUTATIONS.get(source);
|
|
2373
|
+
if (cached !== void 0) return cached;
|
|
1817
2374
|
function visit(node) {
|
|
1818
2375
|
const member3 = memberName(node);
|
|
1819
2376
|
if (member3 === "setPrototypeOf" || member3 === "__proto__" || member3 === "hasInstance")
|
|
1820
2377
|
return true;
|
|
1821
|
-
if (
|
|
2378
|
+
if (ts12.isBinaryExpression(node) && node.operatorToken.kind >= ts12.SyntaxKind.FirstAssignment && node.operatorToken.kind <= ts12.SyntaxKind.LastAssignment && memberName(node.left) === "prototype")
|
|
1822
2379
|
return true;
|
|
1823
|
-
return
|
|
2380
|
+
return ts12.forEachChild(node, visit);
|
|
1824
2381
|
}
|
|
1825
|
-
|
|
2382
|
+
const mutated = visit(source) === true;
|
|
2383
|
+
PROTOTYPE_MUTATIONS.set(source, mutated);
|
|
2384
|
+
return mutated;
|
|
1826
2385
|
}
|
|
1827
2386
|
function memberName(node) {
|
|
1828
|
-
if (
|
|
1829
|
-
if (
|
|
2387
|
+
if (ts12.isPropertyAccessExpression(node)) return node.name.text;
|
|
2388
|
+
if (ts12.isElementAccessExpression(node) && ts12.isStringLiteralLike(node.argumentExpression))
|
|
1830
2389
|
return node.argumentExpression.text;
|
|
1831
2390
|
return null;
|
|
1832
2391
|
}
|
|
@@ -1843,11 +2402,11 @@ function escapedClasses(program, checker, cwd) {
|
|
|
1843
2402
|
const escaped = /* @__PURE__ */ new Set();
|
|
1844
2403
|
const namespaceValues = /* @__PURE__ */ new Map();
|
|
1845
2404
|
function visit(node) {
|
|
1846
|
-
if (
|
|
1847
|
-
if (
|
|
2405
|
+
if (ts12.isTypeNode(node) || ts12.isImportDeclaration(node)) return;
|
|
2406
|
+
if (ts12.isIdentifier(node) || ts12.isPropertyAccessExpression(node) || ts12.isElementAccessExpression(node)) {
|
|
1848
2407
|
recordEscapedReference(checker, node, escaped, namespaceValues, cwd);
|
|
1849
2408
|
}
|
|
1850
|
-
|
|
2409
|
+
ts12.forEachChild(node, visit);
|
|
1851
2410
|
}
|
|
1852
2411
|
for (const source of program.getSourceFiles())
|
|
1853
2412
|
if (ownedSource(source, cwd)) visit(source);
|
|
@@ -1866,7 +2425,7 @@ function recordEscapedReference(checker, node, escaped, namespaceValues, cwd) {
|
|
|
1866
2425
|
if (!namespacePrefix(symbol, node) && !safeClassReference(node))
|
|
1867
2426
|
for (const value of values) escaped.add(value);
|
|
1868
2427
|
}
|
|
1869
|
-
if (
|
|
2428
|
+
if (ts12.isElementAccessExpression(node) && !safeClassReference(node)) {
|
|
1870
2429
|
const receiver = canonicalSymbol(checker, node.expression) ?? checker.getTypeAtLocation(node.expression).getSymbol();
|
|
1871
2430
|
if (receiver !== void 0)
|
|
1872
2431
|
for (const value of ownedClassValues(checker, receiver, cwd))
|
|
@@ -1874,16 +2433,16 @@ function recordEscapedReference(checker, node, escaped, namespaceValues, cwd) {
|
|
|
1874
2433
|
}
|
|
1875
2434
|
}
|
|
1876
2435
|
function ownedClassValues(checker, original, cwd, seen = /* @__PURE__ */ new Set()) {
|
|
1877
|
-
const symbol = original.flags &
|
|
2436
|
+
const symbol = original.flags & ts12.SymbolFlags.Alias ? checker.getAliasedSymbol(original) : original;
|
|
1878
2437
|
const values = /* @__PURE__ */ new Set();
|
|
1879
2438
|
if (seen.has(symbol)) return values;
|
|
1880
2439
|
seen.add(symbol);
|
|
1881
2440
|
if (symbol.declarations?.some(
|
|
1882
|
-
(declaration) =>
|
|
2441
|
+
(declaration) => ts12.isClassDeclaration(declaration) && ownedSource(declaration.getSourceFile(), cwd)
|
|
1883
2442
|
))
|
|
1884
2443
|
values.add(symbol);
|
|
1885
2444
|
if (symbol.declarations?.some(
|
|
1886
|
-
(declaration) => (
|
|
2445
|
+
(declaration) => (ts12.isSourceFile(declaration) || ts12.isModuleDeclaration(declaration)) && ownedSource(declaration.getSourceFile(), cwd)
|
|
1887
2446
|
)) {
|
|
1888
2447
|
for (const exported of checker.getExportsOfModule(symbol)) {
|
|
1889
2448
|
for (const value of ownedClassValues(checker, exported, cwd, seen))
|
|
@@ -1893,16 +2452,16 @@ function ownedClassValues(checker, original, cwd, seen = /* @__PURE__ */ new Set
|
|
|
1893
2452
|
return values;
|
|
1894
2453
|
}
|
|
1895
2454
|
function safeClassReference(node) {
|
|
1896
|
-
let reference =
|
|
1897
|
-
while (
|
|
2455
|
+
let reference = ts12.isPropertyAccessExpression(node.parent) && node.parent.name === node ? node.parent : node;
|
|
2456
|
+
while (ts12.isParenthesizedExpression(reference.parent))
|
|
1898
2457
|
reference = reference.parent;
|
|
1899
2458
|
const parent = reference.parent;
|
|
1900
|
-
return
|
|
2459
|
+
return ts12.isClassDeclaration(parent) && parent.name === reference || ts12.isNewExpression(parent) && parent.expression === reference || ts12.isExpressionWithTypeArguments(parent) && parent.expression === reference || ts12.isBinaryExpression(parent) && parent.operatorToken.kind === ts12.SyntaxKind.InstanceOfKeyword && parent.right === reference;
|
|
1901
2460
|
}
|
|
1902
2461
|
function namespacePrefix(symbol, node) {
|
|
1903
2462
|
const parent = node.parent;
|
|
1904
|
-
const memberCall = (
|
|
1905
|
-
return !symbol.declarations?.some(
|
|
2463
|
+
const memberCall = (ts12.isPropertyAccessExpression(parent) || ts12.isElementAccessExpression(parent)) && ts12.isCallExpression(parent.parent) && parent.parent.expression === parent;
|
|
2464
|
+
return !symbol.declarations?.some(ts12.isClassDeclaration) && (ts12.isPropertyAccessExpression(parent) || ts12.isElementAccessExpression(parent)) && parent.expression === node && !memberCall;
|
|
1906
2465
|
}
|
|
1907
2466
|
function closedNominalBoundary(program, checker, call, consumer, missing, cwd) {
|
|
1908
2467
|
const { implementation, contractSymbol } = missing;
|
|
@@ -1910,7 +2469,7 @@ function closedNominalBoundary(program, checker, call, consumer, missing, cwd) {
|
|
|
1910
2469
|
const consumerSymbol = consumer.name === void 0 ? void 0 : canonicalSymbol(checker, consumer.name);
|
|
1911
2470
|
if (implementationSymbol === void 0 || consumerSymbol === void 0)
|
|
1912
2471
|
return false;
|
|
1913
|
-
const contract = contractSymbol.declarations?.find(
|
|
2472
|
+
const contract = contractSymbol.declarations?.find(ts12.isClassDeclaration);
|
|
1914
2473
|
if (contract === void 0) return false;
|
|
1915
2474
|
const targets = /* @__PURE__ */ new Set([
|
|
1916
2475
|
consumerSymbol,
|
|
@@ -1932,12 +2491,12 @@ function classHierarchySymbols(checker, declaration, seen = /* @__PURE__ */ new
|
|
|
1932
2491
|
if (symbol === void 0 || seen.has(symbol)) return seen;
|
|
1933
2492
|
seen.add(symbol);
|
|
1934
2493
|
for (const clause of declaration.heritageClauses ?? []) {
|
|
1935
|
-
if (clause.token !==
|
|
2494
|
+
if (clause.token !== ts12.SyntaxKind.ExtendsKeyword) continue;
|
|
1936
2495
|
for (const parent of clause.types) {
|
|
1937
2496
|
const ancestor = canonicalSymbol(
|
|
1938
2497
|
checker,
|
|
1939
2498
|
parent.expression
|
|
1940
|
-
)?.declarations?.find(
|
|
2499
|
+
)?.declarations?.find(ts12.isClassDeclaration);
|
|
1941
2500
|
if (ancestor !== void 0)
|
|
1942
2501
|
classHierarchySymbols(checker, ancestor, seen);
|
|
1943
2502
|
}
|
|
@@ -1962,22 +2521,22 @@ function missingImplementation(checker, signature, parameter, call, argument) {
|
|
|
1962
2521
|
function behavioralContract(checker, type) {
|
|
1963
2522
|
if (type.isUnion()) {
|
|
1964
2523
|
const substantive = type.types.filter(
|
|
1965
|
-
(member3) => (member3.flags & (
|
|
2524
|
+
(member3) => (member3.flags & (ts12.TypeFlags.Null | ts12.TypeFlags.Undefined)) === 0
|
|
1966
2525
|
);
|
|
1967
2526
|
if (substantive.length !== 1) return null;
|
|
1968
2527
|
return behavioralContract(checker, substantive[0]);
|
|
1969
2528
|
}
|
|
1970
|
-
if ((type.flags & (
|
|
2529
|
+
if ((type.flags & (ts12.TypeFlags.Any | ts12.TypeFlags.Unknown)) !== 0)
|
|
1971
2530
|
return null;
|
|
1972
2531
|
const declaration = type.getSymbol()?.declarations?.find(
|
|
1973
|
-
(item) =>
|
|
1974
|
-
(modifier) => modifier.kind ===
|
|
2532
|
+
(item) => ts12.isClassDeclaration(item) && item.modifiers?.some(
|
|
2533
|
+
(modifier) => modifier.kind === ts12.SyntaxKind.AbstractKeyword
|
|
1975
2534
|
)
|
|
1976
2535
|
);
|
|
1977
2536
|
if (declaration === void 0) return null;
|
|
1978
2537
|
return checker.getPropertiesOfType(type).some((property) => {
|
|
1979
2538
|
if (!property.declarations?.some(
|
|
1980
|
-
(member3) =>
|
|
2539
|
+
(member3) => ts12.isMethodSignature(member3) || ts12.isMethodDeclaration(member3)
|
|
1981
2540
|
))
|
|
1982
2541
|
return false;
|
|
1983
2542
|
const propertyType = checker.getTypeOfSymbolAtLocation(
|
|
@@ -1988,15 +2547,15 @@ function behavioralContract(checker, type) {
|
|
|
1988
2547
|
}) ? type : null;
|
|
1989
2548
|
}
|
|
1990
2549
|
function ownedClass(checker, expression) {
|
|
1991
|
-
if (!
|
|
2550
|
+
if (!ts12.isNewExpression(expression)) return null;
|
|
1992
2551
|
const type = checker.getTypeAtLocation(expression);
|
|
1993
|
-
if ((type.flags & (
|
|
2552
|
+
if ((type.flags & (ts12.TypeFlags.Any | ts12.TypeFlags.Unknown)) !== 0)
|
|
1994
2553
|
return null;
|
|
1995
|
-
const declaration = type.getSymbol()?.declarations?.find(
|
|
2554
|
+
const declaration = type.getSymbol()?.declarations?.find(ts12.isClassDeclaration);
|
|
1996
2555
|
const constructed = canonicalSymbol(
|
|
1997
2556
|
checker,
|
|
1998
2557
|
expression.expression
|
|
1999
|
-
)?.declarations?.find(
|
|
2558
|
+
)?.declarations?.find(ts12.isClassDeclaration);
|
|
2000
2559
|
if (declaration === void 0 || declaration !== constructed || declaration.getSourceFile().isDeclarationFile || /(?:^|[/\\])(?:node_modules|vendor|generated)(?:[/\\])/u.test(
|
|
2001
2560
|
declaration.getSourceFile().fileName
|
|
2002
2561
|
))
|
|
@@ -2004,10 +2563,10 @@ function ownedClass(checker, expression) {
|
|
|
2004
2563
|
return declaration;
|
|
2005
2564
|
}
|
|
2006
2565
|
function nominallyInherits(checker, declaration, target, seen) {
|
|
2007
|
-
if (
|
|
2566
|
+
if (ts12.canHaveDecorators(declaration) && ts12.getDecorators(declaration)?.length)
|
|
2008
2567
|
return null;
|
|
2009
2568
|
if (hasPrototypeMutation(declaration.getSourceFile()) || declaration.members.some(
|
|
2010
|
-
(member3) =>
|
|
2569
|
+
(member3) => ts12.isConstructorDeclaration(member3) || ts12.isClassStaticBlockDeclaration(member3) || ts12.isPropertyDeclaration(member3) && member3.initializer !== void 0
|
|
2011
2570
|
))
|
|
2012
2571
|
return null;
|
|
2013
2572
|
const symbol = declaration.name === void 0 ? void 0 : canonicalSymbol(checker, declaration.name);
|
|
@@ -2016,60 +2575,60 @@ function nominallyInherits(checker, declaration, target, seen) {
|
|
|
2016
2575
|
seen.add(symbol);
|
|
2017
2576
|
}
|
|
2018
2577
|
const parents = declaration.heritageClauses?.find(
|
|
2019
|
-
(clause) => clause.token ===
|
|
2578
|
+
(clause) => clause.token === ts12.SyntaxKind.ExtendsKeyword
|
|
2020
2579
|
)?.types;
|
|
2021
2580
|
if (parents === void 0) return false;
|
|
2022
2581
|
if (parents.length !== 1) return null;
|
|
2023
2582
|
const parentSymbol = canonicalSymbol(checker, parents[0].expression);
|
|
2024
2583
|
if (parentSymbol === void 0) return null;
|
|
2025
2584
|
if (parentSymbol === target) return true;
|
|
2026
|
-
const inherited = parentSymbol.declarations?.find(
|
|
2585
|
+
const inherited = parentSymbol.declarations?.find(ts12.isClassDeclaration);
|
|
2027
2586
|
return inherited === void 0 ? null : nominallyInherits(checker, inherited, target, new Set(seen));
|
|
2028
2587
|
}
|
|
2029
2588
|
function hasNominalRejectionGuard(checker, signature, parameter, contract) {
|
|
2030
2589
|
const declaration = signature.getDeclaration();
|
|
2031
|
-
if (declaration === void 0 || !
|
|
2590
|
+
if (declaration === void 0 || !ts12.isConstructorDeclaration(declaration))
|
|
2032
2591
|
return false;
|
|
2033
|
-
if (
|
|
2592
|
+
if (ts12.canHaveDecorators(declaration.parent) && ts12.getDecorators(declaration.parent)?.length)
|
|
2034
2593
|
return false;
|
|
2035
2594
|
if (hasPrototypeMutation(declaration.getSourceFile())) return false;
|
|
2036
2595
|
const first = declaration.body?.statements[0];
|
|
2037
|
-
if (first === void 0 || !
|
|
2596
|
+
if (first === void 0 || !ts12.isIfStatement(first) || !alwaysThrows(first.thenStatement))
|
|
2038
2597
|
return false;
|
|
2039
2598
|
const condition2 = unparenthesized2(first.expression);
|
|
2040
|
-
if (!
|
|
2599
|
+
if (!ts12.isPrefixUnaryExpression(condition2) || condition2.operator !== ts12.SyntaxKind.ExclamationToken)
|
|
2041
2600
|
return false;
|
|
2042
2601
|
const comparison2 = unparenthesized2(condition2.operand);
|
|
2043
|
-
if (!
|
|
2602
|
+
if (!ts12.isBinaryExpression(comparison2) || comparison2.operatorToken.kind !== ts12.SyntaxKind.InstanceOfKeyword)
|
|
2044
2603
|
return false;
|
|
2045
2604
|
if (canonicalSymbol(checker, comparison2.left) !== parameter || canonicalSymbol(checker, comparison2.right) !== contract)
|
|
2046
2605
|
return false;
|
|
2047
|
-
const target = contract.declarations?.find(
|
|
2606
|
+
const target = contract.declarations?.find(ts12.isClassDeclaration);
|
|
2048
2607
|
return target !== void 0 && hasOrdinaryInstanceCheck(checker, target, /* @__PURE__ */ new Set());
|
|
2049
2608
|
}
|
|
2050
2609
|
function unparenthesized2(expression) {
|
|
2051
2610
|
let current = expression;
|
|
2052
|
-
while (
|
|
2611
|
+
while (ts12.isParenthesizedExpression(current)) current = current.expression;
|
|
2053
2612
|
return current;
|
|
2054
2613
|
}
|
|
2055
2614
|
function alwaysThrows(statement) {
|
|
2056
|
-
return
|
|
2615
|
+
return ts12.isThrowStatement(statement) || ts12.isBlock(statement) && statement.statements.length === 1 && ts12.isThrowStatement(statement.statements[0]);
|
|
2057
2616
|
}
|
|
2058
2617
|
function hasOrdinaryInstanceCheck(checker, declaration, seen) {
|
|
2059
|
-
if (seen.has(declaration) ||
|
|
2618
|
+
if (seen.has(declaration) || ts12.getDecorators(declaration)?.length || hasPrototypeMutation(declaration.getSourceFile()) || declaration.members.some(ts12.isClassStaticBlockDeclaration))
|
|
2060
2619
|
return false;
|
|
2061
2620
|
seen.add(declaration);
|
|
2062
2621
|
if (declaration.members.some(
|
|
2063
|
-
(member3) => member3.name !== void 0 &&
|
|
2622
|
+
(member3) => member3.name !== void 0 && ts12.isComputedPropertyName(member3.name) && ts12.canHaveModifiers(member3) && ts12.getModifiers(member3)?.some((modifier) => modifier.kind === ts12.SyntaxKind.StaticKeyword)
|
|
2064
2623
|
))
|
|
2065
2624
|
return false;
|
|
2066
2625
|
for (const clause of declaration.heritageClauses ?? []) {
|
|
2067
|
-
if (clause.token !==
|
|
2626
|
+
if (clause.token !== ts12.SyntaxKind.ExtendsKeyword) continue;
|
|
2068
2627
|
for (const parent of clause.types) {
|
|
2069
2628
|
const ancestor = canonicalSymbol(
|
|
2070
2629
|
checker,
|
|
2071
2630
|
parent.expression
|
|
2072
|
-
)?.declarations?.find(
|
|
2631
|
+
)?.declarations?.find(ts12.isClassDeclaration);
|
|
2073
2632
|
if (ancestor === void 0 || !hasOrdinaryInstanceCheck(checker, ancestor, seen))
|
|
2074
2633
|
return false;
|
|
2075
2634
|
}
|
|
@@ -2077,9 +2636,9 @@ function hasOrdinaryInstanceCheck(checker, declaration, seen) {
|
|
|
2077
2636
|
return true;
|
|
2078
2637
|
}
|
|
2079
2638
|
function canonicalSymbol(checker, node) {
|
|
2080
|
-
if (
|
|
2639
|
+
if (ts12.isParenthesizedExpression(node)) node = unparenthesized2(node);
|
|
2081
2640
|
const symbol = checker.getSymbolAtLocation(node);
|
|
2082
|
-
return symbol === void 0 ? void 0 : (symbol.flags &
|
|
2641
|
+
return symbol === void 0 ? void 0 : (symbol.flags & ts12.SymbolFlags.Alias) !== 0 ? checker.getAliasedSymbol(symbol) : symbol;
|
|
2083
2642
|
}
|
|
2084
2643
|
var require_explicit_contract_implementation_default = createRule({
|
|
2085
2644
|
name: "require-explicit-contract-implementation",
|
|
@@ -2104,11 +2663,11 @@ var require_explicit_contract_implementation_default = createRule({
|
|
|
2104
2663
|
const checker = services.program.getTypeChecker();
|
|
2105
2664
|
function inspect(node) {
|
|
2106
2665
|
const tsNode = services.esTreeNodeToTSNodeMap.get(node);
|
|
2107
|
-
if (!
|
|
2666
|
+
if (!ts12.isNewExpression(tsNode)) return;
|
|
2108
2667
|
const consumer = canonicalSymbol(
|
|
2109
2668
|
checker,
|
|
2110
2669
|
tsNode.expression
|
|
2111
|
-
)?.declarations?.find(
|
|
2670
|
+
)?.declarations?.find(ts12.isClassDeclaration);
|
|
2112
2671
|
if (consumer === void 0) return;
|
|
2113
2672
|
const signature = checker.getResolvedSignature(tsNode);
|
|
2114
2673
|
if (signature === void 0 || signature.getDeclaration()?.parent !== consumer)
|
|
@@ -2136,7 +2695,7 @@ var require_explicit_contract_implementation_default = createRule({
|
|
|
2136
2695
|
))
|
|
2137
2696
|
continue;
|
|
2138
2697
|
const contract = missing.contractSymbol.declarations?.find(
|
|
2139
|
-
|
|
2698
|
+
ts12.isClassDeclaration
|
|
2140
2699
|
);
|
|
2141
2700
|
context.report({
|
|
2142
2701
|
node: argument,
|
|
@@ -3437,7 +3996,7 @@ import {
|
|
|
3437
3996
|
ASTUtils as ASTUtils7,
|
|
3438
3997
|
ESLintUtils as ESLintUtils7
|
|
3439
3998
|
} from "@typescript-eslint/utils";
|
|
3440
|
-
import
|
|
3999
|
+
import ts13 from "typescript";
|
|
3441
4000
|
var PREFER_TYPED_REFLECTION_DOCUMENTATION = {
|
|
3442
4001
|
summary: "Prefer typed access when Reflect.get or Reflect.apply discards a known contract.",
|
|
3443
4002
|
rationale: "Reflect.get and Reflect.apply can accept property or argument mistakes that normal typed access catches.",
|
|
@@ -3490,7 +4049,7 @@ var PREFER_TYPED_REFLECTION_DOCUMENTATION = {
|
|
|
3490
4049
|
};
|
|
3491
4050
|
function knownType(type) {
|
|
3492
4051
|
if (type.isUnion()) return type.types.every(knownType);
|
|
3493
|
-
return (type.flags & (
|
|
4052
|
+
return (type.flags & (ts13.TypeFlags.Any | ts13.TypeFlags.Unknown | ts13.TypeFlags.TypeParameter | ts13.TypeFlags.Never)) === 0;
|
|
3494
4053
|
}
|
|
3495
4054
|
var prefer_typed_reflection_default = createRule({
|
|
3496
4055
|
name: "prefer-typed-reflection",
|
|
@@ -3542,7 +4101,7 @@ var prefer_typed_reflection_default = createRule({
|
|
|
3542
4101
|
const key = unwrapExpression(writtenKey);
|
|
3543
4102
|
const name = staticString(key) ?? (key.type === AST_NODE_TYPES18.Literal && typeof key.value === "number" ? String(key.value) : null);
|
|
3544
4103
|
const members = type.isUnion() ? type.types : [type];
|
|
3545
|
-
if (name === null || !members.every((member3) => (member3.flags &
|
|
4104
|
+
if (name === null || !members.every((member3) => (member3.flags & ts13.TypeFlags.Object) !== 0 && checker.getPropertyOfType(member3, name) !== void 0)) return null;
|
|
3546
4105
|
return `(${context.sourceCode.getText(target)})[${context.sourceCode.getText(writtenKey)}]`;
|
|
3547
4106
|
};
|
|
3548
4107
|
return {
|
|
@@ -3570,7 +4129,7 @@ import {
|
|
|
3570
4129
|
AST_NODE_TYPES as AST_NODE_TYPES20,
|
|
3571
4130
|
ESLintUtils as ESLintUtils8
|
|
3572
4131
|
} from "@typescript-eslint/utils";
|
|
3573
|
-
import
|
|
4132
|
+
import ts14 from "typescript";
|
|
3574
4133
|
|
|
3575
4134
|
// src/rules/_unused-private-binding.ts
|
|
3576
4135
|
import { AST_NODE_TYPES as AST_NODE_TYPES19 } from "@typescript-eslint/utils";
|
|
@@ -3671,21 +4230,21 @@ var NO_BROAD_RETURN_TYPE_DOCUMENTATION = {
|
|
|
3671
4230
|
]
|
|
3672
4231
|
};
|
|
3673
4232
|
function isBroad(type, checker) {
|
|
3674
|
-
if ((type.flags & (
|
|
4233
|
+
if ((type.flags & (ts14.TypeFlags.Unknown | ts14.TypeFlags.NonPrimitive)) !== 0)
|
|
3675
4234
|
return true;
|
|
3676
4235
|
const indexes = checker.getIndexInfosOfType(type);
|
|
3677
|
-
return indexes.length > 0 && type.getProperties().length === 0 && indexes.every((index) => (index.type.flags &
|
|
4236
|
+
return indexes.length > 0 && type.getProperties().length === 0 && indexes.every((index) => (index.type.flags & ts14.TypeFlags.Unknown) !== 0);
|
|
3678
4237
|
}
|
|
3679
4238
|
function hasKnownContract(type, checker) {
|
|
3680
4239
|
if (type.isUnion())
|
|
3681
4240
|
return type.types.every((part) => hasKnownContract(part, checker));
|
|
3682
|
-
const excluded =
|
|
4241
|
+
const excluded = ts14.TypeFlags.Any | ts14.TypeFlags.Unknown | ts14.TypeFlags.Never | ts14.TypeFlags.TypeParameter | ts14.TypeFlags.Conditional | ts14.TypeFlags.IndexedAccess | ts14.TypeFlags.Substitution | ts14.TypeFlags.Null | ts14.TypeFlags.Undefined | ts14.TypeFlags.Void;
|
|
3683
4242
|
if ((type.flags & excluded) !== 0 || isBroad(type, checker)) return false;
|
|
3684
|
-
return (type.flags &
|
|
4243
|
+
return (type.flags & ts14.TypeFlags.Object) === 0 || type.getProperties().length > 0;
|
|
3685
4244
|
}
|
|
3686
4245
|
function isOpaque(type, checker) {
|
|
3687
4246
|
if (type.isUnion()) return type.types.some((part) => isOpaque(part, checker));
|
|
3688
|
-
return (type.flags & (
|
|
4247
|
+
return (type.flags & (ts14.TypeFlags.Any | ts14.TypeFlags.Unknown | ts14.TypeFlags.TypeParameter | ts14.TypeFlags.Conditional | ts14.TypeFlags.IndexedAccess | ts14.TypeFlags.Substitution)) !== 0 || isBroad(type, checker);
|
|
3689
4248
|
}
|
|
3690
4249
|
var no_broad_return_type_default = createRule({
|
|
3691
4250
|
name: "no-broad-return-type",
|
|
@@ -3712,7 +4271,7 @@ var no_broad_return_type_default = createRule({
|
|
|
3712
4271
|
const type = checker.getTypeAtLocation(
|
|
3713
4272
|
services.esTreeNodeToTSNodeMap.get(node)
|
|
3714
4273
|
);
|
|
3715
|
-
return (type.flags &
|
|
4274
|
+
return (type.flags & ts14.TypeFlags.TypeParameter) !== 0 ? type : checker.getAwaitedType(type) ?? type;
|
|
3716
4275
|
};
|
|
3717
4276
|
const inspectReturn = (value) => {
|
|
3718
4277
|
const frame = frames.at(-1);
|
|
@@ -3761,7 +4320,7 @@ import {
|
|
|
3761
4320
|
ASTUtils as ASTUtils9,
|
|
3762
4321
|
ESLintUtils as ESLintUtils9
|
|
3763
4322
|
} from "@typescript-eslint/utils";
|
|
3764
|
-
import
|
|
4323
|
+
import ts15 from "typescript";
|
|
3765
4324
|
|
|
3766
4325
|
// src/rules/_literal-identity-reduce-fix.ts
|
|
3767
4326
|
import {
|
|
@@ -3924,7 +4483,7 @@ var no_reduce_accumulator_copy_default = createRule({
|
|
|
3924
4483
|
services.esTreeNodeToTSNodeMap.get(node)
|
|
3925
4484
|
);
|
|
3926
4485
|
const declaration = signature?.declaration;
|
|
3927
|
-
if (!declaration || !program.isSourceFileDefaultLibrary(declaration.getSourceFile()) || !
|
|
4486
|
+
if (!declaration || !program.isSourceFileDefaultLibrary(declaration.getSourceFile()) || !ts15.isInterfaceDeclaration(declaration.parent) || !["Array", "ReadonlyArray"].includes(declaration.parent.name.text))
|
|
3928
4487
|
return;
|
|
3929
4488
|
const accumulator = context.sourceCode.getDeclaredVariables(callback).find((variable) => variable.identifiers.includes(parameter));
|
|
3930
4489
|
if (!accumulator || accumulator.references.some((reference) => reference.isWrite()))
|
|
@@ -3986,7 +4545,7 @@ var no_reduce_accumulator_copy_default = createRule({
|
|
|
3986
4545
|
|
|
3987
4546
|
// src/rules/no-known-value-widening.ts
|
|
3988
4547
|
import { AST_NODE_TYPES as AST_NODE_TYPES23, ESLintUtils as ESLintUtils10 } from "@typescript-eslint/utils";
|
|
3989
|
-
import
|
|
4548
|
+
import ts16 from "typescript";
|
|
3990
4549
|
var NO_KNOWN_VALUE_WIDENING_DOCUMENTATION = {
|
|
3991
4550
|
summary: "Preserve a known value's contract instead of widening a local binding to unknown, object, or an unknown-valued dictionary.",
|
|
3992
4551
|
rationale: "Erasing a typed value's fields forces downstream code to rediscover the same contract through casts, reflection, or representation checks.",
|
|
@@ -4013,13 +4572,13 @@ var NO_KNOWN_VALUE_WIDENING_DOCUMENTATION = {
|
|
|
4013
4572
|
]
|
|
4014
4573
|
};
|
|
4015
4574
|
function erasesContract(type, checker) {
|
|
4016
|
-
if ((type.flags & (
|
|
4575
|
+
if ((type.flags & (ts16.TypeFlags.Unknown | ts16.TypeFlags.NonPrimitive)) !== 0) return true;
|
|
4017
4576
|
const indexes = checker.getIndexInfosOfType(type);
|
|
4018
|
-
return indexes.length > 0 && checker.getPropertiesOfType(type).length === 0 && indexes.every((index) => (index.type.flags &
|
|
4577
|
+
return indexes.length > 0 && checker.getPropertiesOfType(type).length === 0 && indexes.every((index) => (index.type.flags & ts16.TypeFlags.Unknown) !== 0);
|
|
4019
4578
|
}
|
|
4020
4579
|
function hasUnknownContract(type, checker) {
|
|
4021
4580
|
if (type.isUnionOrIntersection()) return type.types.some((part) => hasUnknownContract(part, checker));
|
|
4022
|
-
return (type.flags & (
|
|
4581
|
+
return (type.flags & (ts16.TypeFlags.Any | ts16.TypeFlags.Unknown | ts16.TypeFlags.Never | ts16.TypeFlags.TypeParameter | ts16.TypeFlags.Conditional | ts16.TypeFlags.IndexedAccess | ts16.TypeFlags.Substitution)) !== 0 || erasesContract(type, checker);
|
|
4023
4582
|
}
|
|
4024
4583
|
var no_known_value_widening_default = createRule({
|
|
4025
4584
|
name: "no-known-value-widening",
|
|
@@ -4061,7 +4620,7 @@ var no_known_value_widening_default = createRule({
|
|
|
4061
4620
|
// src/rules/no-invalid-typed-mutation.ts
|
|
4062
4621
|
import { ASTUtils as ASTUtils10, AST_NODE_TYPES as AST_NODE_TYPES24, ESLintUtils as ESLintUtils11 } from "@typescript-eslint/utils";
|
|
4063
4622
|
import { isObjectType, isTypeReference } from "ts-api-utils";
|
|
4064
|
-
import
|
|
4623
|
+
import ts17 from "typescript";
|
|
4065
4624
|
var NO_INVALID_TYPED_MUTATION_DOCUMENTATION = {
|
|
4066
4625
|
summary: "Keep native object mutation APIs from writing incompatible values into declared property types.",
|
|
4067
4626
|
rationale: "Object.assign, Reflect.set and property descriptors accept values that a normal typed property assignment rejects. They can invalidate a domain object's contract while subsequent reads retain its original type.",
|
|
@@ -4219,21 +4778,21 @@ function keepsMutableDescriptor(call, method) {
|
|
|
4219
4778
|
function declaredTargetType(node, checker) {
|
|
4220
4779
|
const symbol = checker.getSymbolAtLocation(node);
|
|
4221
4780
|
const declaration = symbol?.valueDeclaration;
|
|
4222
|
-
if (declaration === void 0 || !(
|
|
4781
|
+
if (declaration === void 0 || !(ts17.isVariableDeclaration(declaration) || ts17.isParameter(declaration)) || declaration.type === void 0) return void 0;
|
|
4223
4782
|
const type = checker.getTypeFromTypeNode(declaration.type);
|
|
4224
|
-
if (!definiteType(type, checker) || type.isUnionOrIntersection() || (type.flags &
|
|
4783
|
+
if (!definiteType(type, checker) || type.isUnionOrIntersection() || (type.flags & ts17.TypeFlags.Object) === 0 || checker.getIndexInfosOfType(type).length > 0 || type.getCallSignatures().length > 0 || type.getConstructSignatures().length > 0) return void 0;
|
|
4225
4784
|
return type;
|
|
4226
4785
|
}
|
|
4227
4786
|
function typedDataProperty(property) {
|
|
4228
4787
|
const declarations = property.getDeclarations();
|
|
4229
|
-
return declarations !== void 0 && declarations.length === 1 && declarations.every((declaration) => (
|
|
4788
|
+
return declarations !== void 0 && declarations.length === 1 && declarations.every((declaration) => (ts17.isPropertySignature(declaration) || ts17.isPropertyDeclaration(declaration)) && declaration.type !== void 0);
|
|
4230
4789
|
}
|
|
4231
4790
|
function propertyWriteType(target, property, node, checker, exact) {
|
|
4232
4791
|
const exposed = checker.getTypeOfSymbolAtLocation(property, node);
|
|
4233
|
-
if (!exact || (property.flags &
|
|
4234
|
-
if ((target.aliasTypeArguments?.length ?? 0) > 0 || isTypeReference(target) && checker.getTypeArguments(target).length > 0 || isObjectType(target) && (target.objectFlags & (
|
|
4792
|
+
if (!exact || (property.flags & ts17.SymbolFlags.Optional) === 0 || (property.flags & ts17.SymbolFlags.Transient) !== 0) return exposed;
|
|
4793
|
+
if ((target.aliasTypeArguments?.length ?? 0) > 0 || isTypeReference(target) && checker.getTypeArguments(target).length > 0 || isObjectType(target) && (target.objectFlags & (ts17.ObjectFlags.Mapped | ts17.ObjectFlags.Instantiated)) !== 0) return exposed;
|
|
4235
4794
|
const declaration = property.getDeclarations()?.[0];
|
|
4236
|
-
if (declaration === void 0 || !(
|
|
4795
|
+
if (declaration === void 0 || !(ts17.isPropertySignature(declaration) || ts17.isPropertyDeclaration(declaration)) || declaration.questionToken === void 0 || declaration.type === void 0) return exposed;
|
|
4237
4796
|
const authored = checker.getTypeFromTypeNode(declaration.type);
|
|
4238
4797
|
return definiteType(authored, checker) && checker.isTypeAssignableTo(authored, exposed) ? authored : exposed;
|
|
4239
4798
|
}
|
|
@@ -4241,13 +4800,13 @@ function definiteType(type, checker, seen = /* @__PURE__ */ new Set()) {
|
|
|
4241
4800
|
if (seen.has(type)) return true;
|
|
4242
4801
|
if (seen.size >= 32) return false;
|
|
4243
4802
|
seen.add(type);
|
|
4244
|
-
const unsafe =
|
|
4803
|
+
const unsafe = ts17.TypeFlags.Any | ts17.TypeFlags.Unknown | ts17.TypeFlags.Never | ts17.TypeFlags.TypeParameter | ts17.TypeFlags.Conditional | ts17.TypeFlags.IndexedAccess | ts17.TypeFlags.Substitution;
|
|
4245
4804
|
if ((type.flags & unsafe) !== 0) return false;
|
|
4246
4805
|
if (type.isUnionOrIntersection()) return type.types.every((part) => definiteType(part, checker, seen));
|
|
4247
4806
|
const arguments_ = isTypeReference(type) ? checker.getTypeArguments(type) : type.aliasTypeArguments ?? [];
|
|
4248
4807
|
if (!arguments_.every((argument) => definiteType(argument, checker, seen))) return false;
|
|
4249
4808
|
if (!definiteSignatures(type, checker, seen)) return false;
|
|
4250
|
-
if (isTypeReference(type) || (type.flags &
|
|
4809
|
+
if (isTypeReference(type) || (type.flags & ts17.TypeFlags.Object) === 0) return true;
|
|
4251
4810
|
return type.getProperties().every((property) => {
|
|
4252
4811
|
const declaration = property.valueDeclaration ?? property.getDeclarations()?.[0];
|
|
4253
4812
|
return declaration !== void 0 && definiteType(checker.getTypeOfSymbolAtLocation(property, declaration), checker, seen);
|
|
@@ -4331,33 +4890,33 @@ function plainProperties(node) {
|
|
|
4331
4890
|
|
|
4332
4891
|
// src/rules/no-contradictory-type-predicate.ts
|
|
4333
4892
|
import { ASTUtils as ASTUtils12, AST_NODE_TYPES as AST_NODE_TYPES26, ESLintUtils as ESLintUtils12 } from "@typescript-eslint/utils";
|
|
4334
|
-
import
|
|
4893
|
+
import ts20 from "typescript";
|
|
4335
4894
|
|
|
4336
4895
|
// src/rules/_has-separate-predicate-contract.ts
|
|
4337
|
-
import
|
|
4896
|
+
import ts18 from "typescript";
|
|
4338
4897
|
function hasSeparatePredicateContract(node, checker) {
|
|
4339
|
-
if (
|
|
4340
|
-
if (!
|
|
4898
|
+
if (ts18.isFunctionExpression(node) || ts18.isArrowFunction(node)) return checker.getContextualType(node) !== void 0;
|
|
4899
|
+
if (!ts18.isFunctionDeclaration(node) && !ts18.isMethodDeclaration(node)) return true;
|
|
4341
4900
|
if (node.name !== void 0 && (checker.getSymbolAtLocation(node.name)?.getDeclarations()?.length ?? 0) > 1) return true;
|
|
4342
|
-
if (!
|
|
4901
|
+
if (!ts18.isMethodDeclaration(node)) return false;
|
|
4343
4902
|
const owner = node.parent;
|
|
4344
|
-
if (
|
|
4345
|
-
return (
|
|
4903
|
+
if (ts18.isObjectLiteralExpression(owner)) return checker.getContextualType(owner) !== void 0;
|
|
4904
|
+
return (ts18.isClassDeclaration(owner) || ts18.isClassExpression(owner)) && (owner.heritageClauses?.length ?? 0) > 0;
|
|
4346
4905
|
}
|
|
4347
4906
|
|
|
4348
4907
|
// src/rules/_contradictory-array-predicate.ts
|
|
4349
4908
|
import { AST_NODE_TYPES as AST_NODE_TYPES25, ASTUtils as ASTUtils11 } from "@typescript-eslint/utils";
|
|
4350
|
-
import
|
|
4909
|
+
import ts19 from "typescript";
|
|
4351
4910
|
import { isTypeReference as isTypeReference2 } from "ts-api-utils";
|
|
4352
4911
|
var HOST_GLOBALS = ["globalThis", "window", "self", "global"];
|
|
4353
|
-
var PRIMITIVE_ELEMENTS =
|
|
4354
|
-
var
|
|
4912
|
+
var PRIMITIVE_ELEMENTS = ts19.TypeFlags.String | ts19.TypeFlags.Number | ts19.TypeFlags.Boolean | ts19.TypeFlags.BigInt | ts19.TypeFlags.ESSymbol;
|
|
4913
|
+
var OBJECT_REFLECTION2 = /* @__PURE__ */ new Set(["getPrototypeOf", "getOwnPropertyDescriptor", "getOwnPropertyDescriptors", "prototype", "constructor", "__proto__"]);
|
|
4355
4914
|
function contradictoryArrayPredicate(sourceCode, services) {
|
|
4356
4915
|
const checker = services.program.getTypeChecker();
|
|
4357
4916
|
const stable2 = /* @__PURE__ */ new WeakMap();
|
|
4358
4917
|
let constructorCapability = false;
|
|
4359
4918
|
function matches(expression, parameter, input, target) {
|
|
4360
|
-
if ((input.flags &
|
|
4919
|
+
if ((input.flags & ts19.TypeFlags.Unknown) === 0 || !plainPrimitiveArray(target, checker)) return false;
|
|
4361
4920
|
const call = unwrapExpression(expression);
|
|
4362
4921
|
if (call.type !== AST_NODE_TYPES25.CallExpression || call.optional || call.arguments.length !== 1) return false;
|
|
4363
4922
|
const argument = call.arguments[0];
|
|
@@ -4385,7 +4944,7 @@ function contradictoryArrayPredicate(sourceCode, services) {
|
|
|
4385
4944
|
function plainPrimitiveArray(target, checker) {
|
|
4386
4945
|
if (!checker.isArrayType(target) || !isTypeReference2(target)) return false;
|
|
4387
4946
|
const [element] = checker.getTypeArguments(target);
|
|
4388
|
-
return element !== void 0 && (element.flags & PRIMITIVE_ELEMENTS) !== 0 && (element.flags & (
|
|
4947
|
+
return element !== void 0 && (element.flags & PRIMITIVE_ELEMENTS) !== 0 && (element.flags & (ts19.TypeFlags.Enum | ts19.TypeFlags.EnumLiteral | ts19.TypeFlags.Intersection)) === 0;
|
|
4389
4948
|
}
|
|
4390
4949
|
function nativeBinding(identifier, sourceCode) {
|
|
4391
4950
|
const binding3 = ASTUtils11.findVariable(sourceCode.getScope(identifier), identifier.name);
|
|
@@ -4417,7 +4976,7 @@ function ordinaryObjectUse(node) {
|
|
|
4417
4976
|
const member3 = node.parent;
|
|
4418
4977
|
if (member3?.type !== AST_NODE_TYPES25.MemberExpression || member3.object !== node) return false;
|
|
4419
4978
|
const name = ASTUtils11.getPropertyName(member3);
|
|
4420
|
-
return name !== null && !
|
|
4979
|
+
return name !== null && !OBJECT_REFLECTION2.has(name);
|
|
4421
4980
|
}
|
|
4422
4981
|
function ordinaryArrayReference(reference) {
|
|
4423
4982
|
if (reference.isWrite()) return false;
|
|
@@ -4450,11 +5009,11 @@ function ordinaryHostReference(reference) {
|
|
|
4450
5009
|
// src/rules/no-contradictory-type-predicate.ts
|
|
4451
5010
|
var RUNTIME_KINDS = /* @__PURE__ */ new Set(["string", "number", "bigint", "boolean", "symbol", "undefined", "object", "function"]);
|
|
4452
5011
|
var PRIMITIVE_KINDS = [
|
|
4453
|
-
[
|
|
4454
|
-
[
|
|
4455
|
-
[
|
|
4456
|
-
[
|
|
4457
|
-
[
|
|
5012
|
+
[ts20.TypeFlags.String, "string"],
|
|
5013
|
+
[ts20.TypeFlags.Number, "number"],
|
|
5014
|
+
[ts20.TypeFlags.BigInt, "bigint"],
|
|
5015
|
+
[ts20.TypeFlags.ESSymbol, "symbol"],
|
|
5016
|
+
[ts20.TypeFlags.Undefined, "undefined"]
|
|
4458
5017
|
];
|
|
4459
5018
|
var NO_CONTRADICTORY_TYPE_PREDICATE_DOCUMENTATION = {
|
|
4460
5019
|
summary: "Keep explicit type predicates consistent with their primitive or native array membership check.",
|
|
@@ -4555,10 +5114,10 @@ var no_contradictory_type_predicate_default = createRule({
|
|
|
4555
5114
|
}
|
|
4556
5115
|
});
|
|
4557
5116
|
function contradiction(input, target, checked, checker, strictNulls) {
|
|
4558
|
-
if (strictNulls && checked === "object" && (target.flags &
|
|
5117
|
+
if (strictNulls && checked === "object" && (target.flags & ts20.TypeFlags.NonPrimitive) !== 0 && admitsNull(input)) return "nullAccepted";
|
|
4559
5118
|
const possible = inputKinds(input, checker);
|
|
4560
5119
|
if (possible === void 0 || !possible.has(checked)) return void 0;
|
|
4561
|
-
if ((target.flags &
|
|
5120
|
+
if ((target.flags & ts20.TypeFlags.Never) !== 0) return "contradictoryPredicate";
|
|
4562
5121
|
const promised = primitiveKinds(target, checker, false);
|
|
4563
5122
|
if (promised !== void 0) {
|
|
4564
5123
|
return !promised.has(checked) || [...promised].some((kind) => kind !== checked && possible.has(kind)) ? "contradictoryPredicate" : void 0;
|
|
@@ -4566,18 +5125,18 @@ function contradiction(input, target, checked, checker, strictNulls) {
|
|
|
4566
5125
|
return closedLiteralContradiction(input, target, checked, checker) ? "closedLiteralPredicate" : void 0;
|
|
4567
5126
|
}
|
|
4568
5127
|
function admitsNull(input) {
|
|
4569
|
-
return (input.flags &
|
|
5128
|
+
return (input.flags & ts20.TypeFlags.Unknown) !== 0 || (input.isUnion() ? input.types : [input]).some((member3) => (member3.flags & ts20.TypeFlags.Null) !== 0);
|
|
4570
5129
|
}
|
|
4571
5130
|
function closedLiteralContradiction(input, target, checked, checker) {
|
|
4572
5131
|
const members = target.isUnion() ? target.types : [target];
|
|
4573
|
-
const literalFlags =
|
|
5132
|
+
const literalFlags = ts20.TypeFlags.StringLiteral | ts20.TypeFlags.NumberLiteral | ts20.TypeFlags.BigIntLiteral | ts20.TypeFlags.BooleanLiteral | ts20.TypeFlags.Null | ts20.TypeFlags.Undefined;
|
|
4574
5133
|
if (!members.every((member3) => (member3.flags & literalFlags) !== 0)) return false;
|
|
4575
5134
|
if (members.some((member3) => literalKind(member3, checker) !== checked)) return true;
|
|
4576
|
-
if ((input.flags &
|
|
5135
|
+
if ((input.flags & ts20.TypeFlags.Unknown) !== 0) return checked !== "undefined";
|
|
4577
5136
|
return (input.isUnion() ? input.types : [input]).some((member3) => literalKind(member3, checker) === checked && !checker.isTypeAssignableTo(member3, target));
|
|
4578
5137
|
}
|
|
4579
5138
|
function literalKind(type, checker) {
|
|
4580
|
-
if ((type.flags &
|
|
5139
|
+
if ((type.flags & ts20.TypeFlags.BooleanLiteral) !== 0) return "boolean";
|
|
4581
5140
|
return primitiveKinds(type, checker, true)?.values().next().value;
|
|
4582
5141
|
}
|
|
4583
5142
|
function singleReturn(node) {
|
|
@@ -4605,7 +5164,7 @@ function sameParameter(declared, tested, sourceCode) {
|
|
|
4605
5164
|
return parameter !== null && parameter === ASTUtils12.findVariable(sourceCode.getScope(tested), tested.name);
|
|
4606
5165
|
}
|
|
4607
5166
|
function inputKinds(type, checker) {
|
|
4608
|
-
if ((type.flags &
|
|
5167
|
+
if ((type.flags & ts20.TypeFlags.Unknown) !== 0) return /* @__PURE__ */ new Set(["string", "number", "bigint", "boolean", "symbol", "undefined", "object", "function"]);
|
|
4609
5168
|
return primitiveKinds(type, checker, true);
|
|
4610
5169
|
}
|
|
4611
5170
|
function primitiveKinds(type, checker, allowLiterals) {
|
|
@@ -4617,7 +5176,7 @@ function primitiveKinds(type, checker, allowLiterals) {
|
|
|
4617
5176
|
kinds.add(kind);
|
|
4618
5177
|
continue;
|
|
4619
5178
|
}
|
|
4620
|
-
if ((member3.flags &
|
|
5179
|
+
if ((member3.flags & ts20.TypeFlags.BooleanLiteral) === 0) return void 0;
|
|
4621
5180
|
booleans.add(checker.typeToString(member3));
|
|
4622
5181
|
}
|
|
4623
5182
|
if (booleans.size > 0) {
|
|
@@ -4631,21 +5190,21 @@ function primitiveKind(type, allowLiterals) {
|
|
|
4631
5190
|
if ((type.flags & flag) !== 0) return kind;
|
|
4632
5191
|
}
|
|
4633
5192
|
if (!allowLiterals) return void 0;
|
|
4634
|
-
if ((type.flags &
|
|
4635
|
-
if ((type.flags &
|
|
4636
|
-
if ((type.flags &
|
|
4637
|
-
if ((type.flags &
|
|
5193
|
+
if ((type.flags & ts20.TypeFlags.StringLiteral) !== 0) return "string";
|
|
5194
|
+
if ((type.flags & ts20.TypeFlags.NumberLiteral) !== 0) return "number";
|
|
5195
|
+
if ((type.flags & ts20.TypeFlags.BigIntLiteral) !== 0) return "bigint";
|
|
5196
|
+
if ((type.flags & ts20.TypeFlags.Null) !== 0) return "object";
|
|
4638
5197
|
return void 0;
|
|
4639
5198
|
}
|
|
4640
5199
|
|
|
4641
5200
|
// src/rules/no-partial-type-predicate.ts
|
|
4642
5201
|
import { ASTUtils as ASTUtils15, AST_NODE_TYPES as AST_NODE_TYPES29, ESLintUtils as ESLintUtils13 } from "@typescript-eslint/utils";
|
|
4643
5202
|
import { isNumberLiteralType } from "ts-api-utils";
|
|
4644
|
-
import
|
|
5203
|
+
import ts22 from "typescript";
|
|
4645
5204
|
|
|
4646
5205
|
// src/rules/_uuid-predicate-witness.ts
|
|
4647
5206
|
import { AST_NODE_TYPES as AST_NODE_TYPES28, ASTUtils as ASTUtils14 } from "@typescript-eslint/utils";
|
|
4648
|
-
import
|
|
5207
|
+
import ts21 from "typescript";
|
|
4649
5208
|
|
|
4650
5209
|
// src/rules/_native-runtime-unchanged.ts
|
|
4651
5210
|
import { AST_NODE_TYPES as AST_NODE_TYPES27, ASTUtils as ASTUtils13 } from "@typescript-eslint/utils";
|
|
@@ -4752,7 +5311,7 @@ function noArguments(node) {
|
|
|
4752
5311
|
function installedZod(node, services) {
|
|
4753
5312
|
const checker = services.program.getTypeChecker();
|
|
4754
5313
|
const symbol = checker.getSymbolAtLocation(services.esTreeNodeToTSNodeMap.get(node));
|
|
4755
|
-
if (symbol === void 0 || (symbol.flags &
|
|
5314
|
+
if (symbol === void 0 || (symbol.flags & ts21.SymbolFlags.Alias) === 0) return false;
|
|
4756
5315
|
const target = checker.getAliasedSymbol(symbol);
|
|
4757
5316
|
const declarations = target.getDeclarations();
|
|
4758
5317
|
return declarations !== void 0 && declarations.length > 0 && declarations.every((declaration) => {
|
|
@@ -4850,25 +5409,25 @@ function primitivePredicate(node, services) {
|
|
|
4850
5409
|
if (node.async || node.generator || node.typeParameters !== void 0 || node.params.length !== 1 || annotation?.type !== AST_NODE_TYPES29.TSTypePredicate || annotation.asserts || annotation.parameterName.type !== AST_NODE_TYPES29.Identifier || annotation.typeAnnotation === void 0 || parameter?.type !== AST_NODE_TYPES29.Identifier || parameter.name !== annotation.parameterName.name || parameter.typeAnnotation === void 0) return void 0;
|
|
4851
5410
|
const checker = services.program.getTypeChecker();
|
|
4852
5411
|
const tsFunction = services.esTreeNodeToTSNodeMap.get(node);
|
|
4853
|
-
if (
|
|
5412
|
+
if (ts22.isMethodDeclaration(tsFunction)) return void 0;
|
|
4854
5413
|
if (hasSeparatePredicateContract(tsFunction, checker)) return void 0;
|
|
4855
5414
|
const target = checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(annotation.typeAnnotation.typeAnnotation));
|
|
4856
5415
|
const kind = primitiveKind2(target);
|
|
4857
5416
|
const input = checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(parameter));
|
|
4858
|
-
const unsafe =
|
|
5417
|
+
const unsafe = ts22.TypeFlags.Any | ts22.TypeFlags.Never | ts22.TypeFlags.TypeParameter | ts22.TypeFlags.Conditional | ts22.TypeFlags.IndexedAccess;
|
|
4859
5418
|
if (kind === void 0 || (input.flags & unsafe) !== 0 || !checker.isTypeAssignableTo(target, input)) return void 0;
|
|
4860
5419
|
const expression = returnedExpression2(node);
|
|
4861
5420
|
return expression === void 0 ? void 0 : { annotation, parameter, expression, kind, input, inputIsTarget: checker.isTypeAssignableTo(input, target) };
|
|
4862
5421
|
}
|
|
4863
5422
|
function primitiveKind2(type) {
|
|
4864
|
-
if ((type.flags &
|
|
4865
|
-
if ((type.flags &
|
|
4866
|
-
if ((type.flags &
|
|
4867
|
-
if ((type.flags &
|
|
5423
|
+
if ((type.flags & ts22.TypeFlags.String) !== 0) return "string";
|
|
5424
|
+
if ((type.flags & ts22.TypeFlags.Number) !== 0) return "number";
|
|
5425
|
+
if ((type.flags & ts22.TypeFlags.BigInt) !== 0) return "bigint";
|
|
5426
|
+
if ((type.flags & ts22.TypeFlags.Boolean) !== 0) return "boolean";
|
|
4868
5427
|
return void 0;
|
|
4869
5428
|
}
|
|
4870
5429
|
function numericWitnessInInput(value, input) {
|
|
4871
|
-
return (input.isUnion() ? input.types : [input]).some((member3) => (member3.flags & (
|
|
5430
|
+
return (input.isUnion() ? input.types : [input]).some((member3) => (member3.flags & (ts22.TypeFlags.Unknown | ts22.TypeFlags.Number)) !== 0 || Number.isFinite(value) && isNumberLiteralType(member3) && member3.value === value);
|
|
4872
5431
|
}
|
|
4873
5432
|
function returnedExpression2(node) {
|
|
4874
5433
|
if (node.body === void 0) return void 0;
|
|
@@ -4981,7 +5540,7 @@ import { AST_NODE_TYPES as AST_NODE_TYPES32, ASTUtils as ASTUtils18, ESLintUtils
|
|
|
4981
5540
|
|
|
4982
5541
|
// src/rules/_boolean-selector-contract.ts
|
|
4983
5542
|
import { AST_NODE_TYPES as AST_NODE_TYPES30, ASTUtils as ASTUtils16 } from "@typescript-eslint/utils";
|
|
4984
|
-
import
|
|
5543
|
+
import ts23 from "typescript";
|
|
4985
5544
|
var MEMBER_REFERENCES = /* @__PURE__ */ new WeakMap();
|
|
4986
5545
|
function isEligibleBooleanSelector(identifier, sourceCode, services) {
|
|
4987
5546
|
const owner = enclosingFunction(identifier);
|
|
@@ -4993,12 +5552,12 @@ function isEligibleBooleanSelector(identifier, sourceCode, services) {
|
|
|
4993
5552
|
const definition = binding3?.defs[0];
|
|
4994
5553
|
if (binding3?.defs.length !== 1 || definition?.type !== "Parameter" || definition.node !== owner || definition.name.type !== AST_NODE_TYPES30.Identifier || binding3.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
4995
5554
|
const checker = services.program.getTypeChecker();
|
|
4996
|
-
if ((checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(definition.name)).flags &
|
|
5555
|
+
if ((checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(definition.name)).flags & ts23.TypeFlags.Boolean) === 0) return false;
|
|
4997
5556
|
const parameter = definition.name.parent.type === AST_NODE_TYPES30.AssignmentPattern ? definition.name.parent : definition.name;
|
|
4998
5557
|
const index = owner.params.indexOf(parameter);
|
|
4999
5558
|
if (index < 0 || isPureMapping(owner, sourceCode, services)) return false;
|
|
5000
5559
|
const implementation = services.esTreeNodeToTSNodeMap.get(owner);
|
|
5001
|
-
if (
|
|
5560
|
+
if (ts23.isSetAccessorDeclaration(implementation)) return false;
|
|
5002
5561
|
const authority = { checker, index, implementation };
|
|
5003
5562
|
if (hasDeclaredContract(authority) || hasMemberCallbackReference(authority, sourceCode, services)) return false;
|
|
5004
5563
|
const callable = callableBinding2(owner, sourceCode);
|
|
@@ -5014,10 +5573,10 @@ function booleanContract(authority, type, independentlyAnnotated = false) {
|
|
|
5014
5573
|
return (type === void 0 ? [] : authority.checker.getNonNullableType(type).getCallSignatures()).some((signature) => {
|
|
5015
5574
|
const declaration = signature.declaration;
|
|
5016
5575
|
const parameter = declaration?.parameters[authority.index];
|
|
5017
|
-
if (declaration === void 0 || declaration === authority.implementation || parameter === void 0 || !
|
|
5018
|
-
if ((authority.checker.getTypeFromTypeNode(parameter.type).flags &
|
|
5576
|
+
if (declaration === void 0 || declaration === authority.implementation || parameter === void 0 || !ts23.isParameter(parameter) || parameter.type === void 0) return false;
|
|
5577
|
+
if ((authority.checker.getTypeFromTypeNode(parameter.type).flags & ts23.TypeFlags.BooleanLike) !== 0) return true;
|
|
5019
5578
|
const instantiated = signature.getParameters()[authority.index];
|
|
5020
|
-
return independentlyAnnotated && instantiated !== void 0 && (authority.checker.getTypeOfSymbolAtLocation(instantiated, declaration).flags &
|
|
5579
|
+
return independentlyAnnotated && instantiated !== void 0 && (authority.checker.getTypeOfSymbolAtLocation(instantiated, declaration).flags & ts23.TypeFlags.BooleanLike) !== 0;
|
|
5021
5580
|
});
|
|
5022
5581
|
}
|
|
5023
5582
|
function callbackContract(authority, expression) {
|
|
@@ -5025,22 +5584,22 @@ function callbackContract(authority, expression) {
|
|
|
5025
5584
|
if (booleanContract(authority, checker.getContextualType(expression))) return true;
|
|
5026
5585
|
const value = outerTypedExpression(expression);
|
|
5027
5586
|
const parent = value.parent;
|
|
5028
|
-
if (
|
|
5587
|
+
if (ts23.isCallExpression(parent)) {
|
|
5029
5588
|
const index = parent.arguments.indexOf(value);
|
|
5030
5589
|
const parameter = index < 0 ? void 0 : checker.getResolvedSignature(parent)?.declaration?.parameters[index];
|
|
5031
|
-
return parameter !== void 0 &&
|
|
5590
|
+
return parameter !== void 0 && ts23.isParameter(parameter) && parameter.type !== void 0 && booleanContract(authority, checker.getTypeFromTypeNode(parameter.type), true);
|
|
5032
5591
|
}
|
|
5033
|
-
if (!
|
|
5592
|
+
if (!ts23.isJsxExpression(parent) || !ts23.isJsxAttribute(parent.parent)) return false;
|
|
5034
5593
|
const attribute = parent.parent;
|
|
5035
|
-
if (checker.getSymbolAtLocation(attribute.name)?.declarations?.some((declaration) => (
|
|
5036
|
-
if (!
|
|
5594
|
+
if (checker.getSymbolAtLocation(attribute.name)?.declarations?.some((declaration) => (ts23.isPropertyDeclaration(declaration) || ts23.isPropertySignature(declaration)) && declaration.type !== void 0 && booleanContract(authority, checker.getTypeFromTypeNode(declaration.type), true)) === true) return true;
|
|
5595
|
+
if (!ts23.isIdentifier(attribute.name)) return false;
|
|
5037
5596
|
const opening = attribute.parent.parent;
|
|
5038
5597
|
const propContract = (type) => {
|
|
5039
5598
|
const property = checker.getPropertyOfType(type, attribute.name.getText());
|
|
5040
5599
|
return property !== void 0 && booleanContract(authority, checker.getTypeOfSymbolAtLocation(property, attribute), true);
|
|
5041
5600
|
};
|
|
5042
5601
|
const props = checker.getResolvedSignature(opening)?.declaration?.parameters[0];
|
|
5043
|
-
if (props !== void 0 &&
|
|
5602
|
+
if (props !== void 0 && ts23.isParameter(props) && props.type !== void 0 && propContract(checker.getTypeFromTypeNode(props.type))) return true;
|
|
5044
5603
|
return checker.getTypeAtLocation(opening.tagName).getCallSignatures().some((signature) => {
|
|
5045
5604
|
const parameter = signature.getParameters()[0];
|
|
5046
5605
|
return parameter !== void 0 && propContract(checker.getTypeOfSymbolAtLocation(parameter, opening.tagName));
|
|
@@ -5048,41 +5607,41 @@ function callbackContract(authority, expression) {
|
|
|
5048
5607
|
}
|
|
5049
5608
|
function outerTypedExpression(node) {
|
|
5050
5609
|
let current = node;
|
|
5051
|
-
while ((
|
|
5610
|
+
while ((ts23.isParenthesizedExpression(current.parent) || ts23.isAsExpression(current.parent) || ts23.isTypeAssertionExpression(current.parent) || ts23.isNonNullExpression(current.parent) || ts23.isSatisfiesExpression(current.parent)) && current.parent.expression === current) current = current.parent;
|
|
5052
5611
|
return current;
|
|
5053
5612
|
}
|
|
5054
5613
|
function hasDeclaredContract(authority) {
|
|
5055
5614
|
const node = authority.implementation;
|
|
5056
5615
|
const checker = authority.checker;
|
|
5057
|
-
if (
|
|
5616
|
+
if (ts23.isArrowFunction(node) || ts23.isFunctionExpression(node)) {
|
|
5058
5617
|
if (callbackContract(authority, node)) return true;
|
|
5059
5618
|
const binding3 = outerTypedExpression(node).parent;
|
|
5060
|
-
if ((
|
|
5061
|
-
return
|
|
5619
|
+
if ((ts23.isVariableDeclaration(binding3) || ts23.isPropertyDeclaration(binding3)) && binding3.type !== void 0 && booleanContract(authority, checker.getTypeFromTypeNode(binding3.type), true)) return true;
|
|
5620
|
+
return ts23.isPropertyDeclaration(binding3) && memberContract(authority, binding3);
|
|
5062
5621
|
}
|
|
5063
|
-
if (
|
|
5064
|
-
if (!
|
|
5065
|
-
return checker.getSymbolAtLocation(node.name)?.declarations?.some((declaration) => declaration !== node &&
|
|
5622
|
+
if (ts23.isMethodDeclaration(node)) return memberContract(authority, node);
|
|
5623
|
+
if (!ts23.isFunctionDeclaration(node) || node.name === void 0) return false;
|
|
5624
|
+
return checker.getSymbolAtLocation(node.name)?.declarations?.some((declaration) => declaration !== node && ts23.isFunctionDeclaration(declaration) && declaration.parameters[authority.index]?.type !== void 0) === true;
|
|
5066
5625
|
}
|
|
5067
5626
|
function memberContract(authority, member3) {
|
|
5068
5627
|
const owner = member3.parent;
|
|
5069
5628
|
const checker = authority.checker;
|
|
5070
5629
|
const symbol = checker.getSymbolAtLocation(member3.name);
|
|
5071
|
-
if (symbol === void 0 ||
|
|
5630
|
+
if (symbol === void 0 || ts23.isPrivateIdentifier(member3.name)) return false;
|
|
5072
5631
|
const matches = (type, independentlyAnnotated = false) => {
|
|
5073
5632
|
const property = type.getProperties().find((candidate2) => candidate2.escapedName === symbol.escapedName);
|
|
5074
5633
|
return property !== void 0 && booleanContract(authority, checker.getTypeOfSymbolAtLocation(property, member3), independentlyAnnotated);
|
|
5075
5634
|
};
|
|
5076
|
-
if (
|
|
5635
|
+
if (ts23.isObjectLiteralExpression(owner)) {
|
|
5077
5636
|
const contextual = checker.getContextualType(owner);
|
|
5078
5637
|
const binding3 = outerTypedExpression(owner).parent;
|
|
5079
|
-
if (
|
|
5638
|
+
if (ts23.isVariableDeclaration(binding3) && binding3.type !== void 0 && matches(checker.getTypeFromTypeNode(binding3.type), true)) return true;
|
|
5080
5639
|
return contextual !== void 0 && matches(contextual);
|
|
5081
5640
|
}
|
|
5082
|
-
if (!
|
|
5083
|
-
const modifiers =
|
|
5084
|
-
if ((modifiers &
|
|
5085
|
-
return owner.heritageClauses?.some((clause) => clause.types.some((heritage) => matches(checker.getTypeAtLocation((modifiers &
|
|
5641
|
+
if (!ts23.isClassDeclaration(owner) && !ts23.isClassExpression(owner)) return false;
|
|
5642
|
+
const modifiers = ts23.getCombinedModifierFlags(member3);
|
|
5643
|
+
if ((modifiers & ts23.ModifierFlags.Private) !== 0) return false;
|
|
5644
|
+
return owner.heritageClauses?.some((clause) => clause.types.some((heritage) => matches(checker.getTypeAtLocation((modifiers & ts23.ModifierFlags.Static) !== 0 ? heritage.expression : heritage), true))) === true;
|
|
5086
5645
|
}
|
|
5087
5646
|
function callableBinding2(owner, sourceCode) {
|
|
5088
5647
|
if (owner.type === AST_NODE_TYPES30.FunctionDeclaration && owner.id !== null) return ASTUtils16.findVariable(sourceCode.getScope(owner), owner.id.name);
|
|
@@ -5102,7 +5661,7 @@ function hasCallbackReference(binding3, authority, sourceCode, services, seen) {
|
|
|
5102
5661
|
const jsxAttribute = parent?.type === AST_NODE_TYPES30.JSXExpressionContainer && parent.parent.type === AST_NODE_TYPES30.JSXAttribute;
|
|
5103
5662
|
if (callArgument || jsxAttribute) {
|
|
5104
5663
|
const expression = services.esTreeNodeToTSNodeMap.get(value);
|
|
5105
|
-
if (
|
|
5664
|
+
if (ts23.isExpression(expression) && callbackContract(authority, expression)) return true;
|
|
5106
5665
|
}
|
|
5107
5666
|
if (parent?.type === AST_NODE_TYPES30.CallExpression && parent.callee === value && forwardedCallbackParameter(parent, authority, sourceCode, services)) return true;
|
|
5108
5667
|
let selected = value;
|
|
@@ -5127,20 +5686,20 @@ function forwardedCallbackParameter(call, authority, sourceCode, services) {
|
|
|
5127
5686
|
const binding3 = ASTUtils16.findVariable(sourceCode.getScope(argument), argument.name);
|
|
5128
5687
|
const definition = binding3?.defs[0];
|
|
5129
5688
|
if (binding3?.defs.length !== 1 || definition?.type !== "Parameter" || definition.node !== wrapper || definition.name.type !== AST_NODE_TYPES30.Identifier || binding3.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
5130
|
-
if ((authority.checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(definition.name)).flags &
|
|
5689
|
+
if ((authority.checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(definition.name)).flags & ts23.TypeFlags.Boolean) === 0) return false;
|
|
5131
5690
|
const parameter = definition.name.parent.type === AST_NODE_TYPES30.AssignmentPattern ? definition.name.parent : definition.name;
|
|
5132
5691
|
const index = wrapper.params.indexOf(parameter);
|
|
5133
5692
|
const implementation = services.esTreeNodeToTSNodeMap.get(wrapper);
|
|
5134
|
-
return index >= 0 && (
|
|
5693
|
+
return index >= 0 && (ts23.isArrowFunction(implementation) || ts23.isFunctionExpression(implementation)) && callbackContract({ checker: authority.checker, index, implementation }, implementation);
|
|
5135
5694
|
}
|
|
5136
5695
|
function hasMemberCallbackReference(authority, sourceCode, services) {
|
|
5137
5696
|
const node = authority.implementation;
|
|
5138
|
-
const member3 =
|
|
5139
|
-
if (member3 === void 0 || !
|
|
5697
|
+
const member3 = ts23.isMethodDeclaration(node) ? node : ts23.isArrowFunction(node) || ts23.isFunctionExpression(node) ? outerTypedExpression(node).parent : void 0;
|
|
5698
|
+
if (member3 === void 0 || !ts23.isMethodDeclaration(member3) && !ts23.isPropertyDeclaration(member3) && !ts23.isPropertyAssignment(member3)) return false;
|
|
5140
5699
|
let references = MEMBER_REFERENCES.get(sourceCode);
|
|
5141
5700
|
if (references === void 0) {
|
|
5142
5701
|
let visit2 = function(current) {
|
|
5143
|
-
if (
|
|
5702
|
+
if (ts23.isPropertyAccessExpression(current)) {
|
|
5144
5703
|
const target = authority.checker.getSymbolAtLocation(current.name);
|
|
5145
5704
|
for (const declaration of target?.declarations ?? []) {
|
|
5146
5705
|
const values = collected.get(declaration) ?? [];
|
|
@@ -5148,7 +5707,7 @@ function hasMemberCallbackReference(authority, sourceCode, services) {
|
|
|
5148
5707
|
collected.set(declaration, values);
|
|
5149
5708
|
}
|
|
5150
5709
|
}
|
|
5151
|
-
|
|
5710
|
+
ts23.forEachChild(current, visit2);
|
|
5152
5711
|
};
|
|
5153
5712
|
var visit = visit2;
|
|
5154
5713
|
const collected = /* @__PURE__ */ new Map();
|
|
@@ -5159,14 +5718,14 @@ function hasMemberCallbackReference(authority, sourceCode, services) {
|
|
|
5159
5718
|
return references.get(member3)?.some((reference) => {
|
|
5160
5719
|
let value = outerTypedExpression(reference);
|
|
5161
5720
|
const bind = value.parent;
|
|
5162
|
-
if (
|
|
5721
|
+
if (ts23.isPropertyAccessExpression(bind) && bind.expression === value && bind.name.text === "bind" && ts23.isCallExpression(bind.parent) && bind.parent.expression === bind && bind.parent.arguments.length === 1) {
|
|
5163
5722
|
const declaration = authority.checker.getResolvedSignature(bind.parent)?.declaration;
|
|
5164
5723
|
if (declaration === void 0 || !services.program.isSourceFileDefaultLibrary(declaration.getSourceFile())) return false;
|
|
5165
5724
|
value = outerTypedExpression(bind.parent);
|
|
5166
5725
|
}
|
|
5167
5726
|
const parent = value.parent;
|
|
5168
|
-
const callback =
|
|
5169
|
-
const jsx =
|
|
5727
|
+
const callback = ts23.isCallExpression(parent) && parent.arguments.some((argument) => argument === value);
|
|
5728
|
+
const jsx = ts23.isJsxExpression(parent) && ts23.isJsxAttribute(parent.parent);
|
|
5170
5729
|
return (callback || jsx) && callbackContract(authority, value);
|
|
5171
5730
|
}) === true;
|
|
5172
5731
|
}
|
|
@@ -5210,21 +5769,21 @@ function sameTarget(left, right, sourceCode, services, operation2) {
|
|
|
5210
5769
|
if (!operation2) return true;
|
|
5211
5770
|
const checker = services.program.getTypeChecker();
|
|
5212
5771
|
const property = checker.getSymbolAtLocation(services.esTreeNodeToTSNodeMap.get(left.property));
|
|
5213
|
-
return property !== void 0 && property === checker.getSymbolAtLocation(services.esTreeNodeToTSNodeMap.get(right.property)) && property.declarations?.every((declaration) =>
|
|
5772
|
+
return property !== void 0 && property === checker.getSymbolAtLocation(services.esTreeNodeToTSNodeMap.get(right.property)) && property.declarations?.every((declaration) => ts23.isMethodDeclaration(declaration)) === true;
|
|
5214
5773
|
}
|
|
5215
5774
|
function pureValue(node, sourceCode, services) {
|
|
5216
5775
|
const value = unwrapExpression(node);
|
|
5217
5776
|
if (value.type === AST_NODE_TYPES30.MemberExpression && !value.computed) return value.object.type === AST_NODE_TYPES30.Super || pureValue(value.object, sourceCode, services);
|
|
5218
5777
|
if (value.type === AST_NODE_TYPES30.ChainExpression) return pureValue(value.expression, sourceCode, services);
|
|
5219
5778
|
if (value.type === AST_NODE_TYPES30.UnaryExpression && (value.operator === "!" || value.operator === "typeof" || value.operator === "void")) return pureValue(value.argument, sourceCode, services);
|
|
5220
|
-
if (value.type === AST_NODE_TYPES30.UnaryExpression && (value.operator === "+" || value.operator === "-" || value.operator === "~")) return
|
|
5779
|
+
if (value.type === AST_NODE_TYPES30.UnaryExpression && (value.operator === "+" || value.operator === "-" || value.operator === "~")) return primitiveValue2(value.argument, services) && pureValue(value.argument, sourceCode, services);
|
|
5221
5780
|
if (!ASTUtils16.hasSideEffect(value, sourceCode, { considerGetters: true, considerImplicitTypeConversion: true })) return true;
|
|
5222
5781
|
if (value.type !== AST_NODE_TYPES30.BinaryExpression || value.left.type === AST_NODE_TYPES30.PrivateIdentifier) return false;
|
|
5223
|
-
return
|
|
5782
|
+
return primitiveValue2(value.left, services) && primitiveValue2(value.right, services) && pureValue(value.left, sourceCode, services) && pureValue(value.right, sourceCode, services);
|
|
5224
5783
|
}
|
|
5225
|
-
function
|
|
5784
|
+
function primitiveValue2(operand, services) {
|
|
5226
5785
|
const type = services.program.getTypeChecker().getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(operand));
|
|
5227
|
-
return (type.isUnion() ? type.types : [type]).every((member3) => (member3.flags & (
|
|
5786
|
+
return (type.isUnion() ? type.types : [type]).every((member3) => (member3.flags & (ts23.TypeFlags.StringLike | ts23.TypeFlags.NumberLike | ts23.TypeFlags.BooleanLike | ts23.TypeFlags.BigIntLike | ts23.TypeFlags.Null | ts23.TypeFlags.Undefined)) !== 0);
|
|
5228
5787
|
}
|
|
5229
5788
|
|
|
5230
5789
|
// src/rules/_literal-selector-fix.ts
|
|
@@ -5458,7 +6017,7 @@ function isDirectTest(identifier) {
|
|
|
5458
6017
|
// src/rules/no-invalid-zod-custom-parse.ts
|
|
5459
6018
|
import { ASTUtils as ASTUtils19, AST_NODE_TYPES as AST_NODE_TYPES34, ESLintUtils as ESLintUtils15 } from "@typescript-eslint/utils";
|
|
5460
6019
|
import { isBigIntLiteralType, isBooleanLiteralType, isNumberLiteralType as isNumberLiteralType2, isStringLiteralType } from "ts-api-utils";
|
|
5461
|
-
import
|
|
6020
|
+
import ts24 from "typescript";
|
|
5462
6021
|
|
|
5463
6022
|
// src/rules/_import-specifier-name.ts
|
|
5464
6023
|
import { AST_NODE_TYPES as AST_NODE_TYPES33 } from "@typescript-eslint/utils";
|
|
@@ -5554,17 +6113,17 @@ function nativeZodDeclaration(signature) {
|
|
|
5554
6113
|
}
|
|
5555
6114
|
function primitiveDomain(type) {
|
|
5556
6115
|
if (type.isUnion()) return type.types.every(primitiveDomain);
|
|
5557
|
-
if ((type.flags & (
|
|
5558
|
-
const flags =
|
|
6116
|
+
if ((type.flags & (ts24.TypeFlags.Enum | ts24.TypeFlags.EnumLiteral)) !== 0) return false;
|
|
6117
|
+
const flags = ts24.TypeFlags.String | ts24.TypeFlags.Number | ts24.TypeFlags.BigInt | ts24.TypeFlags.BooleanLiteral | ts24.TypeFlags.StringLiteral | ts24.TypeFlags.NumberLiteral | ts24.TypeFlags.BigIntLiteral | ts24.TypeFlags.Null | ts24.TypeFlags.Undefined | ts24.TypeFlags.Never;
|
|
5559
6118
|
return (type.flags & flags) !== 0;
|
|
5560
6119
|
}
|
|
5561
6120
|
function acceptsPrimitive(type, value) {
|
|
5562
6121
|
if (type.isUnion()) return type.types.some((member3) => acceptsPrimitive(member3, value));
|
|
5563
|
-
if (value === null) return (type.flags &
|
|
5564
|
-
if (typeof value === "string") return (type.flags &
|
|
5565
|
-
if (typeof value === "number") return (type.flags &
|
|
6122
|
+
if (value === null) return (type.flags & ts24.TypeFlags.Null) !== 0;
|
|
6123
|
+
if (typeof value === "string") return (type.flags & ts24.TypeFlags.String) !== 0 || isStringLiteralType(type) && type.value === value;
|
|
6124
|
+
if (typeof value === "number") return (type.flags & ts24.TypeFlags.Number) !== 0 || isNumberLiteralType2(type) && type.value === value;
|
|
5566
6125
|
if (typeof value === "boolean") return isBooleanLiteralType(type) && type.intrinsicName === String(value);
|
|
5567
|
-
return (type.flags &
|
|
6126
|
+
return (type.flags & ts24.TypeFlags.BigInt) !== 0 || isBigIntLiteralType(type) && bigintValue(type) === value;
|
|
5568
6127
|
}
|
|
5569
6128
|
function bigintValue(type) {
|
|
5570
6129
|
return BigInt(`${type.value.negative ? "-" : ""}${type.value.base10Value}`);
|
|
@@ -5581,7 +6140,7 @@ function primitiveLiteral(node) {
|
|
|
5581
6140
|
|
|
5582
6141
|
// src/rules/no-contradictory-overload-return.ts
|
|
5583
6142
|
import { AST_NODE_TYPES as AST_NODE_TYPES35, ESLintUtils as ESLintUtils16 } from "@typescript-eslint/utils";
|
|
5584
|
-
import
|
|
6143
|
+
import ts25 from "typescript";
|
|
5585
6144
|
var LIMIT = 32;
|
|
5586
6145
|
var NO_CONTRADICTORY_OVERLOAD_RETURN_DOCUMENTATION = {
|
|
5587
6146
|
summary: "Preserve the input/result relationship promised by literal overloads.",
|
|
@@ -5679,16 +6238,16 @@ function privateOverloadFix(sourceCode, filename, node, implementation, proof, s
|
|
|
5679
6238
|
return edits.length === 0 ? null : (fixer) => edits.map((edit) => fixer.replaceText(edit.node, edit.text));
|
|
5680
6239
|
}
|
|
5681
6240
|
function directResultSyntax(node) {
|
|
5682
|
-
if (
|
|
5683
|
-
if (
|
|
5684
|
-
if (!
|
|
5685
|
-
return node.members.every((member3) =>
|
|
6241
|
+
if (ts25.isParenthesizedTypeNode(node)) return directResultSyntax(node.type);
|
|
6242
|
+
if (ts25.isUnionTypeNode(node)) return node.types.length <= LIMIT && node.types.every(directResultSyntax);
|
|
6243
|
+
if (!ts25.isTypeLiteralNode(node)) return primitiveResultSyntax(node);
|
|
6244
|
+
return node.members.every((member3) => ts25.isPropertySignature(member3) && propertyKey(member3.name) !== void 0 && member3.type !== void 0 && primitiveResultSyntax(member3.type));
|
|
5686
6245
|
}
|
|
5687
6246
|
function primitiveResultSyntax(node) {
|
|
5688
|
-
if (
|
|
5689
|
-
if (
|
|
5690
|
-
if (
|
|
5691
|
-
return node.kind ===
|
|
6247
|
+
if (ts25.isParenthesizedTypeNode(node)) return primitiveResultSyntax(node.type);
|
|
6248
|
+
if (ts25.isUnionTypeNode(node)) return node.types.length <= LIMIT && node.types.every(primitiveResultSyntax);
|
|
6249
|
+
if (ts25.isLiteralTypeNode(node)) return primitiveLiteral2(node.literal) !== void 0;
|
|
6250
|
+
return node.kind === ts25.SyntaxKind.StringKeyword || node.kind === ts25.SyntaxKind.NumberKeyword || node.kind === ts25.SyntaxKind.BooleanKeyword || node.kind === ts25.SyntaxKind.UndefinedKeyword || node.kind === ts25.SyntaxKind.NeverKeyword;
|
|
5692
6251
|
}
|
|
5693
6252
|
function branchResultType(branch, sourceCode, services) {
|
|
5694
6253
|
const valueType = (literal2) => typeof literal2.value === "string" ? sourceCode.getText(services.tsNodeToESTreeNodeMap.get(literal2.node)) : String(literal2.value);
|
|
@@ -5697,11 +6256,11 @@ function branchResultType(branch, sourceCode, services) {
|
|
|
5697
6256
|
}
|
|
5698
6257
|
function implementationProof(node, checker) {
|
|
5699
6258
|
const parameter = directParameter(node);
|
|
5700
|
-
if (!
|
|
6259
|
+
if (!ts25.isSourceFile(node.parent) || node.name === void 0 || node.body?.statements.length !== 1 || node.typeParameters !== void 0 || node.asteriskToken !== void 0 || node.modifiers?.some((modifier) => modifier.kind === ts25.SyntaxKind.AsyncKeyword) || parameter === void 0) return void 0;
|
|
5701
6260
|
const returned2 = node.body.statements[0];
|
|
5702
|
-
if (returned2 === void 0 || !
|
|
6261
|
+
if (returned2 === void 0 || !ts25.isReturnStatement(returned2) || returned2.expression === void 0) return void 0;
|
|
5703
6262
|
const expression = unparen(returned2.expression);
|
|
5704
|
-
if (!
|
|
6263
|
+
if (!ts25.isConditionalExpression(expression)) return void 0;
|
|
5705
6264
|
const condition2 = equality(expression.condition, checker.getSymbolAtLocation(parameter.name), checker);
|
|
5706
6265
|
const yes = branchValue(expression.whenTrue);
|
|
5707
6266
|
const no = branchValue(expression.whenFalse);
|
|
@@ -5715,21 +6274,21 @@ function implementationProof(node, checker) {
|
|
|
5715
6274
|
}
|
|
5716
6275
|
function directParameter(node) {
|
|
5717
6276
|
const parameter = node.parameters[0];
|
|
5718
|
-
if (node.parameters.length !== 1 || parameter === void 0 || !
|
|
6277
|
+
if (node.parameters.length !== 1 || parameter === void 0 || !ts25.isIdentifier(parameter.name) || parameter.name.text === "this" || parameter.type === void 0 || parameter.questionToken !== void 0 || parameter.dotDotDotToken !== void 0 || parameter.initializer !== void 0) return void 0;
|
|
5719
6278
|
return { name: parameter.name, type: parameter.type };
|
|
5720
6279
|
}
|
|
5721
6280
|
function overloadCases(node, implementationOutput, checker) {
|
|
5722
6281
|
const declarations = node.name === void 0 ? void 0 : checker.getSymbolAtLocation(node.name)?.declarations;
|
|
5723
|
-
if (declarations === void 0 || declarations.length < 3 || declarations.length > LIMIT + 1 || declarations.some((declaration) => !
|
|
6282
|
+
if (declarations === void 0 || declarations.length < 3 || declarations.length > LIMIT + 1 || declarations.some((declaration) => !ts25.isFunctionDeclaration(declaration))) return void 0;
|
|
5724
6283
|
const cases = [];
|
|
5725
6284
|
const seen = /* @__PURE__ */ new Set();
|
|
5726
6285
|
const implementationParameter = directParameter(node);
|
|
5727
6286
|
if (implementationParameter === void 0) return void 0;
|
|
5728
6287
|
const implementationInput = checker.getTypeAtLocation(implementationParameter.type);
|
|
5729
6288
|
for (const declaration of declarations) {
|
|
5730
|
-
if (!
|
|
6289
|
+
if (!ts25.isFunctionDeclaration(declaration) || declaration === node) continue;
|
|
5731
6290
|
const parameter = directParameter(declaration);
|
|
5732
|
-
if (declaration.body !== void 0 || declaration.typeParameters !== void 0 || parameter === void 0 || !
|
|
6291
|
+
if (declaration.body !== void 0 || declaration.typeParameters !== void 0 || parameter === void 0 || !ts25.isLiteralTypeNode(parameter.type)) return void 0;
|
|
5733
6292
|
const input = primitiveLiteral2(parameter.type.literal);
|
|
5734
6293
|
const signature = checker.getSignatureFromDeclaration(declaration);
|
|
5735
6294
|
if (input === void 0 || seen.has(input.value) || signature === void 0 || !checker.isTypeAssignableTo(checker.getTypeAtLocation(parameter.type), implementationInput)) return void 0;
|
|
@@ -5742,11 +6301,11 @@ function overloadCases(node, implementationOutput, checker) {
|
|
|
5742
6301
|
}
|
|
5743
6302
|
function equality(expression, parameter, checker) {
|
|
5744
6303
|
const value = unparen(expression);
|
|
5745
|
-
if (parameter === void 0 || !
|
|
6304
|
+
if (parameter === void 0 || !ts25.isBinaryExpression(value) || value.operatorToken.kind !== ts25.SyntaxKind.EqualsEqualsEqualsToken && value.operatorToken.kind !== ts25.SyntaxKind.ExclamationEqualsEqualsToken) return void 0;
|
|
5746
6305
|
for (const [tested, expected] of [[value.left, value.right], [value.right, value.left]]) {
|
|
5747
6306
|
const named3 = unparen(tested);
|
|
5748
6307
|
const condition2 = primitiveLiteral2(expected);
|
|
5749
|
-
if (
|
|
6308
|
+
if (ts25.isIdentifier(named3) && checker.getSymbolAtLocation(named3) === parameter && condition2 !== void 0) return { condition: condition2, equal: value.operatorToken.kind === ts25.SyntaxKind.EqualsEqualsEqualsToken };
|
|
5750
6309
|
}
|
|
5751
6310
|
return void 0;
|
|
5752
6311
|
}
|
|
@@ -5754,10 +6313,10 @@ function branchValue(expression) {
|
|
|
5754
6313
|
const node = unparen(expression);
|
|
5755
6314
|
const literal2 = primitiveLiteral2(node);
|
|
5756
6315
|
if (literal2 !== void 0) return { kind: "literal", node, value: literal2 };
|
|
5757
|
-
if (!
|
|
6316
|
+
if (!ts25.isObjectLiteralExpression(node) || node.properties.length > LIMIT) return void 0;
|
|
5758
6317
|
const values = /* @__PURE__ */ new Map();
|
|
5759
6318
|
for (const property of node.properties) {
|
|
5760
|
-
if (!
|
|
6319
|
+
if (!ts25.isPropertyAssignment(property)) return void 0;
|
|
5761
6320
|
const name = propertyKey(property.name);
|
|
5762
6321
|
const value = primitiveLiteral2(property.initializer);
|
|
5763
6322
|
if (name === void 0 || name === "__proto__" || values.has(name) || value === void 0) return void 0;
|
|
@@ -5781,30 +6340,30 @@ function mismatches(branch, expected, checker) {
|
|
|
5781
6340
|
}
|
|
5782
6341
|
function plainPrimitive(type) {
|
|
5783
6342
|
const members = type.isUnion() ? type.types : [type];
|
|
5784
|
-
const allowed =
|
|
5785
|
-
return members.length <= LIMIT && members.every((member3) => (member3.flags & allowed) !== 0 && (member3.flags & (
|
|
6343
|
+
const allowed = ts25.TypeFlags.String | ts25.TypeFlags.StringLiteral | ts25.TypeFlags.Number | ts25.TypeFlags.NumberLiteral | ts25.TypeFlags.BooleanLiteral | ts25.TypeFlags.Null | ts25.TypeFlags.Undefined | ts25.TypeFlags.Never;
|
|
6344
|
+
return members.length <= LIMIT && members.every((member3) => (member3.flags & allowed) !== 0 && (member3.flags & (ts25.TypeFlags.Enum | ts25.TypeFlags.EnumLiteral)) === 0);
|
|
5786
6345
|
}
|
|
5787
6346
|
function primitiveLiteral2(expression) {
|
|
5788
6347
|
const node = unparen(expression);
|
|
5789
|
-
if (
|
|
5790
|
-
if (node.kind ===
|
|
5791
|
-
if (node.kind ===
|
|
5792
|
-
if (node.kind ===
|
|
5793
|
-
if (
|
|
5794
|
-
if (
|
|
5795
|
-
const value = Number(node.operand.text) * (node.operator ===
|
|
6348
|
+
if (ts25.isStringLiteral(node)) return { node, value: node.text };
|
|
6349
|
+
if (node.kind === ts25.SyntaxKind.TrueKeyword) return { node, value: true };
|
|
6350
|
+
if (node.kind === ts25.SyntaxKind.FalseKeyword) return { node, value: false };
|
|
6351
|
+
if (node.kind === ts25.SyntaxKind.NullKeyword) return { node, value: null };
|
|
6352
|
+
if (ts25.isNumericLiteral(node) && Number.isFinite(Number(node.text))) return { node, value: Number(node.text) };
|
|
6353
|
+
if (ts25.isPrefixUnaryExpression(node) && (node.operator === ts25.SyntaxKind.MinusToken || node.operator === ts25.SyntaxKind.PlusToken) && ts25.isNumericLiteral(node.operand)) {
|
|
6354
|
+
const value = Number(node.operand.text) * (node.operator === ts25.SyntaxKind.MinusToken ? -1 : 1);
|
|
5796
6355
|
if (Number.isFinite(value)) return { node, value };
|
|
5797
6356
|
}
|
|
5798
6357
|
return void 0;
|
|
5799
6358
|
}
|
|
5800
6359
|
function propertyKey(name) {
|
|
5801
|
-
if (
|
|
5802
|
-
if (
|
|
6360
|
+
if (ts25.isIdentifier(name) || ts25.isStringLiteral(name)) return name.text;
|
|
6361
|
+
if (ts25.isNumericLiteral(name) && Number.isFinite(Number(name.text))) return String(Number(name.text));
|
|
5803
6362
|
return void 0;
|
|
5804
6363
|
}
|
|
5805
6364
|
function unparen(expression) {
|
|
5806
6365
|
let node = expression;
|
|
5807
|
-
while (
|
|
6366
|
+
while (ts25.isParenthesizedExpression(node)) node = node.expression;
|
|
5808
6367
|
return node;
|
|
5809
6368
|
}
|
|
5810
6369
|
|
|
@@ -12412,7 +12971,7 @@ import {
|
|
|
12412
12971
|
ASTUtils as ASTUtils38,
|
|
12413
12972
|
ESLintUtils as ESLintUtils17
|
|
12414
12973
|
} from "@typescript-eslint/utils";
|
|
12415
|
-
import
|
|
12974
|
+
import ts26 from "typescript";
|
|
12416
12975
|
|
|
12417
12976
|
// src/rules/_existing-domain-comparison-fix.ts
|
|
12418
12977
|
import {
|
|
@@ -12610,7 +13169,7 @@ var EQUALITY_OPERATORS = /* @__PURE__ */ new Set([
|
|
|
12610
13169
|
"==",
|
|
12611
13170
|
"==="
|
|
12612
13171
|
]);
|
|
12613
|
-
var PRIMITIVE_FLAGS =
|
|
13172
|
+
var PRIMITIVE_FLAGS = ts26.TypeFlags.BigIntLike | ts26.TypeFlags.BooleanLike | ts26.TypeFlags.ESSymbolLike | ts26.TypeFlags.Never | ts26.TypeFlags.Null | ts26.TypeFlags.NumberLike | ts26.TypeFlags.StringLike | ts26.TypeFlags.Undefined | ts26.TypeFlags.Void;
|
|
12614
13173
|
function unwrapComparisonExpression(node) {
|
|
12615
13174
|
let current = unwrapExpression(node);
|
|
12616
13175
|
while (current.type === AST_NODE_TYPES68.ChainExpression) {
|
|
@@ -12665,7 +13224,7 @@ function typeMayContainObject(type, checker) {
|
|
|
12665
13224
|
return type.types.some((member3) => typeMayContainObject(member3, checker));
|
|
12666
13225
|
}
|
|
12667
13226
|
if ((type.flags & PRIMITIVE_FLAGS) !== 0) return false;
|
|
12668
|
-
if ((type.flags & (
|
|
13227
|
+
if ((type.flags & (ts26.TypeFlags.Any | ts26.TypeFlags.Unknown | ts26.TypeFlags.TypeParameter)) !== 0) {
|
|
12669
13228
|
return true;
|
|
12670
13229
|
}
|
|
12671
13230
|
if (checker.isArrayType(type) || checker.isTupleType(type)) {
|
|
@@ -12673,7 +13232,7 @@ function typeMayContainObject(type, checker) {
|
|
|
12673
13232
|
return elements.some((element) => typeMayContainObject(element, checker));
|
|
12674
13233
|
}
|
|
12675
13234
|
const symbolName = type.getSymbol()?.getName();
|
|
12676
|
-
if ((symbolName === "Array" || symbolName === "ReadonlyArray") && (type.flags &
|
|
13235
|
+
if ((symbolName === "Array" || symbolName === "ReadonlyArray") && (type.flags & ts26.TypeFlags.Object) !== 0) {
|
|
12677
13236
|
const elements = checker.getTypeArguments(type);
|
|
12678
13237
|
return elements.length === 0 || elements.some((element) => typeMayContainObject(element, checker));
|
|
12679
13238
|
}
|
|
@@ -13124,7 +13683,7 @@ function zeroBoundSemantic(method) {
|
|
|
13124
13683
|
import {
|
|
13125
13684
|
ESLintUtils as ESLintUtils18
|
|
13126
13685
|
} from "@typescript-eslint/utils";
|
|
13127
|
-
import * as
|
|
13686
|
+
import * as ts27 from "typescript";
|
|
13128
13687
|
|
|
13129
13688
|
// src/rules/_collection-property-fix.ts
|
|
13130
13689
|
import {
|
|
@@ -13227,7 +13786,7 @@ function isDefaultLibraryCollection(node, services) {
|
|
|
13227
13786
|
const checker = services.program.getTypeChecker();
|
|
13228
13787
|
const tsNode = services.esTreeNodeToTSNodeMap.get(node);
|
|
13229
13788
|
const type = checker.getTypeAtLocation(tsNode);
|
|
13230
|
-
if ((type.flags & (
|
|
13789
|
+
if ((type.flags & (ts27.TypeFlags.Any | ts27.TypeFlags.Unknown | ts27.TypeFlags.Never | ts27.TypeFlags.TypeParameter | ts27.TypeFlags.Union | ts27.TypeFlags.Intersection)) !== 0) {
|
|
13231
13790
|
return false;
|
|
13232
13791
|
}
|
|
13233
13792
|
return isDefaultLibraryCollectionSymbol(type.getSymbol(), services);
|
|
@@ -13238,7 +13797,7 @@ function isDefaultLibraryCollectionSymbol(symbol, services) {
|
|
|
13238
13797
|
return declarations.length > 0 && declarations.every(
|
|
13239
13798
|
(declaration) => services.program.isSourceFileDefaultLibrary(declaration.getSourceFile())
|
|
13240
13799
|
) && declarations.some(
|
|
13241
|
-
(declaration) =>
|
|
13800
|
+
(declaration) => ts27.isInterfaceDeclaration(declaration) && declaration.name.text === symbol.name
|
|
13242
13801
|
);
|
|
13243
13802
|
}
|
|
13244
13803
|
var no_in_operator_on_built_in_collections_default = createRule({
|
|
@@ -13558,7 +14117,7 @@ import {
|
|
|
13558
14117
|
AST_NODE_TYPES as AST_NODE_TYPES74,
|
|
13559
14118
|
ESLintUtils as ESLintUtils19
|
|
13560
14119
|
} from "@typescript-eslint/utils";
|
|
13561
|
-
import * as
|
|
14120
|
+
import * as ts28 from "typescript";
|
|
13562
14121
|
|
|
13563
14122
|
// src/rules/_class-private.ts
|
|
13564
14123
|
import {
|
|
@@ -13730,15 +14289,15 @@ function candidate(member3) {
|
|
|
13730
14289
|
}
|
|
13731
14290
|
function interfaceNames(services, owner) {
|
|
13732
14291
|
const tsOwner = services.esTreeNodeToTSNodeMap.get(owner);
|
|
13733
|
-
if (!
|
|
13734
|
-
const implemented = tsOwner.heritageClauses?.filter((clause) => clause.token ===
|
|
14292
|
+
if (!ts28.isClassDeclaration(tsOwner) && !ts28.isClassExpression(tsOwner)) return null;
|
|
14293
|
+
const implemented = tsOwner.heritageClauses?.filter((clause) => clause.token === ts28.SyntaxKind.ImplementsKeyword) ?? [];
|
|
13735
14294
|
if (implemented.length === 0) return null;
|
|
13736
14295
|
const checker = services.program.getTypeChecker();
|
|
13737
14296
|
const names = /* @__PURE__ */ new Set();
|
|
13738
14297
|
for (const clause of implemented) {
|
|
13739
14298
|
for (const contract of clause.types) {
|
|
13740
14299
|
const type = checker.getTypeAtLocation(contract);
|
|
13741
|
-
if ((type.flags & (
|
|
14300
|
+
if ((type.flags & (ts28.TypeFlags.Any | ts28.TypeFlags.Unknown)) !== 0) return null;
|
|
13742
14301
|
for (const property of checker.getPropertiesOfType(type)) names.add(property.getName());
|
|
13743
14302
|
}
|
|
13744
14303
|
}
|
|
@@ -14905,7 +15464,7 @@ function tupleFields(helper) {
|
|
|
14905
15464
|
const values = [];
|
|
14906
15465
|
for (const [index, field] of tuple.elementTypes.entries()) {
|
|
14907
15466
|
const value = returned2.argument.elements[index];
|
|
14908
|
-
if (field.type !== AST_NODE_TYPES81.TSNamedTupleMember || field.optional || value?.type !== AST_NODE_TYPES81.Literal || !
|
|
15467
|
+
if (field.type !== AST_NODE_TYPES81.TSNamedTupleMember || field.optional || value?.type !== AST_NODE_TYPES81.Literal || !primitiveValue3(field.elementType, value) || UNSAFE_NAMES.has(field.label.name) || labels.some((label) => label.name === field.label.name))
|
|
14909
15468
|
return null;
|
|
14910
15469
|
labels.push(field.label);
|
|
14911
15470
|
types.push(field.elementType);
|
|
@@ -14913,7 +15472,7 @@ function tupleFields(helper) {
|
|
|
14913
15472
|
}
|
|
14914
15473
|
return { labels, types, values, returned: returned2.argument };
|
|
14915
15474
|
}
|
|
14916
|
-
function
|
|
15475
|
+
function primitiveValue3(type, value) {
|
|
14917
15476
|
switch (type.type) {
|
|
14918
15477
|
case AST_NODE_TYPES81.TSStringKeyword:
|
|
14919
15478
|
return typeof value.value === "string";
|
|
@@ -21004,7 +21563,7 @@ import {
|
|
|
21004
21563
|
AST_NODE_TYPES as AST_NODE_TYPES107,
|
|
21005
21564
|
ASTUtils as ASTUtils65
|
|
21006
21565
|
} from "@typescript-eslint/utils";
|
|
21007
|
-
import * as
|
|
21566
|
+
import * as ts29 from "typescript";
|
|
21008
21567
|
var NO_ZOD_NATIVE_ENUM_DOCUMENTATION = {
|
|
21009
21568
|
summary: 'Disallow `z.nativeEnum()` (and `z.enum()` over a TypeScript enum); use `z.enum(["a", "b"])` with a string-literal union instead.',
|
|
21010
21569
|
rationale: "The project prefers literal-first schema definitions. nativeEnum also accepts plain enum-like objects, so this is an explicit declaration policy, not proof that every call duplicates a TypeScript enum's runtime object.",
|
|
@@ -21113,7 +21672,7 @@ function resolvesToLocalEnum(node, scope) {
|
|
|
21113
21672
|
}
|
|
21114
21673
|
return false;
|
|
21115
21674
|
}
|
|
21116
|
-
var ENUM_SYMBOL_FLAGS =
|
|
21675
|
+
var ENUM_SYMBOL_FLAGS = ts29.SymbolFlags.RegularEnum | ts29.SymbolFlags.ConstEnum | ts29.SymbolFlags.Enum;
|
|
21117
21676
|
function resolvesToImportedEnum(node, services) {
|
|
21118
21677
|
const checker = services.program.getTypeChecker();
|
|
21119
21678
|
const tsNode = services.esTreeNodeToTSNodeMap.get(node);
|
|
@@ -21121,7 +21680,7 @@ function resolvesToImportedEnum(node, services) {
|
|
|
21121
21680
|
if (symbol === void 0) {
|
|
21122
21681
|
return false;
|
|
21123
21682
|
}
|
|
21124
|
-
if ((symbol.flags &
|
|
21683
|
+
if ((symbol.flags & ts29.SymbolFlags.Alias) !== 0) {
|
|
21125
21684
|
symbol = checker.getAliasedSymbol(symbol);
|
|
21126
21685
|
}
|
|
21127
21686
|
return (symbol.flags & ENUM_SYMBOL_FLAGS) !== 0;
|
|
@@ -24766,7 +25325,7 @@ var OPERATIONAL_ROLES = /* @__PURE__ */ new Set([
|
|
|
24766
25325
|
"timeout",
|
|
24767
25326
|
"interval"
|
|
24768
25327
|
]);
|
|
24769
|
-
var
|
|
25328
|
+
var MAX_ALIAS_DEPTH2 = 16;
|
|
24770
25329
|
var PREFER_NOMINAL_ID_TYPES_DOCUMENTATION = {
|
|
24771
25330
|
defaultLevel: "error",
|
|
24772
25331
|
summary: "Distinguish identifier roles sharing primitive types at callable boundaries.",
|
|
@@ -24864,7 +25423,7 @@ function typeDefinitions(node, context) {
|
|
|
24864
25423
|
return [];
|
|
24865
25424
|
}
|
|
24866
25425
|
function rawCarrier(node, context, depth = 0) {
|
|
24867
|
-
if (node === void 0 || depth >=
|
|
25426
|
+
if (node === void 0 || depth >= MAX_ALIAS_DEPTH2) return void 0;
|
|
24868
25427
|
switch (node.type) {
|
|
24869
25428
|
case AST_NODE_TYPES124.TSStringKeyword:
|
|
24870
25429
|
return "string";
|
|
@@ -26355,7 +26914,7 @@ import {
|
|
|
26355
26914
|
ASTUtils as ASTUtils83,
|
|
26356
26915
|
ESLintUtils as ESLintUtils22
|
|
26357
26916
|
} from "@typescript-eslint/utils";
|
|
26358
|
-
import
|
|
26917
|
+
import ts30 from "typescript";
|
|
26359
26918
|
var PREFER_NULLISH_FILTER_PREDICATE_DOCUMENTATION = {
|
|
26360
26919
|
summary: "Prefer an explicit nullish predicate when `filter(Boolean)` removes only nullish values but does not narrow the result type.",
|
|
26361
26920
|
rationale: "An explicit nullish predicate preserves the same runtime elements while letting TypeScript remove `null` and `undefined` from the result.",
|
|
@@ -26418,23 +26977,23 @@ function isBuiltinArrayFilter(node, services) {
|
|
|
26418
26977
|
const symbol = checker.getSymbolAtLocation(property) ?? checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(node.object)).getProperty("filter");
|
|
26419
26978
|
return symbol?.declarations?.some((declaration) => {
|
|
26420
26979
|
const owner = declaration.parent;
|
|
26421
|
-
return
|
|
26980
|
+
return ts30.isInterfaceDeclaration(owner) && (owner.name.text === "Array" || owner.name.text === "ReadonlyArray") && services.program.isSourceFileDefaultLibrary(owner.getSourceFile());
|
|
26422
26981
|
}) ?? false;
|
|
26423
26982
|
}
|
|
26424
26983
|
function arrayElementType(node, services) {
|
|
26425
26984
|
const checker = services.program.getTypeChecker();
|
|
26426
26985
|
const receiver = services.esTreeNodeToTSNodeMap.get(node);
|
|
26427
|
-
return checker.getIndexTypeOfType(checker.getTypeAtLocation(receiver),
|
|
26986
|
+
return checker.getIndexTypeOfType(checker.getTypeAtLocation(receiver), ts30.IndexKind.Number) ?? null;
|
|
26428
26987
|
}
|
|
26429
|
-
var NULLISH_FLAGS =
|
|
26430
|
-
var UNKNOWN_FLAGS =
|
|
26988
|
+
var NULLISH_FLAGS = ts30.TypeFlags.Null | ts30.TypeFlags.Undefined;
|
|
26989
|
+
var UNKNOWN_FLAGS = ts30.TypeFlags.Any | ts30.TypeFlags.Unknown | ts30.TypeFlags.TypeParameter | ts30.TypeFlags.Intersection | ts30.TypeFlags.Enum | ts30.TypeFlags.EnumLiteral;
|
|
26431
26990
|
function isNullishPlusTruthy(type, checker, falsyBrowserObject) {
|
|
26432
26991
|
const members = type.isUnion() ? type.types : [type];
|
|
26433
26992
|
let sawNullish = false;
|
|
26434
26993
|
for (const member3 of members) {
|
|
26435
26994
|
if ((member3.flags & NULLISH_FLAGS) !== 0) {
|
|
26436
26995
|
sawNullish = true;
|
|
26437
|
-
} else if ((member3.flags &
|
|
26996
|
+
} else if ((member3.flags & ts30.TypeFlags.Never) === 0 && !isProvablyTruthy(member3, checker, falsyBrowserObject)) {
|
|
26438
26997
|
return false;
|
|
26439
26998
|
}
|
|
26440
26999
|
}
|
|
@@ -26442,7 +27001,7 @@ function isNullishPlusTruthy(type, checker, falsyBrowserObject) {
|
|
|
26442
27001
|
}
|
|
26443
27002
|
function isProvablyTruthy(type, checker, falsyBrowserObject) {
|
|
26444
27003
|
if ((type.flags & UNKNOWN_FLAGS) !== 0) return false;
|
|
26445
|
-
if ((type.flags &
|
|
27004
|
+
if ((type.flags & ts30.TypeFlags.Object) !== 0) {
|
|
26446
27005
|
if (falsyBrowserObject !== null && checker.isTypeAssignableTo(falsyBrowserObject, type)) return false;
|
|
26447
27006
|
return ![
|
|
26448
27007
|
checker.getStringType(),
|
|
@@ -26451,18 +27010,18 @@ function isProvablyTruthy(type, checker, falsyBrowserObject) {
|
|
|
26451
27010
|
checker.getBooleanType()
|
|
26452
27011
|
].some((primitive) => checker.isTypeAssignableTo(primitive, type));
|
|
26453
27012
|
}
|
|
26454
|
-
if ((type.flags & (
|
|
26455
|
-
if ((type.flags &
|
|
27013
|
+
if ((type.flags & (ts30.TypeFlags.ESSymbol | ts30.TypeFlags.UniqueESSymbol)) !== 0) return true;
|
|
27014
|
+
if ((type.flags & ts30.TypeFlags.BooleanLiteral) !== 0) {
|
|
26456
27015
|
return type.intrinsicName === "true";
|
|
26457
27016
|
}
|
|
26458
|
-
if ((type.flags &
|
|
27017
|
+
if ((type.flags & ts30.TypeFlags.StringLiteral) !== 0) {
|
|
26459
27018
|
return type.value.length > 0;
|
|
26460
27019
|
}
|
|
26461
|
-
if ((type.flags &
|
|
27020
|
+
if ((type.flags & ts30.TypeFlags.NumberLiteral) !== 0) {
|
|
26462
27021
|
const value = type.value;
|
|
26463
27022
|
return value !== 0 && !Number.isNaN(value);
|
|
26464
27023
|
}
|
|
26465
|
-
if ((type.flags &
|
|
27024
|
+
if ((type.flags & ts30.TypeFlags.BigIntLiteral) !== 0) {
|
|
26466
27025
|
return type.value.base10Value !== "0";
|
|
26467
27026
|
}
|
|
26468
27027
|
return false;
|
|
@@ -26518,7 +27077,7 @@ var prefer_nullish_filter_predicate_default = createRule({
|
|
|
26518
27077
|
if (services === null) return {};
|
|
26519
27078
|
const program = services.program;
|
|
26520
27079
|
const checker = program.getTypeChecker();
|
|
26521
|
-
const browserCollection = checker.resolveName("HTMLAllCollection", void 0,
|
|
27080
|
+
const browserCollection = checker.resolveName("HTMLAllCollection", void 0, ts30.SymbolFlags.Type, false);
|
|
26522
27081
|
const falsyBrowserObject = browserCollection?.declarations?.some((declaration) => program.isSourceFileDefaultLibrary(declaration.getSourceFile())) === true ? checker.getDeclaredTypeOfSymbol(browserCollection) : null;
|
|
26523
27082
|
return {
|
|
26524
27083
|
CallExpression(node) {
|
|
@@ -26556,7 +27115,7 @@ import {
|
|
|
26556
27115
|
ESLintUtils as ESLintUtils23,
|
|
26557
27116
|
AST_NODE_TYPES as AST_NODE_TYPES133
|
|
26558
27117
|
} from "@typescript-eslint/utils";
|
|
26559
|
-
import * as
|
|
27118
|
+
import * as ts31 from "typescript";
|
|
26560
27119
|
var PREFER_AWAIT_IN_ASYNC_RETURN_DOCUMENTATION = {
|
|
26561
27120
|
summary: "Prefer explicit `await` for proven Promise `.then` calls; the default scope checks direct async returns.",
|
|
26562
27121
|
rationale: "Promise callback chains mix explicit async control flow with nested callbacks, making sequencing and failure handling harder to read.",
|
|
@@ -26640,7 +27199,7 @@ function isProvenPromiseLike(node, services) {
|
|
|
26640
27199
|
return members.every((member3) => isBuiltInPromiseType(member3, services));
|
|
26641
27200
|
}
|
|
26642
27201
|
function isBuiltInPromiseType(type, services) {
|
|
26643
|
-
if ((type.flags & (
|
|
27202
|
+
if ((type.flags & (ts31.TypeFlags.Any | ts31.TypeFlags.Unknown | ts31.TypeFlags.Never)) !== 0) {
|
|
26644
27203
|
return false;
|
|
26645
27204
|
}
|
|
26646
27205
|
const thenSymbol = services.program.getTypeChecker().getPropertyOfType(type, "then");
|
|
@@ -26649,7 +27208,7 @@ function isBuiltInPromiseType(type, services) {
|
|
|
26649
27208
|
return declarations.every(
|
|
26650
27209
|
(declaration) => {
|
|
26651
27210
|
let owner = declaration.parent;
|
|
26652
|
-
while (owner !== void 0 && !
|
|
27211
|
+
while (owner !== void 0 && !ts31.isInterfaceDeclaration(owner)) {
|
|
26653
27212
|
owner = owner.parent;
|
|
26654
27213
|
}
|
|
26655
27214
|
return owner !== void 0 && (owner.name.text === "Promise" || owner.name.text === "PromiseLike") && services.program.isSourceFileDefaultLibrary(owner.getSourceFile());
|
|
@@ -27433,7 +27992,7 @@ var prefer_shared_zod_enum_default = createRule({
|
|
|
27433
27992
|
|
|
27434
27993
|
// src/rules/prefer-switch-for-repeated-equality.ts
|
|
27435
27994
|
import { AST_NODE_TYPES as AST_NODE_TYPES137, ASTUtils as ASTUtils88, ESLintUtils as ESLintUtils24 } from "@typescript-eslint/utils";
|
|
27436
|
-
import
|
|
27995
|
+
import ts32 from "typescript";
|
|
27437
27996
|
var PREFER_SWITCH_FOR_REPEATED_EQUALITY_DOCUMENTATION = {
|
|
27438
27997
|
defaultLevel: "error",
|
|
27439
27998
|
summary: "Prefer switch over long if/else-if chains that compare one value for strict equality.",
|
|
@@ -27513,7 +28072,7 @@ function hasUnsafeSwitchControl(node) {
|
|
|
27513
28072
|
function hasOpenDiscriminant(node, services) {
|
|
27514
28073
|
if (services === null) return false;
|
|
27515
28074
|
const type = services.program.getTypeChecker().getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(node));
|
|
27516
|
-
const openFlags =
|
|
28075
|
+
const openFlags = ts32.TypeFlags.Any | ts32.TypeFlags.Unknown | ts32.TypeFlags.String | ts32.TypeFlags.Number | ts32.TypeFlags.BigInt | ts32.TypeFlags.ESSymbol;
|
|
27517
28076
|
return (type.isUnion() ? type.types : [type]).some((part) => (part.flags & openFlags) !== 0);
|
|
27518
28077
|
}
|
|
27519
28078
|
var prefer_switch_for_repeated_equality_default = createRule({
|
|
@@ -29711,14 +30270,14 @@ import {
|
|
|
29711
30270
|
AST_NODE_TYPES as AST_NODE_TYPES143,
|
|
29712
30271
|
ESLintUtils as ESLintUtils25
|
|
29713
30272
|
} from "@typescript-eslint/utils";
|
|
29714
|
-
import
|
|
30273
|
+
import ts35 from "typescript";
|
|
29715
30274
|
|
|
29716
30275
|
// src/rules/_equivalent-zod-output-contracts.ts
|
|
29717
30276
|
import { isPropertyReadonlyInType, isTupleTypeReference, isTypeReference as isTypeReference3 } from "ts-api-utils";
|
|
29718
|
-
import
|
|
30277
|
+
import ts33 from "typescript";
|
|
29719
30278
|
var MAX_CONTRACT_PAIRS = 128;
|
|
29720
30279
|
var MAX_UNION_MEMBERS = 16;
|
|
29721
|
-
var UNSAFE_TYPES =
|
|
30280
|
+
var UNSAFE_TYPES = ts33.TypeFlags.Any | ts33.TypeFlags.Unknown | ts33.TypeFlags.Never;
|
|
29722
30281
|
function equivalentZodOutputContracts(checker, parsed, contract) {
|
|
29723
30282
|
const comparison2 = { checker, pending: [[parsed, contract]], seen: /* @__PURE__ */ new Map(), pairs: 0 };
|
|
29724
30283
|
while (comparison2.pending.length > 0) {
|
|
@@ -29778,8 +30337,8 @@ function equivalentContainers(comparison2, left, right) {
|
|
|
29778
30337
|
const rightTuple = isTupleTypeReference(right);
|
|
29779
30338
|
if (leftTuple !== rightTuple) return false;
|
|
29780
30339
|
if (leftTuple && rightTuple && (left.target.readonly !== right.target.readonly || left.target.elementFlags.length !== right.target.elementFlags.length || left.target.elementFlags.some((flag, index) => flag !== right.target.elementFlags[index]))) return false;
|
|
29781
|
-
const leftIndex = comparison2.checker.getIndexInfoOfType(left,
|
|
29782
|
-
const rightIndex = comparison2.checker.getIndexInfoOfType(right,
|
|
30340
|
+
const leftIndex = comparison2.checker.getIndexInfoOfType(left, ts33.IndexKind.Number);
|
|
30341
|
+
const rightIndex = comparison2.checker.getIndexInfoOfType(right, ts33.IndexKind.Number);
|
|
29783
30342
|
if (leftIndex?.isReadonly !== rightIndex?.isReadonly) return false;
|
|
29784
30343
|
const leftArguments = comparison2.checker.getTypeArguments(left);
|
|
29785
30344
|
const rightArguments = comparison2.checker.getTypeArguments(right);
|
|
@@ -29789,10 +30348,10 @@ function equivalentContainers(comparison2, left, right) {
|
|
|
29789
30348
|
});
|
|
29790
30349
|
}
|
|
29791
30350
|
function hasClassDeclaration(type) {
|
|
29792
|
-
return type.getSymbol()?.getDeclarations()?.some(
|
|
30351
|
+
return type.getSymbol()?.getDeclarations()?.some(ts33.isClassDeclaration) === true || type.isIntersection() && type.types.some(hasClassDeclaration);
|
|
29793
30352
|
}
|
|
29794
30353
|
function objectLike(type) {
|
|
29795
|
-
return (type.flags &
|
|
30354
|
+
return (type.flags & ts33.TypeFlags.Object) !== 0 || type.isIntersection();
|
|
29796
30355
|
}
|
|
29797
30356
|
function equivalentProperties(comparison2, left, right) {
|
|
29798
30357
|
const { checker } = comparison2;
|
|
@@ -29807,12 +30366,12 @@ function equivalentProperties(comparison2, left, right) {
|
|
|
29807
30366
|
return true;
|
|
29808
30367
|
}
|
|
29809
30368
|
function opaqueObject(checker, type) {
|
|
29810
|
-
return checker.getIndexInfosOfType(type).length > 0 || checker.getSignaturesOfType(type,
|
|
30369
|
+
return checker.getIndexInfosOfType(type).length > 0 || checker.getSignaturesOfType(type, ts33.SignatureKind.Call).length > 0 || checker.getSignaturesOfType(type, ts33.SignatureKind.Construct).length > 0;
|
|
29811
30370
|
}
|
|
29812
30371
|
function equivalentProperty(comparison2, left, right, property, other) {
|
|
29813
30372
|
const { checker } = comparison2;
|
|
29814
30373
|
if (opaqueProperty(property) || opaqueProperty(other)) return false;
|
|
29815
|
-
if ((property.flags &
|
|
30374
|
+
if ((property.flags & ts33.SymbolFlags.Optional) !== (other.flags & ts33.SymbolFlags.Optional)) return false;
|
|
29816
30375
|
if (isPropertyReadonlyInType(left, property.getEscapedName(), checker) !== isPropertyReadonlyInType(right, other.getEscapedName(), checker)) return false;
|
|
29817
30376
|
const declaration = property.valueDeclaration ?? property.getDeclarations()?.[0];
|
|
29818
30377
|
const otherDeclaration = other.valueDeclaration ?? other.getDeclarations()?.[0];
|
|
@@ -29823,39 +30382,39 @@ function equivalentProperty(comparison2, left, right, property, other) {
|
|
|
29823
30382
|
);
|
|
29824
30383
|
}
|
|
29825
30384
|
function opaqueProperty(property) {
|
|
29826
|
-
return property.getDeclarations()?.some((declaration) =>
|
|
30385
|
+
return property.getDeclarations()?.some((declaration) => ts33.isGetAccessorDeclaration(declaration) || ts33.isSetAccessorDeclaration(declaration) || ts33.isMethodDeclaration(declaration) || ts33.isMethodSignature(declaration)) === true;
|
|
29827
30386
|
}
|
|
29828
30387
|
|
|
29829
30388
|
// src/rules/_has-authoritative-output-contract.ts
|
|
29830
|
-
import
|
|
30389
|
+
import ts34 from "typescript";
|
|
29831
30390
|
function hasAuthoritativeOutputContract(checker, output, contract) {
|
|
29832
30391
|
const callable = enclosingCallable(output);
|
|
29833
30392
|
if (callable === void 0) return false;
|
|
29834
30393
|
const authority = { checker, contract };
|
|
29835
|
-
if (
|
|
30394
|
+
if (ts34.isMethodDeclaration(callable) || ts34.isGetAccessorDeclaration(callable)) return memberContract2(authority, callable);
|
|
29836
30395
|
const binding3 = callable.parent;
|
|
29837
|
-
if ((
|
|
29838
|
-
if (
|
|
30396
|
+
if ((ts34.isVariableDeclaration(binding3) || ts34.isPropertyDeclaration(binding3)) && binding3.initializer === callable && binding3.type !== void 0 && callableContract(authority, checker.getTypeFromTypeNode(binding3.type))) return true;
|
|
30397
|
+
if (ts34.isPropertyDeclaration(binding3) && binding3.initializer === callable && memberContract2(authority, binding3)) return true;
|
|
29839
30398
|
const contextual = checker.getContextualType(callable);
|
|
29840
30399
|
return contextual !== void 0 && callableContract(authority, contextual, callable);
|
|
29841
30400
|
}
|
|
29842
30401
|
function enclosingCallable(output) {
|
|
29843
30402
|
for (let current = output; current !== void 0; current = current.parent) {
|
|
29844
|
-
if (
|
|
29845
|
-
if (
|
|
30403
|
+
if (ts34.isMethodDeclaration(current) || ts34.isGetAccessorDeclaration(current) || ts34.isArrowFunction(current) || ts34.isFunctionExpression(current)) return current;
|
|
30404
|
+
if (ts34.isFunctionDeclaration(current) || ts34.isConstructorDeclaration(current) || ts34.isSetAccessorDeclaration(current)) return void 0;
|
|
29846
30405
|
}
|
|
29847
30406
|
return void 0;
|
|
29848
30407
|
}
|
|
29849
30408
|
function memberContract2(authority, member3) {
|
|
29850
|
-
if ((
|
|
30409
|
+
if ((ts34.getCombinedModifierFlags(member3) & (ts34.ModifierFlags.Private | ts34.ModifierFlags.Static)) !== 0 || ts34.isPrivateIdentifier(member3.name)) return false;
|
|
29851
30410
|
const owner = member3.parent;
|
|
29852
30411
|
const name = authority.checker.getSymbolAtLocation(member3.name)?.getName();
|
|
29853
30412
|
if (name === void 0) return false;
|
|
29854
|
-
if (
|
|
30413
|
+
if (ts34.isObjectLiteralExpression(owner)) {
|
|
29855
30414
|
const contextual = authority.checker.getContextualType(owner);
|
|
29856
30415
|
return contextual !== void 0 && propertyContract(authority, contextual, name, member3, member3);
|
|
29857
30416
|
}
|
|
29858
|
-
if (!
|
|
30417
|
+
if (!ts34.isClassDeclaration(owner) && !ts34.isClassExpression(owner)) return false;
|
|
29859
30418
|
for (const clause of owner.heritageClauses ?? []) {
|
|
29860
30419
|
for (const heritage of clause.types) {
|
|
29861
30420
|
if (propertyContract(authority, authority.checker.getTypeAtLocation(heritage), name, member3)) return true;
|
|
@@ -29867,9 +30426,9 @@ function propertyContract(authority, type, name, member3, contextual) {
|
|
|
29867
30426
|
const property = authority.checker.getPropertyOfType(type, name);
|
|
29868
30427
|
if (property === void 0) return false;
|
|
29869
30428
|
const declared = authority.checker.getTypeOfSymbolAtLocation(property, member3);
|
|
29870
|
-
if (!
|
|
30429
|
+
if (!ts34.isGetAccessorDeclaration(member3)) return callableContract(authority, declared, contextual);
|
|
29871
30430
|
return property.getDeclarations()?.some((declaration) => {
|
|
29872
|
-
if (!(
|
|
30431
|
+
if (!(ts34.isPropertySignature(declaration) || ts34.isPropertyDeclaration(declaration) || ts34.isGetAccessorDeclaration(declaration)) || declaration.type === void 0 || declaration === member3) return false;
|
|
29873
30432
|
return returnsContract(authority, contextual === void 0 ? declared : authority.checker.getTypeAtLocation(declaration.type));
|
|
29874
30433
|
}) === true;
|
|
29875
30434
|
}
|
|
@@ -30208,12 +30767,12 @@ function handWrittenObjectDeclaration(symbol) {
|
|
|
30208
30767
|
const [declaration] = declarations;
|
|
30209
30768
|
if (declarations.length !== 1 || declaration === void 0) return null;
|
|
30210
30769
|
const plainMembers = (members) => members.length > 0 && members.every(
|
|
30211
|
-
(member3) =>
|
|
30770
|
+
(member3) => ts35.isPropertySignature(member3) && member3.type !== void 0 && member3.modifiers?.some((modifier) => modifier.kind === ts35.SyntaxKind.ReadonlyKeyword) !== true
|
|
30212
30771
|
);
|
|
30213
|
-
if (
|
|
30772
|
+
if (ts35.isInterfaceDeclaration(declaration) && declaration.typeParameters === void 0 && declaration.heritageClauses === void 0 && plainMembers(declaration.members)) {
|
|
30214
30773
|
return declaration;
|
|
30215
30774
|
}
|
|
30216
|
-
if (
|
|
30775
|
+
if (ts35.isTypeAliasDeclaration(declaration) && declaration.typeParameters === void 0 && ts35.isTypeLiteralNode(declaration.type) && plainMembers(declaration.type.members)) {
|
|
30217
30776
|
return declaration;
|
|
30218
30777
|
}
|
|
30219
30778
|
return null;
|
|
@@ -30296,7 +30855,7 @@ import {
|
|
|
30296
30855
|
ESLintUtils as ESLintUtils26,
|
|
30297
30856
|
AST_NODE_TYPES as AST_NODE_TYPES145
|
|
30298
30857
|
} from "@typescript-eslint/utils";
|
|
30299
|
-
import
|
|
30858
|
+
import ts36 from "typescript";
|
|
30300
30859
|
|
|
30301
30860
|
// src/rules/_empty-assertion-fix.ts
|
|
30302
30861
|
import {
|
|
@@ -30476,7 +31035,7 @@ function isExhaustiveFiniteSwitch(node, services) {
|
|
|
30476
31035
|
const constituents = discriminantType.isUnion() ? discriminantType.types : [discriminantType];
|
|
30477
31036
|
if (!discriminantType.isUnion() || constituents.length < 2) return false;
|
|
30478
31037
|
if (constituents.every(
|
|
30479
|
-
(constituent) => (constituent.flags &
|
|
31038
|
+
(constituent) => (constituent.flags & ts36.TypeFlags.BooleanLiteral) !== 0
|
|
30480
31039
|
)) {
|
|
30481
31040
|
return false;
|
|
30482
31041
|
}
|
|
@@ -30498,7 +31057,7 @@ function isExhaustiveFiniteSwitch(node, services) {
|
|
|
30498
31057
|
return [...expected].every((key) => handled.has(key));
|
|
30499
31058
|
}
|
|
30500
31059
|
function finiteTypeKey(type, checker) {
|
|
30501
|
-
const finiteFlags =
|
|
31060
|
+
const finiteFlags = ts36.TypeFlags.StringLiteral | ts36.TypeFlags.NumberLiteral | ts36.TypeFlags.BooleanLiteral | ts36.TypeFlags.EnumLiteral | ts36.TypeFlags.UniqueESSymbol | ts36.TypeFlags.Null | ts36.TypeFlags.Undefined;
|
|
30502
31061
|
return (type.flags & finiteFlags) !== 0 ? checker.typeToString(type) : null;
|
|
30503
31062
|
}
|
|
30504
31063
|
var require_assert_never_default = createRule({
|