@sarj/eslint-plugin 16.32.1 → 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/index.cjs +969 -415
- package/dist/index.js +969 -415
- 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,10 +2296,10 @@ 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
|
|
@@ -1821,17 +2375,17 @@ function hasPrototypeMutation(source) {
|
|
|
1821
2375
|
const member3 = memberName(node);
|
|
1822
2376
|
if (member3 === "setPrototypeOf" || member3 === "__proto__" || member3 === "hasInstance")
|
|
1823
2377
|
return true;
|
|
1824
|
-
if (
|
|
2378
|
+
if (ts12.isBinaryExpression(node) && node.operatorToken.kind >= ts12.SyntaxKind.FirstAssignment && node.operatorToken.kind <= ts12.SyntaxKind.LastAssignment && memberName(node.left) === "prototype")
|
|
1825
2379
|
return true;
|
|
1826
|
-
return
|
|
2380
|
+
return ts12.forEachChild(node, visit);
|
|
1827
2381
|
}
|
|
1828
2382
|
const mutated = visit(source) === true;
|
|
1829
2383
|
PROTOTYPE_MUTATIONS.set(source, mutated);
|
|
1830
2384
|
return mutated;
|
|
1831
2385
|
}
|
|
1832
2386
|
function memberName(node) {
|
|
1833
|
-
if (
|
|
1834
|
-
if (
|
|
2387
|
+
if (ts12.isPropertyAccessExpression(node)) return node.name.text;
|
|
2388
|
+
if (ts12.isElementAccessExpression(node) && ts12.isStringLiteralLike(node.argumentExpression))
|
|
1835
2389
|
return node.argumentExpression.text;
|
|
1836
2390
|
return null;
|
|
1837
2391
|
}
|
|
@@ -1848,11 +2402,11 @@ function escapedClasses(program, checker, cwd) {
|
|
|
1848
2402
|
const escaped = /* @__PURE__ */ new Set();
|
|
1849
2403
|
const namespaceValues = /* @__PURE__ */ new Map();
|
|
1850
2404
|
function visit(node) {
|
|
1851
|
-
if (
|
|
1852
|
-
if (
|
|
2405
|
+
if (ts12.isTypeNode(node) || ts12.isImportDeclaration(node)) return;
|
|
2406
|
+
if (ts12.isIdentifier(node) || ts12.isPropertyAccessExpression(node) || ts12.isElementAccessExpression(node)) {
|
|
1853
2407
|
recordEscapedReference(checker, node, escaped, namespaceValues, cwd);
|
|
1854
2408
|
}
|
|
1855
|
-
|
|
2409
|
+
ts12.forEachChild(node, visit);
|
|
1856
2410
|
}
|
|
1857
2411
|
for (const source of program.getSourceFiles())
|
|
1858
2412
|
if (ownedSource(source, cwd)) visit(source);
|
|
@@ -1871,7 +2425,7 @@ function recordEscapedReference(checker, node, escaped, namespaceValues, cwd) {
|
|
|
1871
2425
|
if (!namespacePrefix(symbol, node) && !safeClassReference(node))
|
|
1872
2426
|
for (const value of values) escaped.add(value);
|
|
1873
2427
|
}
|
|
1874
|
-
if (
|
|
2428
|
+
if (ts12.isElementAccessExpression(node) && !safeClassReference(node)) {
|
|
1875
2429
|
const receiver = canonicalSymbol(checker, node.expression) ?? checker.getTypeAtLocation(node.expression).getSymbol();
|
|
1876
2430
|
if (receiver !== void 0)
|
|
1877
2431
|
for (const value of ownedClassValues(checker, receiver, cwd))
|
|
@@ -1879,16 +2433,16 @@ function recordEscapedReference(checker, node, escaped, namespaceValues, cwd) {
|
|
|
1879
2433
|
}
|
|
1880
2434
|
}
|
|
1881
2435
|
function ownedClassValues(checker, original, cwd, seen = /* @__PURE__ */ new Set()) {
|
|
1882
|
-
const symbol = original.flags &
|
|
2436
|
+
const symbol = original.flags & ts12.SymbolFlags.Alias ? checker.getAliasedSymbol(original) : original;
|
|
1883
2437
|
const values = /* @__PURE__ */ new Set();
|
|
1884
2438
|
if (seen.has(symbol)) return values;
|
|
1885
2439
|
seen.add(symbol);
|
|
1886
2440
|
if (symbol.declarations?.some(
|
|
1887
|
-
(declaration) =>
|
|
2441
|
+
(declaration) => ts12.isClassDeclaration(declaration) && ownedSource(declaration.getSourceFile(), cwd)
|
|
1888
2442
|
))
|
|
1889
2443
|
values.add(symbol);
|
|
1890
2444
|
if (symbol.declarations?.some(
|
|
1891
|
-
(declaration) => (
|
|
2445
|
+
(declaration) => (ts12.isSourceFile(declaration) || ts12.isModuleDeclaration(declaration)) && ownedSource(declaration.getSourceFile(), cwd)
|
|
1892
2446
|
)) {
|
|
1893
2447
|
for (const exported of checker.getExportsOfModule(symbol)) {
|
|
1894
2448
|
for (const value of ownedClassValues(checker, exported, cwd, seen))
|
|
@@ -1898,16 +2452,16 @@ function ownedClassValues(checker, original, cwd, seen = /* @__PURE__ */ new Set
|
|
|
1898
2452
|
return values;
|
|
1899
2453
|
}
|
|
1900
2454
|
function safeClassReference(node) {
|
|
1901
|
-
let reference =
|
|
1902
|
-
while (
|
|
2455
|
+
let reference = ts12.isPropertyAccessExpression(node.parent) && node.parent.name === node ? node.parent : node;
|
|
2456
|
+
while (ts12.isParenthesizedExpression(reference.parent))
|
|
1903
2457
|
reference = reference.parent;
|
|
1904
2458
|
const parent = reference.parent;
|
|
1905
|
-
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;
|
|
1906
2460
|
}
|
|
1907
2461
|
function namespacePrefix(symbol, node) {
|
|
1908
2462
|
const parent = node.parent;
|
|
1909
|
-
const memberCall = (
|
|
1910
|
-
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;
|
|
1911
2465
|
}
|
|
1912
2466
|
function closedNominalBoundary(program, checker, call, consumer, missing, cwd) {
|
|
1913
2467
|
const { implementation, contractSymbol } = missing;
|
|
@@ -1915,7 +2469,7 @@ function closedNominalBoundary(program, checker, call, consumer, missing, cwd) {
|
|
|
1915
2469
|
const consumerSymbol = consumer.name === void 0 ? void 0 : canonicalSymbol(checker, consumer.name);
|
|
1916
2470
|
if (implementationSymbol === void 0 || consumerSymbol === void 0)
|
|
1917
2471
|
return false;
|
|
1918
|
-
const contract = contractSymbol.declarations?.find(
|
|
2472
|
+
const contract = contractSymbol.declarations?.find(ts12.isClassDeclaration);
|
|
1919
2473
|
if (contract === void 0) return false;
|
|
1920
2474
|
const targets = /* @__PURE__ */ new Set([
|
|
1921
2475
|
consumerSymbol,
|
|
@@ -1937,12 +2491,12 @@ function classHierarchySymbols(checker, declaration, seen = /* @__PURE__ */ new
|
|
|
1937
2491
|
if (symbol === void 0 || seen.has(symbol)) return seen;
|
|
1938
2492
|
seen.add(symbol);
|
|
1939
2493
|
for (const clause of declaration.heritageClauses ?? []) {
|
|
1940
|
-
if (clause.token !==
|
|
2494
|
+
if (clause.token !== ts12.SyntaxKind.ExtendsKeyword) continue;
|
|
1941
2495
|
for (const parent of clause.types) {
|
|
1942
2496
|
const ancestor = canonicalSymbol(
|
|
1943
2497
|
checker,
|
|
1944
2498
|
parent.expression
|
|
1945
|
-
)?.declarations?.find(
|
|
2499
|
+
)?.declarations?.find(ts12.isClassDeclaration);
|
|
1946
2500
|
if (ancestor !== void 0)
|
|
1947
2501
|
classHierarchySymbols(checker, ancestor, seen);
|
|
1948
2502
|
}
|
|
@@ -1967,22 +2521,22 @@ function missingImplementation(checker, signature, parameter, call, argument) {
|
|
|
1967
2521
|
function behavioralContract(checker, type) {
|
|
1968
2522
|
if (type.isUnion()) {
|
|
1969
2523
|
const substantive = type.types.filter(
|
|
1970
|
-
(member3) => (member3.flags & (
|
|
2524
|
+
(member3) => (member3.flags & (ts12.TypeFlags.Null | ts12.TypeFlags.Undefined)) === 0
|
|
1971
2525
|
);
|
|
1972
2526
|
if (substantive.length !== 1) return null;
|
|
1973
2527
|
return behavioralContract(checker, substantive[0]);
|
|
1974
2528
|
}
|
|
1975
|
-
if ((type.flags & (
|
|
2529
|
+
if ((type.flags & (ts12.TypeFlags.Any | ts12.TypeFlags.Unknown)) !== 0)
|
|
1976
2530
|
return null;
|
|
1977
2531
|
const declaration = type.getSymbol()?.declarations?.find(
|
|
1978
|
-
(item) =>
|
|
1979
|
-
(modifier) => modifier.kind ===
|
|
2532
|
+
(item) => ts12.isClassDeclaration(item) && item.modifiers?.some(
|
|
2533
|
+
(modifier) => modifier.kind === ts12.SyntaxKind.AbstractKeyword
|
|
1980
2534
|
)
|
|
1981
2535
|
);
|
|
1982
2536
|
if (declaration === void 0) return null;
|
|
1983
2537
|
return checker.getPropertiesOfType(type).some((property) => {
|
|
1984
2538
|
if (!property.declarations?.some(
|
|
1985
|
-
(member3) =>
|
|
2539
|
+
(member3) => ts12.isMethodSignature(member3) || ts12.isMethodDeclaration(member3)
|
|
1986
2540
|
))
|
|
1987
2541
|
return false;
|
|
1988
2542
|
const propertyType = checker.getTypeOfSymbolAtLocation(
|
|
@@ -1993,15 +2547,15 @@ function behavioralContract(checker, type) {
|
|
|
1993
2547
|
}) ? type : null;
|
|
1994
2548
|
}
|
|
1995
2549
|
function ownedClass(checker, expression) {
|
|
1996
|
-
if (!
|
|
2550
|
+
if (!ts12.isNewExpression(expression)) return null;
|
|
1997
2551
|
const type = checker.getTypeAtLocation(expression);
|
|
1998
|
-
if ((type.flags & (
|
|
2552
|
+
if ((type.flags & (ts12.TypeFlags.Any | ts12.TypeFlags.Unknown)) !== 0)
|
|
1999
2553
|
return null;
|
|
2000
|
-
const declaration = type.getSymbol()?.declarations?.find(
|
|
2554
|
+
const declaration = type.getSymbol()?.declarations?.find(ts12.isClassDeclaration);
|
|
2001
2555
|
const constructed = canonicalSymbol(
|
|
2002
2556
|
checker,
|
|
2003
2557
|
expression.expression
|
|
2004
|
-
)?.declarations?.find(
|
|
2558
|
+
)?.declarations?.find(ts12.isClassDeclaration);
|
|
2005
2559
|
if (declaration === void 0 || declaration !== constructed || declaration.getSourceFile().isDeclarationFile || /(?:^|[/\\])(?:node_modules|vendor|generated)(?:[/\\])/u.test(
|
|
2006
2560
|
declaration.getSourceFile().fileName
|
|
2007
2561
|
))
|
|
@@ -2009,10 +2563,10 @@ function ownedClass(checker, expression) {
|
|
|
2009
2563
|
return declaration;
|
|
2010
2564
|
}
|
|
2011
2565
|
function nominallyInherits(checker, declaration, target, seen) {
|
|
2012
|
-
if (
|
|
2566
|
+
if (ts12.canHaveDecorators(declaration) && ts12.getDecorators(declaration)?.length)
|
|
2013
2567
|
return null;
|
|
2014
2568
|
if (hasPrototypeMutation(declaration.getSourceFile()) || declaration.members.some(
|
|
2015
|
-
(member3) =>
|
|
2569
|
+
(member3) => ts12.isConstructorDeclaration(member3) || ts12.isClassStaticBlockDeclaration(member3) || ts12.isPropertyDeclaration(member3) && member3.initializer !== void 0
|
|
2016
2570
|
))
|
|
2017
2571
|
return null;
|
|
2018
2572
|
const symbol = declaration.name === void 0 ? void 0 : canonicalSymbol(checker, declaration.name);
|
|
@@ -2021,60 +2575,60 @@ function nominallyInherits(checker, declaration, target, seen) {
|
|
|
2021
2575
|
seen.add(symbol);
|
|
2022
2576
|
}
|
|
2023
2577
|
const parents = declaration.heritageClauses?.find(
|
|
2024
|
-
(clause) => clause.token ===
|
|
2578
|
+
(clause) => clause.token === ts12.SyntaxKind.ExtendsKeyword
|
|
2025
2579
|
)?.types;
|
|
2026
2580
|
if (parents === void 0) return false;
|
|
2027
2581
|
if (parents.length !== 1) return null;
|
|
2028
2582
|
const parentSymbol = canonicalSymbol(checker, parents[0].expression);
|
|
2029
2583
|
if (parentSymbol === void 0) return null;
|
|
2030
2584
|
if (parentSymbol === target) return true;
|
|
2031
|
-
const inherited = parentSymbol.declarations?.find(
|
|
2585
|
+
const inherited = parentSymbol.declarations?.find(ts12.isClassDeclaration);
|
|
2032
2586
|
return inherited === void 0 ? null : nominallyInherits(checker, inherited, target, new Set(seen));
|
|
2033
2587
|
}
|
|
2034
2588
|
function hasNominalRejectionGuard(checker, signature, parameter, contract) {
|
|
2035
2589
|
const declaration = signature.getDeclaration();
|
|
2036
|
-
if (declaration === void 0 || !
|
|
2590
|
+
if (declaration === void 0 || !ts12.isConstructorDeclaration(declaration))
|
|
2037
2591
|
return false;
|
|
2038
|
-
if (
|
|
2592
|
+
if (ts12.canHaveDecorators(declaration.parent) && ts12.getDecorators(declaration.parent)?.length)
|
|
2039
2593
|
return false;
|
|
2040
2594
|
if (hasPrototypeMutation(declaration.getSourceFile())) return false;
|
|
2041
2595
|
const first = declaration.body?.statements[0];
|
|
2042
|
-
if (first === void 0 || !
|
|
2596
|
+
if (first === void 0 || !ts12.isIfStatement(first) || !alwaysThrows(first.thenStatement))
|
|
2043
2597
|
return false;
|
|
2044
2598
|
const condition2 = unparenthesized2(first.expression);
|
|
2045
|
-
if (!
|
|
2599
|
+
if (!ts12.isPrefixUnaryExpression(condition2) || condition2.operator !== ts12.SyntaxKind.ExclamationToken)
|
|
2046
2600
|
return false;
|
|
2047
2601
|
const comparison2 = unparenthesized2(condition2.operand);
|
|
2048
|
-
if (!
|
|
2602
|
+
if (!ts12.isBinaryExpression(comparison2) || comparison2.operatorToken.kind !== ts12.SyntaxKind.InstanceOfKeyword)
|
|
2049
2603
|
return false;
|
|
2050
2604
|
if (canonicalSymbol(checker, comparison2.left) !== parameter || canonicalSymbol(checker, comparison2.right) !== contract)
|
|
2051
2605
|
return false;
|
|
2052
|
-
const target = contract.declarations?.find(
|
|
2606
|
+
const target = contract.declarations?.find(ts12.isClassDeclaration);
|
|
2053
2607
|
return target !== void 0 && hasOrdinaryInstanceCheck(checker, target, /* @__PURE__ */ new Set());
|
|
2054
2608
|
}
|
|
2055
2609
|
function unparenthesized2(expression) {
|
|
2056
2610
|
let current = expression;
|
|
2057
|
-
while (
|
|
2611
|
+
while (ts12.isParenthesizedExpression(current)) current = current.expression;
|
|
2058
2612
|
return current;
|
|
2059
2613
|
}
|
|
2060
2614
|
function alwaysThrows(statement) {
|
|
2061
|
-
return
|
|
2615
|
+
return ts12.isThrowStatement(statement) || ts12.isBlock(statement) && statement.statements.length === 1 && ts12.isThrowStatement(statement.statements[0]);
|
|
2062
2616
|
}
|
|
2063
2617
|
function hasOrdinaryInstanceCheck(checker, declaration, seen) {
|
|
2064
|
-
if (seen.has(declaration) ||
|
|
2618
|
+
if (seen.has(declaration) || ts12.getDecorators(declaration)?.length || hasPrototypeMutation(declaration.getSourceFile()) || declaration.members.some(ts12.isClassStaticBlockDeclaration))
|
|
2065
2619
|
return false;
|
|
2066
2620
|
seen.add(declaration);
|
|
2067
2621
|
if (declaration.members.some(
|
|
2068
|
-
(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)
|
|
2069
2623
|
))
|
|
2070
2624
|
return false;
|
|
2071
2625
|
for (const clause of declaration.heritageClauses ?? []) {
|
|
2072
|
-
if (clause.token !==
|
|
2626
|
+
if (clause.token !== ts12.SyntaxKind.ExtendsKeyword) continue;
|
|
2073
2627
|
for (const parent of clause.types) {
|
|
2074
2628
|
const ancestor = canonicalSymbol(
|
|
2075
2629
|
checker,
|
|
2076
2630
|
parent.expression
|
|
2077
|
-
)?.declarations?.find(
|
|
2631
|
+
)?.declarations?.find(ts12.isClassDeclaration);
|
|
2078
2632
|
if (ancestor === void 0 || !hasOrdinaryInstanceCheck(checker, ancestor, seen))
|
|
2079
2633
|
return false;
|
|
2080
2634
|
}
|
|
@@ -2082,9 +2636,9 @@ function hasOrdinaryInstanceCheck(checker, declaration, seen) {
|
|
|
2082
2636
|
return true;
|
|
2083
2637
|
}
|
|
2084
2638
|
function canonicalSymbol(checker, node) {
|
|
2085
|
-
if (
|
|
2639
|
+
if (ts12.isParenthesizedExpression(node)) node = unparenthesized2(node);
|
|
2086
2640
|
const symbol = checker.getSymbolAtLocation(node);
|
|
2087
|
-
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;
|
|
2088
2642
|
}
|
|
2089
2643
|
var require_explicit_contract_implementation_default = createRule({
|
|
2090
2644
|
name: "require-explicit-contract-implementation",
|
|
@@ -2109,11 +2663,11 @@ var require_explicit_contract_implementation_default = createRule({
|
|
|
2109
2663
|
const checker = services.program.getTypeChecker();
|
|
2110
2664
|
function inspect(node) {
|
|
2111
2665
|
const tsNode = services.esTreeNodeToTSNodeMap.get(node);
|
|
2112
|
-
if (!
|
|
2666
|
+
if (!ts12.isNewExpression(tsNode)) return;
|
|
2113
2667
|
const consumer = canonicalSymbol(
|
|
2114
2668
|
checker,
|
|
2115
2669
|
tsNode.expression
|
|
2116
|
-
)?.declarations?.find(
|
|
2670
|
+
)?.declarations?.find(ts12.isClassDeclaration);
|
|
2117
2671
|
if (consumer === void 0) return;
|
|
2118
2672
|
const signature = checker.getResolvedSignature(tsNode);
|
|
2119
2673
|
if (signature === void 0 || signature.getDeclaration()?.parent !== consumer)
|
|
@@ -2141,7 +2695,7 @@ var require_explicit_contract_implementation_default = createRule({
|
|
|
2141
2695
|
))
|
|
2142
2696
|
continue;
|
|
2143
2697
|
const contract = missing.contractSymbol.declarations?.find(
|
|
2144
|
-
|
|
2698
|
+
ts12.isClassDeclaration
|
|
2145
2699
|
);
|
|
2146
2700
|
context.report({
|
|
2147
2701
|
node: argument,
|
|
@@ -3442,7 +3996,7 @@ import {
|
|
|
3442
3996
|
ASTUtils as ASTUtils7,
|
|
3443
3997
|
ESLintUtils as ESLintUtils7
|
|
3444
3998
|
} from "@typescript-eslint/utils";
|
|
3445
|
-
import
|
|
3999
|
+
import ts13 from "typescript";
|
|
3446
4000
|
var PREFER_TYPED_REFLECTION_DOCUMENTATION = {
|
|
3447
4001
|
summary: "Prefer typed access when Reflect.get or Reflect.apply discards a known contract.",
|
|
3448
4002
|
rationale: "Reflect.get and Reflect.apply can accept property or argument mistakes that normal typed access catches.",
|
|
@@ -3495,7 +4049,7 @@ var PREFER_TYPED_REFLECTION_DOCUMENTATION = {
|
|
|
3495
4049
|
};
|
|
3496
4050
|
function knownType(type) {
|
|
3497
4051
|
if (type.isUnion()) return type.types.every(knownType);
|
|
3498
|
-
return (type.flags & (
|
|
4052
|
+
return (type.flags & (ts13.TypeFlags.Any | ts13.TypeFlags.Unknown | ts13.TypeFlags.TypeParameter | ts13.TypeFlags.Never)) === 0;
|
|
3499
4053
|
}
|
|
3500
4054
|
var prefer_typed_reflection_default = createRule({
|
|
3501
4055
|
name: "prefer-typed-reflection",
|
|
@@ -3547,7 +4101,7 @@ var prefer_typed_reflection_default = createRule({
|
|
|
3547
4101
|
const key = unwrapExpression(writtenKey);
|
|
3548
4102
|
const name = staticString(key) ?? (key.type === AST_NODE_TYPES18.Literal && typeof key.value === "number" ? String(key.value) : null);
|
|
3549
4103
|
const members = type.isUnion() ? type.types : [type];
|
|
3550
|
-
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;
|
|
3551
4105
|
return `(${context.sourceCode.getText(target)})[${context.sourceCode.getText(writtenKey)}]`;
|
|
3552
4106
|
};
|
|
3553
4107
|
return {
|
|
@@ -3575,7 +4129,7 @@ import {
|
|
|
3575
4129
|
AST_NODE_TYPES as AST_NODE_TYPES20,
|
|
3576
4130
|
ESLintUtils as ESLintUtils8
|
|
3577
4131
|
} from "@typescript-eslint/utils";
|
|
3578
|
-
import
|
|
4132
|
+
import ts14 from "typescript";
|
|
3579
4133
|
|
|
3580
4134
|
// src/rules/_unused-private-binding.ts
|
|
3581
4135
|
import { AST_NODE_TYPES as AST_NODE_TYPES19 } from "@typescript-eslint/utils";
|
|
@@ -3676,21 +4230,21 @@ var NO_BROAD_RETURN_TYPE_DOCUMENTATION = {
|
|
|
3676
4230
|
]
|
|
3677
4231
|
};
|
|
3678
4232
|
function isBroad(type, checker) {
|
|
3679
|
-
if ((type.flags & (
|
|
4233
|
+
if ((type.flags & (ts14.TypeFlags.Unknown | ts14.TypeFlags.NonPrimitive)) !== 0)
|
|
3680
4234
|
return true;
|
|
3681
4235
|
const indexes = checker.getIndexInfosOfType(type);
|
|
3682
|
-
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);
|
|
3683
4237
|
}
|
|
3684
4238
|
function hasKnownContract(type, checker) {
|
|
3685
4239
|
if (type.isUnion())
|
|
3686
4240
|
return type.types.every((part) => hasKnownContract(part, checker));
|
|
3687
|
-
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;
|
|
3688
4242
|
if ((type.flags & excluded) !== 0 || isBroad(type, checker)) return false;
|
|
3689
|
-
return (type.flags &
|
|
4243
|
+
return (type.flags & ts14.TypeFlags.Object) === 0 || type.getProperties().length > 0;
|
|
3690
4244
|
}
|
|
3691
4245
|
function isOpaque(type, checker) {
|
|
3692
4246
|
if (type.isUnion()) return type.types.some((part) => isOpaque(part, checker));
|
|
3693
|
-
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);
|
|
3694
4248
|
}
|
|
3695
4249
|
var no_broad_return_type_default = createRule({
|
|
3696
4250
|
name: "no-broad-return-type",
|
|
@@ -3717,7 +4271,7 @@ var no_broad_return_type_default = createRule({
|
|
|
3717
4271
|
const type = checker.getTypeAtLocation(
|
|
3718
4272
|
services.esTreeNodeToTSNodeMap.get(node)
|
|
3719
4273
|
);
|
|
3720
|
-
return (type.flags &
|
|
4274
|
+
return (type.flags & ts14.TypeFlags.TypeParameter) !== 0 ? type : checker.getAwaitedType(type) ?? type;
|
|
3721
4275
|
};
|
|
3722
4276
|
const inspectReturn = (value) => {
|
|
3723
4277
|
const frame = frames.at(-1);
|
|
@@ -3766,7 +4320,7 @@ import {
|
|
|
3766
4320
|
ASTUtils as ASTUtils9,
|
|
3767
4321
|
ESLintUtils as ESLintUtils9
|
|
3768
4322
|
} from "@typescript-eslint/utils";
|
|
3769
|
-
import
|
|
4323
|
+
import ts15 from "typescript";
|
|
3770
4324
|
|
|
3771
4325
|
// src/rules/_literal-identity-reduce-fix.ts
|
|
3772
4326
|
import {
|
|
@@ -3929,7 +4483,7 @@ var no_reduce_accumulator_copy_default = createRule({
|
|
|
3929
4483
|
services.esTreeNodeToTSNodeMap.get(node)
|
|
3930
4484
|
);
|
|
3931
4485
|
const declaration = signature?.declaration;
|
|
3932
|
-
if (!declaration || !program.isSourceFileDefaultLibrary(declaration.getSourceFile()) || !
|
|
4486
|
+
if (!declaration || !program.isSourceFileDefaultLibrary(declaration.getSourceFile()) || !ts15.isInterfaceDeclaration(declaration.parent) || !["Array", "ReadonlyArray"].includes(declaration.parent.name.text))
|
|
3933
4487
|
return;
|
|
3934
4488
|
const accumulator = context.sourceCode.getDeclaredVariables(callback).find((variable) => variable.identifiers.includes(parameter));
|
|
3935
4489
|
if (!accumulator || accumulator.references.some((reference) => reference.isWrite()))
|
|
@@ -3991,7 +4545,7 @@ var no_reduce_accumulator_copy_default = createRule({
|
|
|
3991
4545
|
|
|
3992
4546
|
// src/rules/no-known-value-widening.ts
|
|
3993
4547
|
import { AST_NODE_TYPES as AST_NODE_TYPES23, ESLintUtils as ESLintUtils10 } from "@typescript-eslint/utils";
|
|
3994
|
-
import
|
|
4548
|
+
import ts16 from "typescript";
|
|
3995
4549
|
var NO_KNOWN_VALUE_WIDENING_DOCUMENTATION = {
|
|
3996
4550
|
summary: "Preserve a known value's contract instead of widening a local binding to unknown, object, or an unknown-valued dictionary.",
|
|
3997
4551
|
rationale: "Erasing a typed value's fields forces downstream code to rediscover the same contract through casts, reflection, or representation checks.",
|
|
@@ -4018,13 +4572,13 @@ var NO_KNOWN_VALUE_WIDENING_DOCUMENTATION = {
|
|
|
4018
4572
|
]
|
|
4019
4573
|
};
|
|
4020
4574
|
function erasesContract(type, checker) {
|
|
4021
|
-
if ((type.flags & (
|
|
4575
|
+
if ((type.flags & (ts16.TypeFlags.Unknown | ts16.TypeFlags.NonPrimitive)) !== 0) return true;
|
|
4022
4576
|
const indexes = checker.getIndexInfosOfType(type);
|
|
4023
|
-
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);
|
|
4024
4578
|
}
|
|
4025
4579
|
function hasUnknownContract(type, checker) {
|
|
4026
4580
|
if (type.isUnionOrIntersection()) return type.types.some((part) => hasUnknownContract(part, checker));
|
|
4027
|
-
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);
|
|
4028
4582
|
}
|
|
4029
4583
|
var no_known_value_widening_default = createRule({
|
|
4030
4584
|
name: "no-known-value-widening",
|
|
@@ -4066,7 +4620,7 @@ var no_known_value_widening_default = createRule({
|
|
|
4066
4620
|
// src/rules/no-invalid-typed-mutation.ts
|
|
4067
4621
|
import { ASTUtils as ASTUtils10, AST_NODE_TYPES as AST_NODE_TYPES24, ESLintUtils as ESLintUtils11 } from "@typescript-eslint/utils";
|
|
4068
4622
|
import { isObjectType, isTypeReference } from "ts-api-utils";
|
|
4069
|
-
import
|
|
4623
|
+
import ts17 from "typescript";
|
|
4070
4624
|
var NO_INVALID_TYPED_MUTATION_DOCUMENTATION = {
|
|
4071
4625
|
summary: "Keep native object mutation APIs from writing incompatible values into declared property types.",
|
|
4072
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.",
|
|
@@ -4224,21 +4778,21 @@ function keepsMutableDescriptor(call, method) {
|
|
|
4224
4778
|
function declaredTargetType(node, checker) {
|
|
4225
4779
|
const symbol = checker.getSymbolAtLocation(node);
|
|
4226
4780
|
const declaration = symbol?.valueDeclaration;
|
|
4227
|
-
if (declaration === void 0 || !(
|
|
4781
|
+
if (declaration === void 0 || !(ts17.isVariableDeclaration(declaration) || ts17.isParameter(declaration)) || declaration.type === void 0) return void 0;
|
|
4228
4782
|
const type = checker.getTypeFromTypeNode(declaration.type);
|
|
4229
|
-
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;
|
|
4230
4784
|
return type;
|
|
4231
4785
|
}
|
|
4232
4786
|
function typedDataProperty(property) {
|
|
4233
4787
|
const declarations = property.getDeclarations();
|
|
4234
|
-
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);
|
|
4235
4789
|
}
|
|
4236
4790
|
function propertyWriteType(target, property, node, checker, exact) {
|
|
4237
4791
|
const exposed = checker.getTypeOfSymbolAtLocation(property, node);
|
|
4238
|
-
if (!exact || (property.flags &
|
|
4239
|
-
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;
|
|
4240
4794
|
const declaration = property.getDeclarations()?.[0];
|
|
4241
|
-
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;
|
|
4242
4796
|
const authored = checker.getTypeFromTypeNode(declaration.type);
|
|
4243
4797
|
return definiteType(authored, checker) && checker.isTypeAssignableTo(authored, exposed) ? authored : exposed;
|
|
4244
4798
|
}
|
|
@@ -4246,13 +4800,13 @@ function definiteType(type, checker, seen = /* @__PURE__ */ new Set()) {
|
|
|
4246
4800
|
if (seen.has(type)) return true;
|
|
4247
4801
|
if (seen.size >= 32) return false;
|
|
4248
4802
|
seen.add(type);
|
|
4249
|
-
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;
|
|
4250
4804
|
if ((type.flags & unsafe) !== 0) return false;
|
|
4251
4805
|
if (type.isUnionOrIntersection()) return type.types.every((part) => definiteType(part, checker, seen));
|
|
4252
4806
|
const arguments_ = isTypeReference(type) ? checker.getTypeArguments(type) : type.aliasTypeArguments ?? [];
|
|
4253
4807
|
if (!arguments_.every((argument) => definiteType(argument, checker, seen))) return false;
|
|
4254
4808
|
if (!definiteSignatures(type, checker, seen)) return false;
|
|
4255
|
-
if (isTypeReference(type) || (type.flags &
|
|
4809
|
+
if (isTypeReference(type) || (type.flags & ts17.TypeFlags.Object) === 0) return true;
|
|
4256
4810
|
return type.getProperties().every((property) => {
|
|
4257
4811
|
const declaration = property.valueDeclaration ?? property.getDeclarations()?.[0];
|
|
4258
4812
|
return declaration !== void 0 && definiteType(checker.getTypeOfSymbolAtLocation(property, declaration), checker, seen);
|
|
@@ -4336,33 +4890,33 @@ function plainProperties(node) {
|
|
|
4336
4890
|
|
|
4337
4891
|
// src/rules/no-contradictory-type-predicate.ts
|
|
4338
4892
|
import { ASTUtils as ASTUtils12, AST_NODE_TYPES as AST_NODE_TYPES26, ESLintUtils as ESLintUtils12 } from "@typescript-eslint/utils";
|
|
4339
|
-
import
|
|
4893
|
+
import ts20 from "typescript";
|
|
4340
4894
|
|
|
4341
4895
|
// src/rules/_has-separate-predicate-contract.ts
|
|
4342
|
-
import
|
|
4896
|
+
import ts18 from "typescript";
|
|
4343
4897
|
function hasSeparatePredicateContract(node, checker) {
|
|
4344
|
-
if (
|
|
4345
|
-
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;
|
|
4346
4900
|
if (node.name !== void 0 && (checker.getSymbolAtLocation(node.name)?.getDeclarations()?.length ?? 0) > 1) return true;
|
|
4347
|
-
if (!
|
|
4901
|
+
if (!ts18.isMethodDeclaration(node)) return false;
|
|
4348
4902
|
const owner = node.parent;
|
|
4349
|
-
if (
|
|
4350
|
-
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;
|
|
4351
4905
|
}
|
|
4352
4906
|
|
|
4353
4907
|
// src/rules/_contradictory-array-predicate.ts
|
|
4354
4908
|
import { AST_NODE_TYPES as AST_NODE_TYPES25, ASTUtils as ASTUtils11 } from "@typescript-eslint/utils";
|
|
4355
|
-
import
|
|
4909
|
+
import ts19 from "typescript";
|
|
4356
4910
|
import { isTypeReference as isTypeReference2 } from "ts-api-utils";
|
|
4357
4911
|
var HOST_GLOBALS = ["globalThis", "window", "self", "global"];
|
|
4358
|
-
var PRIMITIVE_ELEMENTS =
|
|
4359
|
-
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__"]);
|
|
4360
4914
|
function contradictoryArrayPredicate(sourceCode, services) {
|
|
4361
4915
|
const checker = services.program.getTypeChecker();
|
|
4362
4916
|
const stable2 = /* @__PURE__ */ new WeakMap();
|
|
4363
4917
|
let constructorCapability = false;
|
|
4364
4918
|
function matches(expression, parameter, input, target) {
|
|
4365
|
-
if ((input.flags &
|
|
4919
|
+
if ((input.flags & ts19.TypeFlags.Unknown) === 0 || !plainPrimitiveArray(target, checker)) return false;
|
|
4366
4920
|
const call = unwrapExpression(expression);
|
|
4367
4921
|
if (call.type !== AST_NODE_TYPES25.CallExpression || call.optional || call.arguments.length !== 1) return false;
|
|
4368
4922
|
const argument = call.arguments[0];
|
|
@@ -4390,7 +4944,7 @@ function contradictoryArrayPredicate(sourceCode, services) {
|
|
|
4390
4944
|
function plainPrimitiveArray(target, checker) {
|
|
4391
4945
|
if (!checker.isArrayType(target) || !isTypeReference2(target)) return false;
|
|
4392
4946
|
const [element] = checker.getTypeArguments(target);
|
|
4393
|
-
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;
|
|
4394
4948
|
}
|
|
4395
4949
|
function nativeBinding(identifier, sourceCode) {
|
|
4396
4950
|
const binding3 = ASTUtils11.findVariable(sourceCode.getScope(identifier), identifier.name);
|
|
@@ -4422,7 +4976,7 @@ function ordinaryObjectUse(node) {
|
|
|
4422
4976
|
const member3 = node.parent;
|
|
4423
4977
|
if (member3?.type !== AST_NODE_TYPES25.MemberExpression || member3.object !== node) return false;
|
|
4424
4978
|
const name = ASTUtils11.getPropertyName(member3);
|
|
4425
|
-
return name !== null && !
|
|
4979
|
+
return name !== null && !OBJECT_REFLECTION2.has(name);
|
|
4426
4980
|
}
|
|
4427
4981
|
function ordinaryArrayReference(reference) {
|
|
4428
4982
|
if (reference.isWrite()) return false;
|
|
@@ -4455,11 +5009,11 @@ function ordinaryHostReference(reference) {
|
|
|
4455
5009
|
// src/rules/no-contradictory-type-predicate.ts
|
|
4456
5010
|
var RUNTIME_KINDS = /* @__PURE__ */ new Set(["string", "number", "bigint", "boolean", "symbol", "undefined", "object", "function"]);
|
|
4457
5011
|
var PRIMITIVE_KINDS = [
|
|
4458
|
-
[
|
|
4459
|
-
[
|
|
4460
|
-
[
|
|
4461
|
-
[
|
|
4462
|
-
[
|
|
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"]
|
|
4463
5017
|
];
|
|
4464
5018
|
var NO_CONTRADICTORY_TYPE_PREDICATE_DOCUMENTATION = {
|
|
4465
5019
|
summary: "Keep explicit type predicates consistent with their primitive or native array membership check.",
|
|
@@ -4560,10 +5114,10 @@ var no_contradictory_type_predicate_default = createRule({
|
|
|
4560
5114
|
}
|
|
4561
5115
|
});
|
|
4562
5116
|
function contradiction(input, target, checked, checker, strictNulls) {
|
|
4563
|
-
if (strictNulls && checked === "object" && (target.flags &
|
|
5117
|
+
if (strictNulls && checked === "object" && (target.flags & ts20.TypeFlags.NonPrimitive) !== 0 && admitsNull(input)) return "nullAccepted";
|
|
4564
5118
|
const possible = inputKinds(input, checker);
|
|
4565
5119
|
if (possible === void 0 || !possible.has(checked)) return void 0;
|
|
4566
|
-
if ((target.flags &
|
|
5120
|
+
if ((target.flags & ts20.TypeFlags.Never) !== 0) return "contradictoryPredicate";
|
|
4567
5121
|
const promised = primitiveKinds(target, checker, false);
|
|
4568
5122
|
if (promised !== void 0) {
|
|
4569
5123
|
return !promised.has(checked) || [...promised].some((kind) => kind !== checked && possible.has(kind)) ? "contradictoryPredicate" : void 0;
|
|
@@ -4571,18 +5125,18 @@ function contradiction(input, target, checked, checker, strictNulls) {
|
|
|
4571
5125
|
return closedLiteralContradiction(input, target, checked, checker) ? "closedLiteralPredicate" : void 0;
|
|
4572
5126
|
}
|
|
4573
5127
|
function admitsNull(input) {
|
|
4574
|
-
return (input.flags &
|
|
5128
|
+
return (input.flags & ts20.TypeFlags.Unknown) !== 0 || (input.isUnion() ? input.types : [input]).some((member3) => (member3.flags & ts20.TypeFlags.Null) !== 0);
|
|
4575
5129
|
}
|
|
4576
5130
|
function closedLiteralContradiction(input, target, checked, checker) {
|
|
4577
5131
|
const members = target.isUnion() ? target.types : [target];
|
|
4578
|
-
const literalFlags =
|
|
5132
|
+
const literalFlags = ts20.TypeFlags.StringLiteral | ts20.TypeFlags.NumberLiteral | ts20.TypeFlags.BigIntLiteral | ts20.TypeFlags.BooleanLiteral | ts20.TypeFlags.Null | ts20.TypeFlags.Undefined;
|
|
4579
5133
|
if (!members.every((member3) => (member3.flags & literalFlags) !== 0)) return false;
|
|
4580
5134
|
if (members.some((member3) => literalKind(member3, checker) !== checked)) return true;
|
|
4581
|
-
if ((input.flags &
|
|
5135
|
+
if ((input.flags & ts20.TypeFlags.Unknown) !== 0) return checked !== "undefined";
|
|
4582
5136
|
return (input.isUnion() ? input.types : [input]).some((member3) => literalKind(member3, checker) === checked && !checker.isTypeAssignableTo(member3, target));
|
|
4583
5137
|
}
|
|
4584
5138
|
function literalKind(type, checker) {
|
|
4585
|
-
if ((type.flags &
|
|
5139
|
+
if ((type.flags & ts20.TypeFlags.BooleanLiteral) !== 0) return "boolean";
|
|
4586
5140
|
return primitiveKinds(type, checker, true)?.values().next().value;
|
|
4587
5141
|
}
|
|
4588
5142
|
function singleReturn(node) {
|
|
@@ -4610,7 +5164,7 @@ function sameParameter(declared, tested, sourceCode) {
|
|
|
4610
5164
|
return parameter !== null && parameter === ASTUtils12.findVariable(sourceCode.getScope(tested), tested.name);
|
|
4611
5165
|
}
|
|
4612
5166
|
function inputKinds(type, checker) {
|
|
4613
|
-
if ((type.flags &
|
|
5167
|
+
if ((type.flags & ts20.TypeFlags.Unknown) !== 0) return /* @__PURE__ */ new Set(["string", "number", "bigint", "boolean", "symbol", "undefined", "object", "function"]);
|
|
4614
5168
|
return primitiveKinds(type, checker, true);
|
|
4615
5169
|
}
|
|
4616
5170
|
function primitiveKinds(type, checker, allowLiterals) {
|
|
@@ -4622,7 +5176,7 @@ function primitiveKinds(type, checker, allowLiterals) {
|
|
|
4622
5176
|
kinds.add(kind);
|
|
4623
5177
|
continue;
|
|
4624
5178
|
}
|
|
4625
|
-
if ((member3.flags &
|
|
5179
|
+
if ((member3.flags & ts20.TypeFlags.BooleanLiteral) === 0) return void 0;
|
|
4626
5180
|
booleans.add(checker.typeToString(member3));
|
|
4627
5181
|
}
|
|
4628
5182
|
if (booleans.size > 0) {
|
|
@@ -4636,21 +5190,21 @@ function primitiveKind(type, allowLiterals) {
|
|
|
4636
5190
|
if ((type.flags & flag) !== 0) return kind;
|
|
4637
5191
|
}
|
|
4638
5192
|
if (!allowLiterals) return void 0;
|
|
4639
|
-
if ((type.flags &
|
|
4640
|
-
if ((type.flags &
|
|
4641
|
-
if ((type.flags &
|
|
4642
|
-
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";
|
|
4643
5197
|
return void 0;
|
|
4644
5198
|
}
|
|
4645
5199
|
|
|
4646
5200
|
// src/rules/no-partial-type-predicate.ts
|
|
4647
5201
|
import { ASTUtils as ASTUtils15, AST_NODE_TYPES as AST_NODE_TYPES29, ESLintUtils as ESLintUtils13 } from "@typescript-eslint/utils";
|
|
4648
5202
|
import { isNumberLiteralType } from "ts-api-utils";
|
|
4649
|
-
import
|
|
5203
|
+
import ts22 from "typescript";
|
|
4650
5204
|
|
|
4651
5205
|
// src/rules/_uuid-predicate-witness.ts
|
|
4652
5206
|
import { AST_NODE_TYPES as AST_NODE_TYPES28, ASTUtils as ASTUtils14 } from "@typescript-eslint/utils";
|
|
4653
|
-
import
|
|
5207
|
+
import ts21 from "typescript";
|
|
4654
5208
|
|
|
4655
5209
|
// src/rules/_native-runtime-unchanged.ts
|
|
4656
5210
|
import { AST_NODE_TYPES as AST_NODE_TYPES27, ASTUtils as ASTUtils13 } from "@typescript-eslint/utils";
|
|
@@ -4757,7 +5311,7 @@ function noArguments(node) {
|
|
|
4757
5311
|
function installedZod(node, services) {
|
|
4758
5312
|
const checker = services.program.getTypeChecker();
|
|
4759
5313
|
const symbol = checker.getSymbolAtLocation(services.esTreeNodeToTSNodeMap.get(node));
|
|
4760
|
-
if (symbol === void 0 || (symbol.flags &
|
|
5314
|
+
if (symbol === void 0 || (symbol.flags & ts21.SymbolFlags.Alias) === 0) return false;
|
|
4761
5315
|
const target = checker.getAliasedSymbol(symbol);
|
|
4762
5316
|
const declarations = target.getDeclarations();
|
|
4763
5317
|
return declarations !== void 0 && declarations.length > 0 && declarations.every((declaration) => {
|
|
@@ -4855,25 +5409,25 @@ function primitivePredicate(node, services) {
|
|
|
4855
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;
|
|
4856
5410
|
const checker = services.program.getTypeChecker();
|
|
4857
5411
|
const tsFunction = services.esTreeNodeToTSNodeMap.get(node);
|
|
4858
|
-
if (
|
|
5412
|
+
if (ts22.isMethodDeclaration(tsFunction)) return void 0;
|
|
4859
5413
|
if (hasSeparatePredicateContract(tsFunction, checker)) return void 0;
|
|
4860
5414
|
const target = checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(annotation.typeAnnotation.typeAnnotation));
|
|
4861
5415
|
const kind = primitiveKind2(target);
|
|
4862
5416
|
const input = checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(parameter));
|
|
4863
|
-
const unsafe =
|
|
5417
|
+
const unsafe = ts22.TypeFlags.Any | ts22.TypeFlags.Never | ts22.TypeFlags.TypeParameter | ts22.TypeFlags.Conditional | ts22.TypeFlags.IndexedAccess;
|
|
4864
5418
|
if (kind === void 0 || (input.flags & unsafe) !== 0 || !checker.isTypeAssignableTo(target, input)) return void 0;
|
|
4865
5419
|
const expression = returnedExpression2(node);
|
|
4866
5420
|
return expression === void 0 ? void 0 : { annotation, parameter, expression, kind, input, inputIsTarget: checker.isTypeAssignableTo(input, target) };
|
|
4867
5421
|
}
|
|
4868
5422
|
function primitiveKind2(type) {
|
|
4869
|
-
if ((type.flags &
|
|
4870
|
-
if ((type.flags &
|
|
4871
|
-
if ((type.flags &
|
|
4872
|
-
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";
|
|
4873
5427
|
return void 0;
|
|
4874
5428
|
}
|
|
4875
5429
|
function numericWitnessInInput(value, input) {
|
|
4876
|
-
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);
|
|
4877
5431
|
}
|
|
4878
5432
|
function returnedExpression2(node) {
|
|
4879
5433
|
if (node.body === void 0) return void 0;
|
|
@@ -4986,7 +5540,7 @@ import { AST_NODE_TYPES as AST_NODE_TYPES32, ASTUtils as ASTUtils18, ESLintUtils
|
|
|
4986
5540
|
|
|
4987
5541
|
// src/rules/_boolean-selector-contract.ts
|
|
4988
5542
|
import { AST_NODE_TYPES as AST_NODE_TYPES30, ASTUtils as ASTUtils16 } from "@typescript-eslint/utils";
|
|
4989
|
-
import
|
|
5543
|
+
import ts23 from "typescript";
|
|
4990
5544
|
var MEMBER_REFERENCES = /* @__PURE__ */ new WeakMap();
|
|
4991
5545
|
function isEligibleBooleanSelector(identifier, sourceCode, services) {
|
|
4992
5546
|
const owner = enclosingFunction(identifier);
|
|
@@ -4998,12 +5552,12 @@ function isEligibleBooleanSelector(identifier, sourceCode, services) {
|
|
|
4998
5552
|
const definition = binding3?.defs[0];
|
|
4999
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;
|
|
5000
5554
|
const checker = services.program.getTypeChecker();
|
|
5001
|
-
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;
|
|
5002
5556
|
const parameter = definition.name.parent.type === AST_NODE_TYPES30.AssignmentPattern ? definition.name.parent : definition.name;
|
|
5003
5557
|
const index = owner.params.indexOf(parameter);
|
|
5004
5558
|
if (index < 0 || isPureMapping(owner, sourceCode, services)) return false;
|
|
5005
5559
|
const implementation = services.esTreeNodeToTSNodeMap.get(owner);
|
|
5006
|
-
if (
|
|
5560
|
+
if (ts23.isSetAccessorDeclaration(implementation)) return false;
|
|
5007
5561
|
const authority = { checker, index, implementation };
|
|
5008
5562
|
if (hasDeclaredContract(authority) || hasMemberCallbackReference(authority, sourceCode, services)) return false;
|
|
5009
5563
|
const callable = callableBinding2(owner, sourceCode);
|
|
@@ -5019,10 +5573,10 @@ function booleanContract(authority, type, independentlyAnnotated = false) {
|
|
|
5019
5573
|
return (type === void 0 ? [] : authority.checker.getNonNullableType(type).getCallSignatures()).some((signature) => {
|
|
5020
5574
|
const declaration = signature.declaration;
|
|
5021
5575
|
const parameter = declaration?.parameters[authority.index];
|
|
5022
|
-
if (declaration === void 0 || declaration === authority.implementation || parameter === void 0 || !
|
|
5023
|
-
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;
|
|
5024
5578
|
const instantiated = signature.getParameters()[authority.index];
|
|
5025
|
-
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;
|
|
5026
5580
|
});
|
|
5027
5581
|
}
|
|
5028
5582
|
function callbackContract(authority, expression) {
|
|
@@ -5030,22 +5584,22 @@ function callbackContract(authority, expression) {
|
|
|
5030
5584
|
if (booleanContract(authority, checker.getContextualType(expression))) return true;
|
|
5031
5585
|
const value = outerTypedExpression(expression);
|
|
5032
5586
|
const parent = value.parent;
|
|
5033
|
-
if (
|
|
5587
|
+
if (ts23.isCallExpression(parent)) {
|
|
5034
5588
|
const index = parent.arguments.indexOf(value);
|
|
5035
5589
|
const parameter = index < 0 ? void 0 : checker.getResolvedSignature(parent)?.declaration?.parameters[index];
|
|
5036
|
-
return parameter !== void 0 &&
|
|
5590
|
+
return parameter !== void 0 && ts23.isParameter(parameter) && parameter.type !== void 0 && booleanContract(authority, checker.getTypeFromTypeNode(parameter.type), true);
|
|
5037
5591
|
}
|
|
5038
|
-
if (!
|
|
5592
|
+
if (!ts23.isJsxExpression(parent) || !ts23.isJsxAttribute(parent.parent)) return false;
|
|
5039
5593
|
const attribute = parent.parent;
|
|
5040
|
-
if (checker.getSymbolAtLocation(attribute.name)?.declarations?.some((declaration) => (
|
|
5041
|
-
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;
|
|
5042
5596
|
const opening = attribute.parent.parent;
|
|
5043
5597
|
const propContract = (type) => {
|
|
5044
5598
|
const property = checker.getPropertyOfType(type, attribute.name.getText());
|
|
5045
5599
|
return property !== void 0 && booleanContract(authority, checker.getTypeOfSymbolAtLocation(property, attribute), true);
|
|
5046
5600
|
};
|
|
5047
5601
|
const props = checker.getResolvedSignature(opening)?.declaration?.parameters[0];
|
|
5048
|
-
if (props !== void 0 &&
|
|
5602
|
+
if (props !== void 0 && ts23.isParameter(props) && props.type !== void 0 && propContract(checker.getTypeFromTypeNode(props.type))) return true;
|
|
5049
5603
|
return checker.getTypeAtLocation(opening.tagName).getCallSignatures().some((signature) => {
|
|
5050
5604
|
const parameter = signature.getParameters()[0];
|
|
5051
5605
|
return parameter !== void 0 && propContract(checker.getTypeOfSymbolAtLocation(parameter, opening.tagName));
|
|
@@ -5053,41 +5607,41 @@ function callbackContract(authority, expression) {
|
|
|
5053
5607
|
}
|
|
5054
5608
|
function outerTypedExpression(node) {
|
|
5055
5609
|
let current = node;
|
|
5056
|
-
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;
|
|
5057
5611
|
return current;
|
|
5058
5612
|
}
|
|
5059
5613
|
function hasDeclaredContract(authority) {
|
|
5060
5614
|
const node = authority.implementation;
|
|
5061
5615
|
const checker = authority.checker;
|
|
5062
|
-
if (
|
|
5616
|
+
if (ts23.isArrowFunction(node) || ts23.isFunctionExpression(node)) {
|
|
5063
5617
|
if (callbackContract(authority, node)) return true;
|
|
5064
5618
|
const binding3 = outerTypedExpression(node).parent;
|
|
5065
|
-
if ((
|
|
5066
|
-
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);
|
|
5067
5621
|
}
|
|
5068
|
-
if (
|
|
5069
|
-
if (!
|
|
5070
|
-
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;
|
|
5071
5625
|
}
|
|
5072
5626
|
function memberContract(authority, member3) {
|
|
5073
5627
|
const owner = member3.parent;
|
|
5074
5628
|
const checker = authority.checker;
|
|
5075
5629
|
const symbol = checker.getSymbolAtLocation(member3.name);
|
|
5076
|
-
if (symbol === void 0 ||
|
|
5630
|
+
if (symbol === void 0 || ts23.isPrivateIdentifier(member3.name)) return false;
|
|
5077
5631
|
const matches = (type, independentlyAnnotated = false) => {
|
|
5078
5632
|
const property = type.getProperties().find((candidate2) => candidate2.escapedName === symbol.escapedName);
|
|
5079
5633
|
return property !== void 0 && booleanContract(authority, checker.getTypeOfSymbolAtLocation(property, member3), independentlyAnnotated);
|
|
5080
5634
|
};
|
|
5081
|
-
if (
|
|
5635
|
+
if (ts23.isObjectLiteralExpression(owner)) {
|
|
5082
5636
|
const contextual = checker.getContextualType(owner);
|
|
5083
5637
|
const binding3 = outerTypedExpression(owner).parent;
|
|
5084
|
-
if (
|
|
5638
|
+
if (ts23.isVariableDeclaration(binding3) && binding3.type !== void 0 && matches(checker.getTypeFromTypeNode(binding3.type), true)) return true;
|
|
5085
5639
|
return contextual !== void 0 && matches(contextual);
|
|
5086
5640
|
}
|
|
5087
|
-
if (!
|
|
5088
|
-
const modifiers =
|
|
5089
|
-
if ((modifiers &
|
|
5090
|
-
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;
|
|
5091
5645
|
}
|
|
5092
5646
|
function callableBinding2(owner, sourceCode) {
|
|
5093
5647
|
if (owner.type === AST_NODE_TYPES30.FunctionDeclaration && owner.id !== null) return ASTUtils16.findVariable(sourceCode.getScope(owner), owner.id.name);
|
|
@@ -5107,7 +5661,7 @@ function hasCallbackReference(binding3, authority, sourceCode, services, seen) {
|
|
|
5107
5661
|
const jsxAttribute = parent?.type === AST_NODE_TYPES30.JSXExpressionContainer && parent.parent.type === AST_NODE_TYPES30.JSXAttribute;
|
|
5108
5662
|
if (callArgument || jsxAttribute) {
|
|
5109
5663
|
const expression = services.esTreeNodeToTSNodeMap.get(value);
|
|
5110
|
-
if (
|
|
5664
|
+
if (ts23.isExpression(expression) && callbackContract(authority, expression)) return true;
|
|
5111
5665
|
}
|
|
5112
5666
|
if (parent?.type === AST_NODE_TYPES30.CallExpression && parent.callee === value && forwardedCallbackParameter(parent, authority, sourceCode, services)) return true;
|
|
5113
5667
|
let selected = value;
|
|
@@ -5132,20 +5686,20 @@ function forwardedCallbackParameter(call, authority, sourceCode, services) {
|
|
|
5132
5686
|
const binding3 = ASTUtils16.findVariable(sourceCode.getScope(argument), argument.name);
|
|
5133
5687
|
const definition = binding3?.defs[0];
|
|
5134
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;
|
|
5135
|
-
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;
|
|
5136
5690
|
const parameter = definition.name.parent.type === AST_NODE_TYPES30.AssignmentPattern ? definition.name.parent : definition.name;
|
|
5137
5691
|
const index = wrapper.params.indexOf(parameter);
|
|
5138
5692
|
const implementation = services.esTreeNodeToTSNodeMap.get(wrapper);
|
|
5139
|
-
return index >= 0 && (
|
|
5693
|
+
return index >= 0 && (ts23.isArrowFunction(implementation) || ts23.isFunctionExpression(implementation)) && callbackContract({ checker: authority.checker, index, implementation }, implementation);
|
|
5140
5694
|
}
|
|
5141
5695
|
function hasMemberCallbackReference(authority, sourceCode, services) {
|
|
5142
5696
|
const node = authority.implementation;
|
|
5143
|
-
const member3 =
|
|
5144
|
-
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;
|
|
5145
5699
|
let references = MEMBER_REFERENCES.get(sourceCode);
|
|
5146
5700
|
if (references === void 0) {
|
|
5147
5701
|
let visit2 = function(current) {
|
|
5148
|
-
if (
|
|
5702
|
+
if (ts23.isPropertyAccessExpression(current)) {
|
|
5149
5703
|
const target = authority.checker.getSymbolAtLocation(current.name);
|
|
5150
5704
|
for (const declaration of target?.declarations ?? []) {
|
|
5151
5705
|
const values = collected.get(declaration) ?? [];
|
|
@@ -5153,7 +5707,7 @@ function hasMemberCallbackReference(authority, sourceCode, services) {
|
|
|
5153
5707
|
collected.set(declaration, values);
|
|
5154
5708
|
}
|
|
5155
5709
|
}
|
|
5156
|
-
|
|
5710
|
+
ts23.forEachChild(current, visit2);
|
|
5157
5711
|
};
|
|
5158
5712
|
var visit = visit2;
|
|
5159
5713
|
const collected = /* @__PURE__ */ new Map();
|
|
@@ -5164,14 +5718,14 @@ function hasMemberCallbackReference(authority, sourceCode, services) {
|
|
|
5164
5718
|
return references.get(member3)?.some((reference) => {
|
|
5165
5719
|
let value = outerTypedExpression(reference);
|
|
5166
5720
|
const bind = value.parent;
|
|
5167
|
-
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) {
|
|
5168
5722
|
const declaration = authority.checker.getResolvedSignature(bind.parent)?.declaration;
|
|
5169
5723
|
if (declaration === void 0 || !services.program.isSourceFileDefaultLibrary(declaration.getSourceFile())) return false;
|
|
5170
5724
|
value = outerTypedExpression(bind.parent);
|
|
5171
5725
|
}
|
|
5172
5726
|
const parent = value.parent;
|
|
5173
|
-
const callback =
|
|
5174
|
-
const jsx =
|
|
5727
|
+
const callback = ts23.isCallExpression(parent) && parent.arguments.some((argument) => argument === value);
|
|
5728
|
+
const jsx = ts23.isJsxExpression(parent) && ts23.isJsxAttribute(parent.parent);
|
|
5175
5729
|
return (callback || jsx) && callbackContract(authority, value);
|
|
5176
5730
|
}) === true;
|
|
5177
5731
|
}
|
|
@@ -5215,21 +5769,21 @@ function sameTarget(left, right, sourceCode, services, operation2) {
|
|
|
5215
5769
|
if (!operation2) return true;
|
|
5216
5770
|
const checker = services.program.getTypeChecker();
|
|
5217
5771
|
const property = checker.getSymbolAtLocation(services.esTreeNodeToTSNodeMap.get(left.property));
|
|
5218
|
-
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;
|
|
5219
5773
|
}
|
|
5220
5774
|
function pureValue(node, sourceCode, services) {
|
|
5221
5775
|
const value = unwrapExpression(node);
|
|
5222
5776
|
if (value.type === AST_NODE_TYPES30.MemberExpression && !value.computed) return value.object.type === AST_NODE_TYPES30.Super || pureValue(value.object, sourceCode, services);
|
|
5223
5777
|
if (value.type === AST_NODE_TYPES30.ChainExpression) return pureValue(value.expression, sourceCode, services);
|
|
5224
5778
|
if (value.type === AST_NODE_TYPES30.UnaryExpression && (value.operator === "!" || value.operator === "typeof" || value.operator === "void")) return pureValue(value.argument, sourceCode, services);
|
|
5225
|
-
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);
|
|
5226
5780
|
if (!ASTUtils16.hasSideEffect(value, sourceCode, { considerGetters: true, considerImplicitTypeConversion: true })) return true;
|
|
5227
5781
|
if (value.type !== AST_NODE_TYPES30.BinaryExpression || value.left.type === AST_NODE_TYPES30.PrivateIdentifier) return false;
|
|
5228
|
-
return
|
|
5782
|
+
return primitiveValue2(value.left, services) && primitiveValue2(value.right, services) && pureValue(value.left, sourceCode, services) && pureValue(value.right, sourceCode, services);
|
|
5229
5783
|
}
|
|
5230
|
-
function
|
|
5784
|
+
function primitiveValue2(operand, services) {
|
|
5231
5785
|
const type = services.program.getTypeChecker().getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(operand));
|
|
5232
|
-
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);
|
|
5233
5787
|
}
|
|
5234
5788
|
|
|
5235
5789
|
// src/rules/_literal-selector-fix.ts
|
|
@@ -5463,7 +6017,7 @@ function isDirectTest(identifier) {
|
|
|
5463
6017
|
// src/rules/no-invalid-zod-custom-parse.ts
|
|
5464
6018
|
import { ASTUtils as ASTUtils19, AST_NODE_TYPES as AST_NODE_TYPES34, ESLintUtils as ESLintUtils15 } from "@typescript-eslint/utils";
|
|
5465
6019
|
import { isBigIntLiteralType, isBooleanLiteralType, isNumberLiteralType as isNumberLiteralType2, isStringLiteralType } from "ts-api-utils";
|
|
5466
|
-
import
|
|
6020
|
+
import ts24 from "typescript";
|
|
5467
6021
|
|
|
5468
6022
|
// src/rules/_import-specifier-name.ts
|
|
5469
6023
|
import { AST_NODE_TYPES as AST_NODE_TYPES33 } from "@typescript-eslint/utils";
|
|
@@ -5559,17 +6113,17 @@ function nativeZodDeclaration(signature) {
|
|
|
5559
6113
|
}
|
|
5560
6114
|
function primitiveDomain(type) {
|
|
5561
6115
|
if (type.isUnion()) return type.types.every(primitiveDomain);
|
|
5562
|
-
if ((type.flags & (
|
|
5563
|
-
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;
|
|
5564
6118
|
return (type.flags & flags) !== 0;
|
|
5565
6119
|
}
|
|
5566
6120
|
function acceptsPrimitive(type, value) {
|
|
5567
6121
|
if (type.isUnion()) return type.types.some((member3) => acceptsPrimitive(member3, value));
|
|
5568
|
-
if (value === null) return (type.flags &
|
|
5569
|
-
if (typeof value === "string") return (type.flags &
|
|
5570
|
-
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;
|
|
5571
6125
|
if (typeof value === "boolean") return isBooleanLiteralType(type) && type.intrinsicName === String(value);
|
|
5572
|
-
return (type.flags &
|
|
6126
|
+
return (type.flags & ts24.TypeFlags.BigInt) !== 0 || isBigIntLiteralType(type) && bigintValue(type) === value;
|
|
5573
6127
|
}
|
|
5574
6128
|
function bigintValue(type) {
|
|
5575
6129
|
return BigInt(`${type.value.negative ? "-" : ""}${type.value.base10Value}`);
|
|
@@ -5586,7 +6140,7 @@ function primitiveLiteral(node) {
|
|
|
5586
6140
|
|
|
5587
6141
|
// src/rules/no-contradictory-overload-return.ts
|
|
5588
6142
|
import { AST_NODE_TYPES as AST_NODE_TYPES35, ESLintUtils as ESLintUtils16 } from "@typescript-eslint/utils";
|
|
5589
|
-
import
|
|
6143
|
+
import ts25 from "typescript";
|
|
5590
6144
|
var LIMIT = 32;
|
|
5591
6145
|
var NO_CONTRADICTORY_OVERLOAD_RETURN_DOCUMENTATION = {
|
|
5592
6146
|
summary: "Preserve the input/result relationship promised by literal overloads.",
|
|
@@ -5684,16 +6238,16 @@ function privateOverloadFix(sourceCode, filename, node, implementation, proof, s
|
|
|
5684
6238
|
return edits.length === 0 ? null : (fixer) => edits.map((edit) => fixer.replaceText(edit.node, edit.text));
|
|
5685
6239
|
}
|
|
5686
6240
|
function directResultSyntax(node) {
|
|
5687
|
-
if (
|
|
5688
|
-
if (
|
|
5689
|
-
if (!
|
|
5690
|
-
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));
|
|
5691
6245
|
}
|
|
5692
6246
|
function primitiveResultSyntax(node) {
|
|
5693
|
-
if (
|
|
5694
|
-
if (
|
|
5695
|
-
if (
|
|
5696
|
-
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;
|
|
5697
6251
|
}
|
|
5698
6252
|
function branchResultType(branch, sourceCode, services) {
|
|
5699
6253
|
const valueType = (literal2) => typeof literal2.value === "string" ? sourceCode.getText(services.tsNodeToESTreeNodeMap.get(literal2.node)) : String(literal2.value);
|
|
@@ -5702,11 +6256,11 @@ function branchResultType(branch, sourceCode, services) {
|
|
|
5702
6256
|
}
|
|
5703
6257
|
function implementationProof(node, checker) {
|
|
5704
6258
|
const parameter = directParameter(node);
|
|
5705
|
-
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;
|
|
5706
6260
|
const returned2 = node.body.statements[0];
|
|
5707
|
-
if (returned2 === void 0 || !
|
|
6261
|
+
if (returned2 === void 0 || !ts25.isReturnStatement(returned2) || returned2.expression === void 0) return void 0;
|
|
5708
6262
|
const expression = unparen(returned2.expression);
|
|
5709
|
-
if (!
|
|
6263
|
+
if (!ts25.isConditionalExpression(expression)) return void 0;
|
|
5710
6264
|
const condition2 = equality(expression.condition, checker.getSymbolAtLocation(parameter.name), checker);
|
|
5711
6265
|
const yes = branchValue(expression.whenTrue);
|
|
5712
6266
|
const no = branchValue(expression.whenFalse);
|
|
@@ -5720,21 +6274,21 @@ function implementationProof(node, checker) {
|
|
|
5720
6274
|
}
|
|
5721
6275
|
function directParameter(node) {
|
|
5722
6276
|
const parameter = node.parameters[0];
|
|
5723
|
-
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;
|
|
5724
6278
|
return { name: parameter.name, type: parameter.type };
|
|
5725
6279
|
}
|
|
5726
6280
|
function overloadCases(node, implementationOutput, checker) {
|
|
5727
6281
|
const declarations = node.name === void 0 ? void 0 : checker.getSymbolAtLocation(node.name)?.declarations;
|
|
5728
|
-
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;
|
|
5729
6283
|
const cases = [];
|
|
5730
6284
|
const seen = /* @__PURE__ */ new Set();
|
|
5731
6285
|
const implementationParameter = directParameter(node);
|
|
5732
6286
|
if (implementationParameter === void 0) return void 0;
|
|
5733
6287
|
const implementationInput = checker.getTypeAtLocation(implementationParameter.type);
|
|
5734
6288
|
for (const declaration of declarations) {
|
|
5735
|
-
if (!
|
|
6289
|
+
if (!ts25.isFunctionDeclaration(declaration) || declaration === node) continue;
|
|
5736
6290
|
const parameter = directParameter(declaration);
|
|
5737
|
-
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;
|
|
5738
6292
|
const input = primitiveLiteral2(parameter.type.literal);
|
|
5739
6293
|
const signature = checker.getSignatureFromDeclaration(declaration);
|
|
5740
6294
|
if (input === void 0 || seen.has(input.value) || signature === void 0 || !checker.isTypeAssignableTo(checker.getTypeAtLocation(parameter.type), implementationInput)) return void 0;
|
|
@@ -5747,11 +6301,11 @@ function overloadCases(node, implementationOutput, checker) {
|
|
|
5747
6301
|
}
|
|
5748
6302
|
function equality(expression, parameter, checker) {
|
|
5749
6303
|
const value = unparen(expression);
|
|
5750
|
-
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;
|
|
5751
6305
|
for (const [tested, expected] of [[value.left, value.right], [value.right, value.left]]) {
|
|
5752
6306
|
const named3 = unparen(tested);
|
|
5753
6307
|
const condition2 = primitiveLiteral2(expected);
|
|
5754
|
-
if (
|
|
6308
|
+
if (ts25.isIdentifier(named3) && checker.getSymbolAtLocation(named3) === parameter && condition2 !== void 0) return { condition: condition2, equal: value.operatorToken.kind === ts25.SyntaxKind.EqualsEqualsEqualsToken };
|
|
5755
6309
|
}
|
|
5756
6310
|
return void 0;
|
|
5757
6311
|
}
|
|
@@ -5759,10 +6313,10 @@ function branchValue(expression) {
|
|
|
5759
6313
|
const node = unparen(expression);
|
|
5760
6314
|
const literal2 = primitiveLiteral2(node);
|
|
5761
6315
|
if (literal2 !== void 0) return { kind: "literal", node, value: literal2 };
|
|
5762
|
-
if (!
|
|
6316
|
+
if (!ts25.isObjectLiteralExpression(node) || node.properties.length > LIMIT) return void 0;
|
|
5763
6317
|
const values = /* @__PURE__ */ new Map();
|
|
5764
6318
|
for (const property of node.properties) {
|
|
5765
|
-
if (!
|
|
6319
|
+
if (!ts25.isPropertyAssignment(property)) return void 0;
|
|
5766
6320
|
const name = propertyKey(property.name);
|
|
5767
6321
|
const value = primitiveLiteral2(property.initializer);
|
|
5768
6322
|
if (name === void 0 || name === "__proto__" || values.has(name) || value === void 0) return void 0;
|
|
@@ -5786,30 +6340,30 @@ function mismatches(branch, expected, checker) {
|
|
|
5786
6340
|
}
|
|
5787
6341
|
function plainPrimitive(type) {
|
|
5788
6342
|
const members = type.isUnion() ? type.types : [type];
|
|
5789
|
-
const allowed =
|
|
5790
|
-
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);
|
|
5791
6345
|
}
|
|
5792
6346
|
function primitiveLiteral2(expression) {
|
|
5793
6347
|
const node = unparen(expression);
|
|
5794
|
-
if (
|
|
5795
|
-
if (node.kind ===
|
|
5796
|
-
if (node.kind ===
|
|
5797
|
-
if (node.kind ===
|
|
5798
|
-
if (
|
|
5799
|
-
if (
|
|
5800
|
-
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);
|
|
5801
6355
|
if (Number.isFinite(value)) return { node, value };
|
|
5802
6356
|
}
|
|
5803
6357
|
return void 0;
|
|
5804
6358
|
}
|
|
5805
6359
|
function propertyKey(name) {
|
|
5806
|
-
if (
|
|
5807
|
-
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));
|
|
5808
6362
|
return void 0;
|
|
5809
6363
|
}
|
|
5810
6364
|
function unparen(expression) {
|
|
5811
6365
|
let node = expression;
|
|
5812
|
-
while (
|
|
6366
|
+
while (ts25.isParenthesizedExpression(node)) node = node.expression;
|
|
5813
6367
|
return node;
|
|
5814
6368
|
}
|
|
5815
6369
|
|
|
@@ -12417,7 +12971,7 @@ import {
|
|
|
12417
12971
|
ASTUtils as ASTUtils38,
|
|
12418
12972
|
ESLintUtils as ESLintUtils17
|
|
12419
12973
|
} from "@typescript-eslint/utils";
|
|
12420
|
-
import
|
|
12974
|
+
import ts26 from "typescript";
|
|
12421
12975
|
|
|
12422
12976
|
// src/rules/_existing-domain-comparison-fix.ts
|
|
12423
12977
|
import {
|
|
@@ -12615,7 +13169,7 @@ var EQUALITY_OPERATORS = /* @__PURE__ */ new Set([
|
|
|
12615
13169
|
"==",
|
|
12616
13170
|
"==="
|
|
12617
13171
|
]);
|
|
12618
|
-
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;
|
|
12619
13173
|
function unwrapComparisonExpression(node) {
|
|
12620
13174
|
let current = unwrapExpression(node);
|
|
12621
13175
|
while (current.type === AST_NODE_TYPES68.ChainExpression) {
|
|
@@ -12670,7 +13224,7 @@ function typeMayContainObject(type, checker) {
|
|
|
12670
13224
|
return type.types.some((member3) => typeMayContainObject(member3, checker));
|
|
12671
13225
|
}
|
|
12672
13226
|
if ((type.flags & PRIMITIVE_FLAGS) !== 0) return false;
|
|
12673
|
-
if ((type.flags & (
|
|
13227
|
+
if ((type.flags & (ts26.TypeFlags.Any | ts26.TypeFlags.Unknown | ts26.TypeFlags.TypeParameter)) !== 0) {
|
|
12674
13228
|
return true;
|
|
12675
13229
|
}
|
|
12676
13230
|
if (checker.isArrayType(type) || checker.isTupleType(type)) {
|
|
@@ -12678,7 +13232,7 @@ function typeMayContainObject(type, checker) {
|
|
|
12678
13232
|
return elements.some((element) => typeMayContainObject(element, checker));
|
|
12679
13233
|
}
|
|
12680
13234
|
const symbolName = type.getSymbol()?.getName();
|
|
12681
|
-
if ((symbolName === "Array" || symbolName === "ReadonlyArray") && (type.flags &
|
|
13235
|
+
if ((symbolName === "Array" || symbolName === "ReadonlyArray") && (type.flags & ts26.TypeFlags.Object) !== 0) {
|
|
12682
13236
|
const elements = checker.getTypeArguments(type);
|
|
12683
13237
|
return elements.length === 0 || elements.some((element) => typeMayContainObject(element, checker));
|
|
12684
13238
|
}
|
|
@@ -13129,7 +13683,7 @@ function zeroBoundSemantic(method) {
|
|
|
13129
13683
|
import {
|
|
13130
13684
|
ESLintUtils as ESLintUtils18
|
|
13131
13685
|
} from "@typescript-eslint/utils";
|
|
13132
|
-
import * as
|
|
13686
|
+
import * as ts27 from "typescript";
|
|
13133
13687
|
|
|
13134
13688
|
// src/rules/_collection-property-fix.ts
|
|
13135
13689
|
import {
|
|
@@ -13232,7 +13786,7 @@ function isDefaultLibraryCollection(node, services) {
|
|
|
13232
13786
|
const checker = services.program.getTypeChecker();
|
|
13233
13787
|
const tsNode = services.esTreeNodeToTSNodeMap.get(node);
|
|
13234
13788
|
const type = checker.getTypeAtLocation(tsNode);
|
|
13235
|
-
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) {
|
|
13236
13790
|
return false;
|
|
13237
13791
|
}
|
|
13238
13792
|
return isDefaultLibraryCollectionSymbol(type.getSymbol(), services);
|
|
@@ -13243,7 +13797,7 @@ function isDefaultLibraryCollectionSymbol(symbol, services) {
|
|
|
13243
13797
|
return declarations.length > 0 && declarations.every(
|
|
13244
13798
|
(declaration) => services.program.isSourceFileDefaultLibrary(declaration.getSourceFile())
|
|
13245
13799
|
) && declarations.some(
|
|
13246
|
-
(declaration) =>
|
|
13800
|
+
(declaration) => ts27.isInterfaceDeclaration(declaration) && declaration.name.text === symbol.name
|
|
13247
13801
|
);
|
|
13248
13802
|
}
|
|
13249
13803
|
var no_in_operator_on_built_in_collections_default = createRule({
|
|
@@ -13563,7 +14117,7 @@ import {
|
|
|
13563
14117
|
AST_NODE_TYPES as AST_NODE_TYPES74,
|
|
13564
14118
|
ESLintUtils as ESLintUtils19
|
|
13565
14119
|
} from "@typescript-eslint/utils";
|
|
13566
|
-
import * as
|
|
14120
|
+
import * as ts28 from "typescript";
|
|
13567
14121
|
|
|
13568
14122
|
// src/rules/_class-private.ts
|
|
13569
14123
|
import {
|
|
@@ -13735,15 +14289,15 @@ function candidate(member3) {
|
|
|
13735
14289
|
}
|
|
13736
14290
|
function interfaceNames(services, owner) {
|
|
13737
14291
|
const tsOwner = services.esTreeNodeToTSNodeMap.get(owner);
|
|
13738
|
-
if (!
|
|
13739
|
-
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) ?? [];
|
|
13740
14294
|
if (implemented.length === 0) return null;
|
|
13741
14295
|
const checker = services.program.getTypeChecker();
|
|
13742
14296
|
const names = /* @__PURE__ */ new Set();
|
|
13743
14297
|
for (const clause of implemented) {
|
|
13744
14298
|
for (const contract of clause.types) {
|
|
13745
14299
|
const type = checker.getTypeAtLocation(contract);
|
|
13746
|
-
if ((type.flags & (
|
|
14300
|
+
if ((type.flags & (ts28.TypeFlags.Any | ts28.TypeFlags.Unknown)) !== 0) return null;
|
|
13747
14301
|
for (const property of checker.getPropertiesOfType(type)) names.add(property.getName());
|
|
13748
14302
|
}
|
|
13749
14303
|
}
|
|
@@ -14910,7 +15464,7 @@ function tupleFields(helper) {
|
|
|
14910
15464
|
const values = [];
|
|
14911
15465
|
for (const [index, field] of tuple.elementTypes.entries()) {
|
|
14912
15466
|
const value = returned2.argument.elements[index];
|
|
14913
|
-
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))
|
|
14914
15468
|
return null;
|
|
14915
15469
|
labels.push(field.label);
|
|
14916
15470
|
types.push(field.elementType);
|
|
@@ -14918,7 +15472,7 @@ function tupleFields(helper) {
|
|
|
14918
15472
|
}
|
|
14919
15473
|
return { labels, types, values, returned: returned2.argument };
|
|
14920
15474
|
}
|
|
14921
|
-
function
|
|
15475
|
+
function primitiveValue3(type, value) {
|
|
14922
15476
|
switch (type.type) {
|
|
14923
15477
|
case AST_NODE_TYPES81.TSStringKeyword:
|
|
14924
15478
|
return typeof value.value === "string";
|
|
@@ -21009,7 +21563,7 @@ import {
|
|
|
21009
21563
|
AST_NODE_TYPES as AST_NODE_TYPES107,
|
|
21010
21564
|
ASTUtils as ASTUtils65
|
|
21011
21565
|
} from "@typescript-eslint/utils";
|
|
21012
|
-
import * as
|
|
21566
|
+
import * as ts29 from "typescript";
|
|
21013
21567
|
var NO_ZOD_NATIVE_ENUM_DOCUMENTATION = {
|
|
21014
21568
|
summary: 'Disallow `z.nativeEnum()` (and `z.enum()` over a TypeScript enum); use `z.enum(["a", "b"])` with a string-literal union instead.',
|
|
21015
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.",
|
|
@@ -21118,7 +21672,7 @@ function resolvesToLocalEnum(node, scope) {
|
|
|
21118
21672
|
}
|
|
21119
21673
|
return false;
|
|
21120
21674
|
}
|
|
21121
|
-
var ENUM_SYMBOL_FLAGS =
|
|
21675
|
+
var ENUM_SYMBOL_FLAGS = ts29.SymbolFlags.RegularEnum | ts29.SymbolFlags.ConstEnum | ts29.SymbolFlags.Enum;
|
|
21122
21676
|
function resolvesToImportedEnum(node, services) {
|
|
21123
21677
|
const checker = services.program.getTypeChecker();
|
|
21124
21678
|
const tsNode = services.esTreeNodeToTSNodeMap.get(node);
|
|
@@ -21126,7 +21680,7 @@ function resolvesToImportedEnum(node, services) {
|
|
|
21126
21680
|
if (symbol === void 0) {
|
|
21127
21681
|
return false;
|
|
21128
21682
|
}
|
|
21129
|
-
if ((symbol.flags &
|
|
21683
|
+
if ((symbol.flags & ts29.SymbolFlags.Alias) !== 0) {
|
|
21130
21684
|
symbol = checker.getAliasedSymbol(symbol);
|
|
21131
21685
|
}
|
|
21132
21686
|
return (symbol.flags & ENUM_SYMBOL_FLAGS) !== 0;
|
|
@@ -24771,7 +25325,7 @@ var OPERATIONAL_ROLES = /* @__PURE__ */ new Set([
|
|
|
24771
25325
|
"timeout",
|
|
24772
25326
|
"interval"
|
|
24773
25327
|
]);
|
|
24774
|
-
var
|
|
25328
|
+
var MAX_ALIAS_DEPTH2 = 16;
|
|
24775
25329
|
var PREFER_NOMINAL_ID_TYPES_DOCUMENTATION = {
|
|
24776
25330
|
defaultLevel: "error",
|
|
24777
25331
|
summary: "Distinguish identifier roles sharing primitive types at callable boundaries.",
|
|
@@ -24869,7 +25423,7 @@ function typeDefinitions(node, context) {
|
|
|
24869
25423
|
return [];
|
|
24870
25424
|
}
|
|
24871
25425
|
function rawCarrier(node, context, depth = 0) {
|
|
24872
|
-
if (node === void 0 || depth >=
|
|
25426
|
+
if (node === void 0 || depth >= MAX_ALIAS_DEPTH2) return void 0;
|
|
24873
25427
|
switch (node.type) {
|
|
24874
25428
|
case AST_NODE_TYPES124.TSStringKeyword:
|
|
24875
25429
|
return "string";
|
|
@@ -26360,7 +26914,7 @@ import {
|
|
|
26360
26914
|
ASTUtils as ASTUtils83,
|
|
26361
26915
|
ESLintUtils as ESLintUtils22
|
|
26362
26916
|
} from "@typescript-eslint/utils";
|
|
26363
|
-
import
|
|
26917
|
+
import ts30 from "typescript";
|
|
26364
26918
|
var PREFER_NULLISH_FILTER_PREDICATE_DOCUMENTATION = {
|
|
26365
26919
|
summary: "Prefer an explicit nullish predicate when `filter(Boolean)` removes only nullish values but does not narrow the result type.",
|
|
26366
26920
|
rationale: "An explicit nullish predicate preserves the same runtime elements while letting TypeScript remove `null` and `undefined` from the result.",
|
|
@@ -26423,23 +26977,23 @@ function isBuiltinArrayFilter(node, services) {
|
|
|
26423
26977
|
const symbol = checker.getSymbolAtLocation(property) ?? checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(node.object)).getProperty("filter");
|
|
26424
26978
|
return symbol?.declarations?.some((declaration) => {
|
|
26425
26979
|
const owner = declaration.parent;
|
|
26426
|
-
return
|
|
26980
|
+
return ts30.isInterfaceDeclaration(owner) && (owner.name.text === "Array" || owner.name.text === "ReadonlyArray") && services.program.isSourceFileDefaultLibrary(owner.getSourceFile());
|
|
26427
26981
|
}) ?? false;
|
|
26428
26982
|
}
|
|
26429
26983
|
function arrayElementType(node, services) {
|
|
26430
26984
|
const checker = services.program.getTypeChecker();
|
|
26431
26985
|
const receiver = services.esTreeNodeToTSNodeMap.get(node);
|
|
26432
|
-
return checker.getIndexTypeOfType(checker.getTypeAtLocation(receiver),
|
|
26986
|
+
return checker.getIndexTypeOfType(checker.getTypeAtLocation(receiver), ts30.IndexKind.Number) ?? null;
|
|
26433
26987
|
}
|
|
26434
|
-
var NULLISH_FLAGS =
|
|
26435
|
-
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;
|
|
26436
26990
|
function isNullishPlusTruthy(type, checker, falsyBrowserObject) {
|
|
26437
26991
|
const members = type.isUnion() ? type.types : [type];
|
|
26438
26992
|
let sawNullish = false;
|
|
26439
26993
|
for (const member3 of members) {
|
|
26440
26994
|
if ((member3.flags & NULLISH_FLAGS) !== 0) {
|
|
26441
26995
|
sawNullish = true;
|
|
26442
|
-
} else if ((member3.flags &
|
|
26996
|
+
} else if ((member3.flags & ts30.TypeFlags.Never) === 0 && !isProvablyTruthy(member3, checker, falsyBrowserObject)) {
|
|
26443
26997
|
return false;
|
|
26444
26998
|
}
|
|
26445
26999
|
}
|
|
@@ -26447,7 +27001,7 @@ function isNullishPlusTruthy(type, checker, falsyBrowserObject) {
|
|
|
26447
27001
|
}
|
|
26448
27002
|
function isProvablyTruthy(type, checker, falsyBrowserObject) {
|
|
26449
27003
|
if ((type.flags & UNKNOWN_FLAGS) !== 0) return false;
|
|
26450
|
-
if ((type.flags &
|
|
27004
|
+
if ((type.flags & ts30.TypeFlags.Object) !== 0) {
|
|
26451
27005
|
if (falsyBrowserObject !== null && checker.isTypeAssignableTo(falsyBrowserObject, type)) return false;
|
|
26452
27006
|
return ![
|
|
26453
27007
|
checker.getStringType(),
|
|
@@ -26456,18 +27010,18 @@ function isProvablyTruthy(type, checker, falsyBrowserObject) {
|
|
|
26456
27010
|
checker.getBooleanType()
|
|
26457
27011
|
].some((primitive) => checker.isTypeAssignableTo(primitive, type));
|
|
26458
27012
|
}
|
|
26459
|
-
if ((type.flags & (
|
|
26460
|
-
if ((type.flags &
|
|
27013
|
+
if ((type.flags & (ts30.TypeFlags.ESSymbol | ts30.TypeFlags.UniqueESSymbol)) !== 0) return true;
|
|
27014
|
+
if ((type.flags & ts30.TypeFlags.BooleanLiteral) !== 0) {
|
|
26461
27015
|
return type.intrinsicName === "true";
|
|
26462
27016
|
}
|
|
26463
|
-
if ((type.flags &
|
|
27017
|
+
if ((type.flags & ts30.TypeFlags.StringLiteral) !== 0) {
|
|
26464
27018
|
return type.value.length > 0;
|
|
26465
27019
|
}
|
|
26466
|
-
if ((type.flags &
|
|
27020
|
+
if ((type.flags & ts30.TypeFlags.NumberLiteral) !== 0) {
|
|
26467
27021
|
const value = type.value;
|
|
26468
27022
|
return value !== 0 && !Number.isNaN(value);
|
|
26469
27023
|
}
|
|
26470
|
-
if ((type.flags &
|
|
27024
|
+
if ((type.flags & ts30.TypeFlags.BigIntLiteral) !== 0) {
|
|
26471
27025
|
return type.value.base10Value !== "0";
|
|
26472
27026
|
}
|
|
26473
27027
|
return false;
|
|
@@ -26523,7 +27077,7 @@ var prefer_nullish_filter_predicate_default = createRule({
|
|
|
26523
27077
|
if (services === null) return {};
|
|
26524
27078
|
const program = services.program;
|
|
26525
27079
|
const checker = program.getTypeChecker();
|
|
26526
|
-
const browserCollection = checker.resolveName("HTMLAllCollection", void 0,
|
|
27080
|
+
const browserCollection = checker.resolveName("HTMLAllCollection", void 0, ts30.SymbolFlags.Type, false);
|
|
26527
27081
|
const falsyBrowserObject = browserCollection?.declarations?.some((declaration) => program.isSourceFileDefaultLibrary(declaration.getSourceFile())) === true ? checker.getDeclaredTypeOfSymbol(browserCollection) : null;
|
|
26528
27082
|
return {
|
|
26529
27083
|
CallExpression(node) {
|
|
@@ -26561,7 +27115,7 @@ import {
|
|
|
26561
27115
|
ESLintUtils as ESLintUtils23,
|
|
26562
27116
|
AST_NODE_TYPES as AST_NODE_TYPES133
|
|
26563
27117
|
} from "@typescript-eslint/utils";
|
|
26564
|
-
import * as
|
|
27118
|
+
import * as ts31 from "typescript";
|
|
26565
27119
|
var PREFER_AWAIT_IN_ASYNC_RETURN_DOCUMENTATION = {
|
|
26566
27120
|
summary: "Prefer explicit `await` for proven Promise `.then` calls; the default scope checks direct async returns.",
|
|
26567
27121
|
rationale: "Promise callback chains mix explicit async control flow with nested callbacks, making sequencing and failure handling harder to read.",
|
|
@@ -26645,7 +27199,7 @@ function isProvenPromiseLike(node, services) {
|
|
|
26645
27199
|
return members.every((member3) => isBuiltInPromiseType(member3, services));
|
|
26646
27200
|
}
|
|
26647
27201
|
function isBuiltInPromiseType(type, services) {
|
|
26648
|
-
if ((type.flags & (
|
|
27202
|
+
if ((type.flags & (ts31.TypeFlags.Any | ts31.TypeFlags.Unknown | ts31.TypeFlags.Never)) !== 0) {
|
|
26649
27203
|
return false;
|
|
26650
27204
|
}
|
|
26651
27205
|
const thenSymbol = services.program.getTypeChecker().getPropertyOfType(type, "then");
|
|
@@ -26654,7 +27208,7 @@ function isBuiltInPromiseType(type, services) {
|
|
|
26654
27208
|
return declarations.every(
|
|
26655
27209
|
(declaration) => {
|
|
26656
27210
|
let owner = declaration.parent;
|
|
26657
|
-
while (owner !== void 0 && !
|
|
27211
|
+
while (owner !== void 0 && !ts31.isInterfaceDeclaration(owner)) {
|
|
26658
27212
|
owner = owner.parent;
|
|
26659
27213
|
}
|
|
26660
27214
|
return owner !== void 0 && (owner.name.text === "Promise" || owner.name.text === "PromiseLike") && services.program.isSourceFileDefaultLibrary(owner.getSourceFile());
|
|
@@ -27438,7 +27992,7 @@ var prefer_shared_zod_enum_default = createRule({
|
|
|
27438
27992
|
|
|
27439
27993
|
// src/rules/prefer-switch-for-repeated-equality.ts
|
|
27440
27994
|
import { AST_NODE_TYPES as AST_NODE_TYPES137, ASTUtils as ASTUtils88, ESLintUtils as ESLintUtils24 } from "@typescript-eslint/utils";
|
|
27441
|
-
import
|
|
27995
|
+
import ts32 from "typescript";
|
|
27442
27996
|
var PREFER_SWITCH_FOR_REPEATED_EQUALITY_DOCUMENTATION = {
|
|
27443
27997
|
defaultLevel: "error",
|
|
27444
27998
|
summary: "Prefer switch over long if/else-if chains that compare one value for strict equality.",
|
|
@@ -27518,7 +28072,7 @@ function hasUnsafeSwitchControl(node) {
|
|
|
27518
28072
|
function hasOpenDiscriminant(node, services) {
|
|
27519
28073
|
if (services === null) return false;
|
|
27520
28074
|
const type = services.program.getTypeChecker().getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(node));
|
|
27521
|
-
const openFlags =
|
|
28075
|
+
const openFlags = ts32.TypeFlags.Any | ts32.TypeFlags.Unknown | ts32.TypeFlags.String | ts32.TypeFlags.Number | ts32.TypeFlags.BigInt | ts32.TypeFlags.ESSymbol;
|
|
27522
28076
|
return (type.isUnion() ? type.types : [type]).some((part) => (part.flags & openFlags) !== 0);
|
|
27523
28077
|
}
|
|
27524
28078
|
var prefer_switch_for_repeated_equality_default = createRule({
|
|
@@ -29716,14 +30270,14 @@ import {
|
|
|
29716
30270
|
AST_NODE_TYPES as AST_NODE_TYPES143,
|
|
29717
30271
|
ESLintUtils as ESLintUtils25
|
|
29718
30272
|
} from "@typescript-eslint/utils";
|
|
29719
|
-
import
|
|
30273
|
+
import ts35 from "typescript";
|
|
29720
30274
|
|
|
29721
30275
|
// src/rules/_equivalent-zod-output-contracts.ts
|
|
29722
30276
|
import { isPropertyReadonlyInType, isTupleTypeReference, isTypeReference as isTypeReference3 } from "ts-api-utils";
|
|
29723
|
-
import
|
|
30277
|
+
import ts33 from "typescript";
|
|
29724
30278
|
var MAX_CONTRACT_PAIRS = 128;
|
|
29725
30279
|
var MAX_UNION_MEMBERS = 16;
|
|
29726
|
-
var UNSAFE_TYPES =
|
|
30280
|
+
var UNSAFE_TYPES = ts33.TypeFlags.Any | ts33.TypeFlags.Unknown | ts33.TypeFlags.Never;
|
|
29727
30281
|
function equivalentZodOutputContracts(checker, parsed, contract) {
|
|
29728
30282
|
const comparison2 = { checker, pending: [[parsed, contract]], seen: /* @__PURE__ */ new Map(), pairs: 0 };
|
|
29729
30283
|
while (comparison2.pending.length > 0) {
|
|
@@ -29783,8 +30337,8 @@ function equivalentContainers(comparison2, left, right) {
|
|
|
29783
30337
|
const rightTuple = isTupleTypeReference(right);
|
|
29784
30338
|
if (leftTuple !== rightTuple) return false;
|
|
29785
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;
|
|
29786
|
-
const leftIndex = comparison2.checker.getIndexInfoOfType(left,
|
|
29787
|
-
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);
|
|
29788
30342
|
if (leftIndex?.isReadonly !== rightIndex?.isReadonly) return false;
|
|
29789
30343
|
const leftArguments = comparison2.checker.getTypeArguments(left);
|
|
29790
30344
|
const rightArguments = comparison2.checker.getTypeArguments(right);
|
|
@@ -29794,10 +30348,10 @@ function equivalentContainers(comparison2, left, right) {
|
|
|
29794
30348
|
});
|
|
29795
30349
|
}
|
|
29796
30350
|
function hasClassDeclaration(type) {
|
|
29797
|
-
return type.getSymbol()?.getDeclarations()?.some(
|
|
30351
|
+
return type.getSymbol()?.getDeclarations()?.some(ts33.isClassDeclaration) === true || type.isIntersection() && type.types.some(hasClassDeclaration);
|
|
29798
30352
|
}
|
|
29799
30353
|
function objectLike(type) {
|
|
29800
|
-
return (type.flags &
|
|
30354
|
+
return (type.flags & ts33.TypeFlags.Object) !== 0 || type.isIntersection();
|
|
29801
30355
|
}
|
|
29802
30356
|
function equivalentProperties(comparison2, left, right) {
|
|
29803
30357
|
const { checker } = comparison2;
|
|
@@ -29812,12 +30366,12 @@ function equivalentProperties(comparison2, left, right) {
|
|
|
29812
30366
|
return true;
|
|
29813
30367
|
}
|
|
29814
30368
|
function opaqueObject(checker, type) {
|
|
29815
|
-
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;
|
|
29816
30370
|
}
|
|
29817
30371
|
function equivalentProperty(comparison2, left, right, property, other) {
|
|
29818
30372
|
const { checker } = comparison2;
|
|
29819
30373
|
if (opaqueProperty(property) || opaqueProperty(other)) return false;
|
|
29820
|
-
if ((property.flags &
|
|
30374
|
+
if ((property.flags & ts33.SymbolFlags.Optional) !== (other.flags & ts33.SymbolFlags.Optional)) return false;
|
|
29821
30375
|
if (isPropertyReadonlyInType(left, property.getEscapedName(), checker) !== isPropertyReadonlyInType(right, other.getEscapedName(), checker)) return false;
|
|
29822
30376
|
const declaration = property.valueDeclaration ?? property.getDeclarations()?.[0];
|
|
29823
30377
|
const otherDeclaration = other.valueDeclaration ?? other.getDeclarations()?.[0];
|
|
@@ -29828,39 +30382,39 @@ function equivalentProperty(comparison2, left, right, property, other) {
|
|
|
29828
30382
|
);
|
|
29829
30383
|
}
|
|
29830
30384
|
function opaqueProperty(property) {
|
|
29831
|
-
return property.getDeclarations()?.some((declaration) =>
|
|
30385
|
+
return property.getDeclarations()?.some((declaration) => ts33.isGetAccessorDeclaration(declaration) || ts33.isSetAccessorDeclaration(declaration) || ts33.isMethodDeclaration(declaration) || ts33.isMethodSignature(declaration)) === true;
|
|
29832
30386
|
}
|
|
29833
30387
|
|
|
29834
30388
|
// src/rules/_has-authoritative-output-contract.ts
|
|
29835
|
-
import
|
|
30389
|
+
import ts34 from "typescript";
|
|
29836
30390
|
function hasAuthoritativeOutputContract(checker, output, contract) {
|
|
29837
30391
|
const callable = enclosingCallable(output);
|
|
29838
30392
|
if (callable === void 0) return false;
|
|
29839
30393
|
const authority = { checker, contract };
|
|
29840
|
-
if (
|
|
30394
|
+
if (ts34.isMethodDeclaration(callable) || ts34.isGetAccessorDeclaration(callable)) return memberContract2(authority, callable);
|
|
29841
30395
|
const binding3 = callable.parent;
|
|
29842
|
-
if ((
|
|
29843
|
-
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;
|
|
29844
30398
|
const contextual = checker.getContextualType(callable);
|
|
29845
30399
|
return contextual !== void 0 && callableContract(authority, contextual, callable);
|
|
29846
30400
|
}
|
|
29847
30401
|
function enclosingCallable(output) {
|
|
29848
30402
|
for (let current = output; current !== void 0; current = current.parent) {
|
|
29849
|
-
if (
|
|
29850
|
-
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;
|
|
29851
30405
|
}
|
|
29852
30406
|
return void 0;
|
|
29853
30407
|
}
|
|
29854
30408
|
function memberContract2(authority, member3) {
|
|
29855
|
-
if ((
|
|
30409
|
+
if ((ts34.getCombinedModifierFlags(member3) & (ts34.ModifierFlags.Private | ts34.ModifierFlags.Static)) !== 0 || ts34.isPrivateIdentifier(member3.name)) return false;
|
|
29856
30410
|
const owner = member3.parent;
|
|
29857
30411
|
const name = authority.checker.getSymbolAtLocation(member3.name)?.getName();
|
|
29858
30412
|
if (name === void 0) return false;
|
|
29859
|
-
if (
|
|
30413
|
+
if (ts34.isObjectLiteralExpression(owner)) {
|
|
29860
30414
|
const contextual = authority.checker.getContextualType(owner);
|
|
29861
30415
|
return contextual !== void 0 && propertyContract(authority, contextual, name, member3, member3);
|
|
29862
30416
|
}
|
|
29863
|
-
if (!
|
|
30417
|
+
if (!ts34.isClassDeclaration(owner) && !ts34.isClassExpression(owner)) return false;
|
|
29864
30418
|
for (const clause of owner.heritageClauses ?? []) {
|
|
29865
30419
|
for (const heritage of clause.types) {
|
|
29866
30420
|
if (propertyContract(authority, authority.checker.getTypeAtLocation(heritage), name, member3)) return true;
|
|
@@ -29872,9 +30426,9 @@ function propertyContract(authority, type, name, member3, contextual) {
|
|
|
29872
30426
|
const property = authority.checker.getPropertyOfType(type, name);
|
|
29873
30427
|
if (property === void 0) return false;
|
|
29874
30428
|
const declared = authority.checker.getTypeOfSymbolAtLocation(property, member3);
|
|
29875
|
-
if (!
|
|
30429
|
+
if (!ts34.isGetAccessorDeclaration(member3)) return callableContract(authority, declared, contextual);
|
|
29876
30430
|
return property.getDeclarations()?.some((declaration) => {
|
|
29877
|
-
if (!(
|
|
30431
|
+
if (!(ts34.isPropertySignature(declaration) || ts34.isPropertyDeclaration(declaration) || ts34.isGetAccessorDeclaration(declaration)) || declaration.type === void 0 || declaration === member3) return false;
|
|
29878
30432
|
return returnsContract(authority, contextual === void 0 ? declared : authority.checker.getTypeAtLocation(declaration.type));
|
|
29879
30433
|
}) === true;
|
|
29880
30434
|
}
|
|
@@ -30213,12 +30767,12 @@ function handWrittenObjectDeclaration(symbol) {
|
|
|
30213
30767
|
const [declaration] = declarations;
|
|
30214
30768
|
if (declarations.length !== 1 || declaration === void 0) return null;
|
|
30215
30769
|
const plainMembers = (members) => members.length > 0 && members.every(
|
|
30216
|
-
(member3) =>
|
|
30770
|
+
(member3) => ts35.isPropertySignature(member3) && member3.type !== void 0 && member3.modifiers?.some((modifier) => modifier.kind === ts35.SyntaxKind.ReadonlyKeyword) !== true
|
|
30217
30771
|
);
|
|
30218
|
-
if (
|
|
30772
|
+
if (ts35.isInterfaceDeclaration(declaration) && declaration.typeParameters === void 0 && declaration.heritageClauses === void 0 && plainMembers(declaration.members)) {
|
|
30219
30773
|
return declaration;
|
|
30220
30774
|
}
|
|
30221
|
-
if (
|
|
30775
|
+
if (ts35.isTypeAliasDeclaration(declaration) && declaration.typeParameters === void 0 && ts35.isTypeLiteralNode(declaration.type) && plainMembers(declaration.type.members)) {
|
|
30222
30776
|
return declaration;
|
|
30223
30777
|
}
|
|
30224
30778
|
return null;
|
|
@@ -30301,7 +30855,7 @@ import {
|
|
|
30301
30855
|
ESLintUtils as ESLintUtils26,
|
|
30302
30856
|
AST_NODE_TYPES as AST_NODE_TYPES145
|
|
30303
30857
|
} from "@typescript-eslint/utils";
|
|
30304
|
-
import
|
|
30858
|
+
import ts36 from "typescript";
|
|
30305
30859
|
|
|
30306
30860
|
// src/rules/_empty-assertion-fix.ts
|
|
30307
30861
|
import {
|
|
@@ -30481,7 +31035,7 @@ function isExhaustiveFiniteSwitch(node, services) {
|
|
|
30481
31035
|
const constituents = discriminantType.isUnion() ? discriminantType.types : [discriminantType];
|
|
30482
31036
|
if (!discriminantType.isUnion() || constituents.length < 2) return false;
|
|
30483
31037
|
if (constituents.every(
|
|
30484
|
-
(constituent) => (constituent.flags &
|
|
31038
|
+
(constituent) => (constituent.flags & ts36.TypeFlags.BooleanLiteral) !== 0
|
|
30485
31039
|
)) {
|
|
30486
31040
|
return false;
|
|
30487
31041
|
}
|
|
@@ -30503,7 +31057,7 @@ function isExhaustiveFiniteSwitch(node, services) {
|
|
|
30503
31057
|
return [...expected].every((key) => handled.has(key));
|
|
30504
31058
|
}
|
|
30505
31059
|
function finiteTypeKey(type, checker) {
|
|
30506
|
-
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;
|
|
30507
31061
|
return (type.flags & finiteFlags) !== 0 ? checker.typeToString(type) : null;
|
|
30508
31062
|
}
|
|
30509
31063
|
var require_assert_never_default = createRule({
|