@sarj/eslint-plugin 16.36.6 → 16.38.50
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 +908 -761
- package/dist/index.js +902 -755
- package/dist/rule-examples.cjs +168 -44
- package/dist/rule-examples.js +168 -44
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -627,41 +627,230 @@ var no_mutating_input_with_result_default = createRule({
|
|
|
627
627
|
});
|
|
628
628
|
|
|
629
629
|
// src/rules/no-negative-only-http-status-assertion.ts
|
|
630
|
-
import { AST_NODE_TYPES as
|
|
630
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES9, ASTUtils as ASTUtils7 } from "@typescript-eslint/utils";
|
|
631
|
+
|
|
632
|
+
// src/rules/_native-fetch-reference.ts
|
|
633
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES7, ASTUtils as ASTUtils5 } from "@typescript-eslint/utils";
|
|
634
|
+
|
|
635
|
+
// src/rules/_native-runtime-unchanged.ts
|
|
636
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES6, ASTUtils as ASTUtils4 } from "@typescript-eslint/utils";
|
|
637
|
+
|
|
638
|
+
// src/rules/_stable-value-binding.ts
|
|
639
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES4 } from "@typescript-eslint/utils";
|
|
640
|
+
function typeOnlyReference(reference) {
|
|
641
|
+
if (reference.isTypeReference && !reference.isValueReference) return true;
|
|
642
|
+
let current = outerExpression(reference.identifier);
|
|
643
|
+
while (current.parent?.type === AST_NODE_TYPES4.TSQualifiedName && current.parent.left === current) {
|
|
644
|
+
current = current.parent;
|
|
645
|
+
}
|
|
646
|
+
return current.parent?.type === AST_NODE_TYPES4.TSTypeQuery && current.parent.exprName === current;
|
|
647
|
+
}
|
|
648
|
+
function stableValueBinding(variable, acceptRead) {
|
|
649
|
+
let initializer;
|
|
650
|
+
return variable.references.every((reference) => {
|
|
651
|
+
if (!reference.isWrite()) return acceptRead?.(reference) ?? true;
|
|
652
|
+
if (reference.init !== true || initializer !== void 0 && initializer !== reference.identifier) return false;
|
|
653
|
+
initializer = reference.identifier;
|
|
654
|
+
return true;
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// src/rules/_static-string.ts
|
|
659
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES5, ASTUtils as ASTUtils3 } from "@typescript-eslint/utils";
|
|
660
|
+
function staticString(node) {
|
|
661
|
+
if (node === void 0) return null;
|
|
662
|
+
const value = unwrapExpression(node);
|
|
663
|
+
if (value.type === AST_NODE_TYPES5.Literal && typeof value.value === "string") return value.value;
|
|
664
|
+
return value.type === AST_NODE_TYPES5.TemplateLiteral && value.expressions.length === 0 ? value.quasis[0]?.value.cooked ?? null : null;
|
|
665
|
+
}
|
|
666
|
+
var SCOPED_STRING_VALUES = /* @__PURE__ */ new WeakMap();
|
|
667
|
+
function scopedStaticString(node, sourceCode) {
|
|
668
|
+
let value = unwrapExpression(node);
|
|
669
|
+
if (value.type !== AST_NODE_TYPES5.Identifier) return staticString(value);
|
|
670
|
+
let values = SCOPED_STRING_VALUES.get(sourceCode);
|
|
671
|
+
if (values === void 0) {
|
|
672
|
+
values = /* @__PURE__ */ new WeakMap();
|
|
673
|
+
SCOPED_STRING_VALUES.set(sourceCode, values);
|
|
674
|
+
}
|
|
675
|
+
const seen = /* @__PURE__ */ new Set();
|
|
676
|
+
const pending = [];
|
|
677
|
+
let result = null;
|
|
678
|
+
while (value.type === AST_NODE_TYPES5.Identifier) {
|
|
679
|
+
const binding3 = ASTUtils3.findVariable(sourceCode.getScope(value), value.name);
|
|
680
|
+
if (binding3 === null || seen.has(binding3)) break;
|
|
681
|
+
if (values.has(binding3)) {
|
|
682
|
+
result = values.get(binding3) ?? null;
|
|
683
|
+
break;
|
|
684
|
+
}
|
|
685
|
+
seen.add(binding3);
|
|
686
|
+
pending.push(binding3);
|
|
687
|
+
const definition = binding3.defs.length === 1 ? binding3.defs[0] : void 0;
|
|
688
|
+
if (definition?.type !== "Variable" || definition.node.id.type !== AST_NODE_TYPES5.Identifier || definition.node.init === null || binding3.references.some((reference) => reference.isWrite() && reference.init !== true)) break;
|
|
689
|
+
value = unwrapExpression(definition.node.init);
|
|
690
|
+
if (value.type !== AST_NODE_TYPES5.Identifier) result = staticString(value);
|
|
691
|
+
}
|
|
692
|
+
for (const binding3 of pending) values.set(binding3, result);
|
|
693
|
+
return result;
|
|
694
|
+
}
|
|
695
|
+
function staticPropertyName(node, sourceCode) {
|
|
696
|
+
const direct = ASTUtils3.getPropertyName(node);
|
|
697
|
+
if (direct !== null || !node.computed) return direct;
|
|
698
|
+
const key = node.type === AST_NODE_TYPES5.MemberExpression ? node.property : node.key;
|
|
699
|
+
return scopedStaticString(key, sourceCode);
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// src/rules/_native-runtime-unchanged.ts
|
|
703
|
+
var INDEXES = /* @__PURE__ */ new WeakMap();
|
|
704
|
+
var GLOBAL_OBJECTS = /* @__PURE__ */ new Set(["globalThis", "global", "window", "self"]);
|
|
705
|
+
function nativeRuntimeUnchanged(sourceCode, name) {
|
|
706
|
+
const index = runtimeIndex(sourceCode);
|
|
707
|
+
const cached = index.results.get(name);
|
|
708
|
+
if (cached !== void 0) return cached;
|
|
709
|
+
const changed = index.nodes.some((node) => node.type === AST_NODE_TYPES6.MemberExpression && staticPropertyName(node, sourceCode) === "constructor" || name === "fetch" && node.type === AST_NODE_TYPES6.Property && node.parent.type === AST_NODE_TYPES6.ObjectPattern && staticPropertyName(node, sourceCode) === "constructor" || name === "RegExp" && node.type === AST_NODE_TYPES6.Literal && "regex" in node) || index.references.some((reference) => (name !== "fetch" || !typeOnlyReference(reference)) && unsafeReference(reference.identifier, sourceCode, name, index));
|
|
710
|
+
index.results.set(name, !changed);
|
|
711
|
+
return !changed;
|
|
712
|
+
}
|
|
713
|
+
function runtimeIndex(sourceCode) {
|
|
714
|
+
const cached = INDEXES.get(sourceCode);
|
|
715
|
+
if (cached !== void 0) return cached;
|
|
716
|
+
const references = sourceCode.scopeManager?.scopes.flatMap((scope) => scope.references.filter((reference) => reference.isValueReference !== false)) ?? [];
|
|
717
|
+
const nodes = [];
|
|
718
|
+
const pending = [sourceCode.ast];
|
|
719
|
+
while (pending.length > 0) {
|
|
720
|
+
const node = pending.pop();
|
|
721
|
+
if (node === void 0) continue;
|
|
722
|
+
nodes.push(node);
|
|
723
|
+
forEachAstChild(node, sourceCode.visitorKeys, (child) => {
|
|
724
|
+
pending.push(child);
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
const index = { references, nodes, results: /* @__PURE__ */ new Map(), fetchAliases: /* @__PURE__ */ new Map() };
|
|
728
|
+
INDEXES.set(sourceCode, index);
|
|
729
|
+
return index;
|
|
730
|
+
}
|
|
731
|
+
function unsafeReference(node, sourceCode, name, index) {
|
|
732
|
+
if (!ambient(node, sourceCode)) return false;
|
|
733
|
+
if (node.name === "eval" || node.name === "Function") return true;
|
|
734
|
+
if (node.name === name) return name === "fetch" ? !fetchRead(node, sourceCode, index) : !nativeRead(node, name);
|
|
735
|
+
if (!GLOBAL_OBJECTS.has(node.name)) return false;
|
|
736
|
+
const value = outerExpression(node);
|
|
737
|
+
const property = value.parent;
|
|
738
|
+
if (name === "fetch" && property?.type === AST_NODE_TYPES6.UnaryExpression && property.operator === "typeof") return false;
|
|
739
|
+
if (property?.type !== AST_NODE_TYPES6.MemberExpression || property.object !== value) {
|
|
740
|
+
return name !== "fetch" || !fetchProjection(value, sourceCode, index);
|
|
741
|
+
}
|
|
742
|
+
const key = staticPropertyName(property, sourceCode);
|
|
743
|
+
if (key === null || key === "eval" || key === "Function" || key === "constructor") return true;
|
|
744
|
+
if (name === "fetch" && GLOBAL_OBJECTS.has(key)) return true;
|
|
745
|
+
return key === name && !(name === "fetch" ? fetchRead(property, sourceCode, index) : nativeRead(property, name));
|
|
746
|
+
}
|
|
747
|
+
function ambient(node, sourceCode) {
|
|
748
|
+
const variable = ASTUtils4.findVariable(sourceCode.getScope(node), node.name);
|
|
749
|
+
return variable === null || variable.defs.length === 0;
|
|
750
|
+
}
|
|
751
|
+
function fetchUse(node, sourceCode) {
|
|
752
|
+
const value = outerExpression(node);
|
|
753
|
+
const parent = value.parent;
|
|
754
|
+
if (parent?.type === AST_NODE_TYPES6.CallExpression && parent.callee === value || parent?.type === AST_NODE_TYPES6.UnaryExpression && parent.operator === "typeof") return true;
|
|
755
|
+
if (parent?.type !== AST_NODE_TYPES6.VariableDeclarator || parent.init !== value || parent.id.type !== AST_NODE_TYPES6.Identifier) return false;
|
|
756
|
+
return stableConstBinding(parent.id, sourceCode) ?? false;
|
|
757
|
+
}
|
|
758
|
+
function stableConstBinding(node, sourceCode) {
|
|
759
|
+
const binding3 = ASTUtils4.findVariable(sourceCode.getScope(node), node.name);
|
|
760
|
+
if (binding3 === null || binding3.defs.length !== 1) return null;
|
|
761
|
+
const [definition] = binding3.defs;
|
|
762
|
+
return definition?.type === "Variable" && definition.parent.kind === "const" && definition.node.init !== null && definition.parent.parent.type !== AST_NODE_TYPES6.ExportNamedDeclaration && !binding3.references.some((reference) => reference.isWrite() && reference.init !== true) ? binding3 : null;
|
|
763
|
+
}
|
|
764
|
+
function fetchRead(node, sourceCode, index) {
|
|
765
|
+
const use = fetchUse(node, sourceCode);
|
|
766
|
+
return use === true || use !== false && fetchAliasRead(use, sourceCode, index);
|
|
767
|
+
}
|
|
768
|
+
function fetchAliasRead(binding3, sourceCode, index) {
|
|
769
|
+
const pending = [binding3];
|
|
770
|
+
const visited = [];
|
|
771
|
+
let safe = true;
|
|
772
|
+
while (pending.length > 0 && safe) {
|
|
773
|
+
const current = pending.pop();
|
|
774
|
+
if (current === void 0) continue;
|
|
775
|
+
const cached = index.fetchAliases.get(current);
|
|
776
|
+
if (cached === "safe") continue;
|
|
777
|
+
if (cached !== void 0) {
|
|
778
|
+
safe = false;
|
|
779
|
+
break;
|
|
780
|
+
}
|
|
781
|
+
index.fetchAliases.set(current, "visiting");
|
|
782
|
+
visited.push(current);
|
|
783
|
+
const captures = fetchAliasCaptures(current, sourceCode);
|
|
784
|
+
if (captures === false) {
|
|
785
|
+
safe = false;
|
|
786
|
+
break;
|
|
787
|
+
}
|
|
788
|
+
for (const captured of captures) pending.push(captured);
|
|
789
|
+
}
|
|
790
|
+
for (const current of visited) index.fetchAliases.set(current, safe ? "safe" : "unsafe");
|
|
791
|
+
return safe;
|
|
792
|
+
}
|
|
793
|
+
function fetchAliasCaptures(binding3, sourceCode) {
|
|
794
|
+
const captures = [];
|
|
795
|
+
for (const reference of binding3.references) {
|
|
796
|
+
if (reference.isValueReference === false || reference.init === true || typeOnlyReference(reference)) continue;
|
|
797
|
+
const use = fetchUse(reference.identifier, sourceCode);
|
|
798
|
+
if (use === false) return false;
|
|
799
|
+
if (use !== true) captures.push(use);
|
|
800
|
+
}
|
|
801
|
+
return captures;
|
|
802
|
+
}
|
|
803
|
+
function fetchProjection(node, sourceCode, index) {
|
|
804
|
+
const declaration = node.parent;
|
|
805
|
+
if (declaration?.type !== AST_NODE_TYPES6.VariableDeclarator || declaration.init !== node || declaration.id.type !== AST_NODE_TYPES6.ObjectPattern || declaration.id.properties.length !== 1) return false;
|
|
806
|
+
const [property] = declaration.id.properties;
|
|
807
|
+
if (property?.type !== AST_NODE_TYPES6.Property || staticPropertyName(property, sourceCode) !== "fetch" || property.value.type !== AST_NODE_TYPES6.Identifier) return false;
|
|
808
|
+
const binding3 = stableConstBinding(property.value, sourceCode);
|
|
809
|
+
return binding3 !== null && fetchAliasRead(binding3, sourceCode, index);
|
|
810
|
+
}
|
|
811
|
+
function nativeRead(node, name) {
|
|
812
|
+
const value = outerExpression(node);
|
|
813
|
+
const parent = value.parent;
|
|
814
|
+
if (parent?.type === AST_NODE_TYPES6.UnaryExpression && parent.operator === "typeof") return true;
|
|
815
|
+
if (name !== "Error") return false;
|
|
816
|
+
return parent?.type === AST_NODE_TYPES6.NewExpression && parent.callee === value || parent?.type === AST_NODE_TYPES6.BinaryExpression && parent.operator === "instanceof" && parent.right === value;
|
|
817
|
+
}
|
|
631
818
|
|
|
632
819
|
// src/rules/_native-fetch-reference.ts
|
|
633
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES4, ASTUtils as ASTUtils3 } from "@typescript-eslint/utils";
|
|
634
820
|
var GLOBAL_RECEIVERS = /* @__PURE__ */ new Set(["globalThis", "self", "window"]);
|
|
635
|
-
function nativeFetchReference(node, sourceCode
|
|
821
|
+
function nativeFetchReference(node, sourceCode) {
|
|
822
|
+
return lexicalFetchReference(node, sourceCode) && nativeRuntimeUnchanged(sourceCode, "fetch");
|
|
823
|
+
}
|
|
824
|
+
function lexicalFetchReference(node, sourceCode, seen = /* @__PURE__ */ new Set()) {
|
|
636
825
|
const expression = unwrapExpression(node);
|
|
637
|
-
if (expression.type ===
|
|
638
|
-
return
|
|
826
|
+
if (expression.type === AST_NODE_TYPES7.MemberExpression) {
|
|
827
|
+
return staticPropertyName(expression, sourceCode) === "fetch" && globalReceiver(expression.object, sourceCode);
|
|
639
828
|
}
|
|
640
|
-
if (expression.type !==
|
|
641
|
-
const binding3 =
|
|
829
|
+
if (expression.type !== AST_NODE_TYPES7.Identifier) return false;
|
|
830
|
+
const binding3 = ASTUtils5.findVariable(sourceCode.getScope(expression), expression.name);
|
|
642
831
|
if (binding3 === null || binding3.defs.length === 0) return expression.name === "fetch";
|
|
643
832
|
if (seen.has(binding3) || seen.size >= 8 || binding3.defs.length !== 1 || binding3.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
644
833
|
seen.add(binding3);
|
|
645
834
|
const [definition] = binding3.defs;
|
|
646
835
|
if (definition?.type !== "Variable" || definition.parent.kind !== "const" || definition.node.init === null) return false;
|
|
647
|
-
if (definition.node.id.type ===
|
|
648
|
-
return
|
|
836
|
+
if (definition.node.id.type === AST_NODE_TYPES7.Identifier) {
|
|
837
|
+
return lexicalFetchReference(definition.node.init, sourceCode, seen);
|
|
649
838
|
}
|
|
650
|
-
return definition.node.id.type ===
|
|
839
|
+
return definition.node.id.type === AST_NODE_TYPES7.ObjectPattern && globalReceiver(definition.node.init, sourceCode) && definition.node.id.properties.some((property) => property.type === AST_NODE_TYPES7.Property && staticPropertyName(property, sourceCode) === "fetch" && property.value.type === AST_NODE_TYPES7.Identifier && ASTUtils5.findVariable(sourceCode.getScope(property.value), property.value.name) === binding3);
|
|
651
840
|
}
|
|
652
841
|
function globalReceiver(node, sourceCode) {
|
|
653
842
|
const receiver = unwrapExpression(node);
|
|
654
|
-
return receiver.type ===
|
|
843
|
+
return receiver.type === AST_NODE_TYPES7.Identifier && GLOBAL_RECEIVERS.has(receiver.name) && !ASTUtils5.findVariable(sourceCode.getScope(receiver), receiver.name)?.defs.length;
|
|
655
844
|
}
|
|
656
845
|
|
|
657
846
|
// src/rules/_test-mock-provenance.ts
|
|
658
|
-
import { AST_NODE_TYPES as
|
|
847
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES8, ASTUtils as ASTUtils6 } from "@typescript-eslint/utils";
|
|
659
848
|
function importedTestMockNamespace(source, identifier) {
|
|
660
|
-
const binding3 =
|
|
849
|
+
const binding3 = ASTUtils6.findVariable(source.getScope(identifier), identifier.name);
|
|
661
850
|
const importedBinding = runtimeImportBinding(binding3);
|
|
662
|
-
if (importedBinding === null || importedBinding.specifier.type !==
|
|
851
|
+
if (importedBinding === null || importedBinding.specifier.type !== AST_NODE_TYPES8.ImportSpecifier) return null;
|
|
663
852
|
const specifier = importedBinding.specifier;
|
|
664
|
-
const imported = specifier.imported.type ===
|
|
853
|
+
const imported = specifier.imported.type === AST_NODE_TYPES8.Identifier ? specifier.imported.name : specifier.imported.value;
|
|
665
854
|
const module = importedBinding.module;
|
|
666
855
|
if (module === "vitest" && (imported === "vi" || imported === "vitest")) return "vitest";
|
|
667
856
|
if (module === "@jest/globals" && imported === "jest") return "jest";
|
|
@@ -669,12 +858,12 @@ function importedTestMockNamespace(source, identifier) {
|
|
|
669
858
|
}
|
|
670
859
|
function isUnshadowedTestMockGlobal(source, identifier) {
|
|
671
860
|
if (identifier.name !== "vi" && identifier.name !== "jest") return false;
|
|
672
|
-
const binding3 =
|
|
861
|
+
const binding3 = ASTUtils6.findVariable(source.getScope(identifier), identifier.name);
|
|
673
862
|
return binding3 === null || binding3.defs.length === 0 && !binding3.references.some((reference) => reference.isWrite());
|
|
674
863
|
}
|
|
675
864
|
var TEST_FRAMEWORK_MODULES = /* @__PURE__ */ new Set(["@jest/globals", "@playwright/test", "bun:test", "node:test", "vitest"]);
|
|
676
865
|
function runtimeTestFrameworkName(source, identifier, kind) {
|
|
677
|
-
const binding3 =
|
|
866
|
+
const binding3 = ASTUtils6.findVariable(source.getScope(identifier), identifier.name);
|
|
678
867
|
if (binding3 === null || binding3.defs.length === 0) {
|
|
679
868
|
return binding3?.references.some((reference) => reference.isWrite()) ? null : identifier.name;
|
|
680
869
|
}
|
|
@@ -682,22 +871,22 @@ function runtimeTestFrameworkName(source, identifier, kind) {
|
|
|
682
871
|
if (importedBinding === null) return null;
|
|
683
872
|
const { specifier, module } = importedBinding;
|
|
684
873
|
const isNodeAssertion = kind === "assertion" && (module === "node:assert" || module === "node:assert/strict");
|
|
685
|
-
if (specifier.type ===
|
|
874
|
+
if (specifier.type === AST_NODE_TYPES8.ImportSpecifier) {
|
|
686
875
|
if (isNodeAssertion) return "assert";
|
|
687
876
|
if (!TEST_FRAMEWORK_MODULES.has(module)) return null;
|
|
688
|
-
const imported = specifier.imported.type ===
|
|
877
|
+
const imported = specifier.imported.type === AST_NODE_TYPES8.Identifier ? specifier.imported.name : specifier.imported.value;
|
|
689
878
|
return imported;
|
|
690
879
|
}
|
|
691
880
|
if (isNodeAssertion) return "assert";
|
|
692
|
-
return kind === "test" && module === "node:test" && specifier.type ===
|
|
881
|
+
return kind === "test" && module === "node:test" && specifier.type === AST_NODE_TYPES8.ImportDefaultSpecifier ? "test" : null;
|
|
693
882
|
}
|
|
694
883
|
function runtimeImportBinding(binding3) {
|
|
695
884
|
if (binding3?.defs.length !== 1) return null;
|
|
696
885
|
const definition = binding3.defs[0];
|
|
697
|
-
if (definition?.type !== "ImportBinding" || definition.parent.type !==
|
|
886
|
+
if (definition?.type !== "ImportBinding" || definition.parent.type !== AST_NODE_TYPES8.ImportDeclaration || definition.parent.importKind === "type") return null;
|
|
698
887
|
const specifier = definition.node;
|
|
699
|
-
if (specifier.type !==
|
|
700
|
-
if (specifier.type ===
|
|
888
|
+
if (specifier.type !== AST_NODE_TYPES8.ImportSpecifier && specifier.type !== AST_NODE_TYPES8.ImportDefaultSpecifier && specifier.type !== AST_NODE_TYPES8.ImportNamespaceSpecifier) return null;
|
|
889
|
+
if (specifier.type === AST_NODE_TYPES8.ImportSpecifier && specifier.importKind === "type") return null;
|
|
701
890
|
return { module: definition.parent.source.value, specifier };
|
|
702
891
|
}
|
|
703
892
|
function vitestFixtureTestName(source, identifier) {
|
|
@@ -705,24 +894,24 @@ function vitestFixtureTestName(source, identifier) {
|
|
|
705
894
|
}
|
|
706
895
|
function fixtureTestName(node, source, seen) {
|
|
707
896
|
node = unwrapExpression(node);
|
|
708
|
-
if (node.type ===
|
|
897
|
+
if (node.type === AST_NODE_TYPES8.CallExpression) {
|
|
709
898
|
const callee = unwrapExpression(node.callee);
|
|
710
|
-
return !node.optional && callee.type ===
|
|
899
|
+
return !node.optional && callee.type === AST_NODE_TYPES8.MemberExpression && !callee.optional && ASTUtils6.getPropertyName(callee) === "extend" && node.arguments.length > 0 && !node.arguments.some((argument) => argument.type === AST_NODE_TYPES8.SpreadElement) ? fixtureTestName(callee.object, source, seen) : null;
|
|
711
900
|
}
|
|
712
|
-
if (node.type !==
|
|
713
|
-
const binding3 =
|
|
901
|
+
if (node.type !== AST_NODE_TYPES8.Identifier) return null;
|
|
902
|
+
const binding3 = ASTUtils6.findVariable(source.getScope(node), node.name);
|
|
714
903
|
if (binding3 === null || seen.has(binding3) || !unchangedFixtureApi(binding3)) return null;
|
|
715
904
|
seen.add(binding3);
|
|
716
905
|
const imported = runtimeImportBinding(binding3);
|
|
717
|
-
if (imported?.module === "vitest" && imported.specifier.type ===
|
|
906
|
+
if (imported?.module === "vitest" && imported.specifier.type === AST_NODE_TYPES8.ImportSpecifier) {
|
|
718
907
|
const name = imported.specifier.imported;
|
|
719
|
-
const value = name.type ===
|
|
908
|
+
const value = name.type === AST_NODE_TYPES8.Identifier ? name.name : name.value;
|
|
720
909
|
return value === "test" || value === "it" ? value : null;
|
|
721
910
|
}
|
|
722
911
|
const definition = binding3.defs[0];
|
|
723
|
-
if (binding3.defs.length !== 1 || definition?.node.type !==
|
|
912
|
+
if (binding3.defs.length !== 1 || definition?.node.type !== AST_NODE_TYPES8.VariableDeclarator || definition.node.id.type !== AST_NODE_TYPES8.Identifier || definition.node.parent.kind !== "const" || definition.node.init === null || definition.node.init.range[1] > node.range[0]) return null;
|
|
724
913
|
const initializer = unwrapExpression(definition.node.init);
|
|
725
|
-
return initializer.type ===
|
|
914
|
+
return initializer.type === AST_NODE_TYPES8.CallExpression ? fixtureTestName(initializer, source, seen) : null;
|
|
726
915
|
}
|
|
727
916
|
var FIXTURE_API_STABILITY = /* @__PURE__ */ new WeakMap();
|
|
728
917
|
function unchangedFixtureApi(binding3) {
|
|
@@ -732,9 +921,9 @@ function unchangedFixtureApi(binding3) {
|
|
|
732
921
|
if (reference.isWrite()) return reference.init === true;
|
|
733
922
|
if (reference.isTypeReference && !reference.isValueReference) return true;
|
|
734
923
|
let use = outerExpression(reference.identifier);
|
|
735
|
-
while (use.parent?.type ===
|
|
924
|
+
while (use.parent?.type === AST_NODE_TYPES8.MemberExpression && use.parent.object === use) use = outerExpression(use.parent);
|
|
736
925
|
const parent = use.parent;
|
|
737
|
-
return parent?.type ===
|
|
926
|
+
return parent?.type === AST_NODE_TYPES8.CallExpression && parent.callee === use || parent?.type === AST_NODE_TYPES8.ExportSpecifier || parent?.type === AST_NODE_TYPES8.ExportDefaultDeclaration || parent?.type === AST_NODE_TYPES8.TSTypeQuery || parent?.type === AST_NODE_TYPES8.UnaryExpression && parent.operator === "typeof";
|
|
738
927
|
});
|
|
739
928
|
FIXTURE_API_STABILITY.set(binding3, unchanged);
|
|
740
929
|
return unchanged;
|
|
@@ -764,72 +953,72 @@ var NO_NEGATIVE_ONLY_HTTP_STATUS_ASSERTION_DOCUMENTATION = {
|
|
|
764
953
|
]
|
|
765
954
|
};
|
|
766
955
|
function statusAssertion(source, call) {
|
|
767
|
-
if (call.arguments.length !== 1 || call.arguments[0]?.type !==
|
|
768
|
-
const matcher =
|
|
956
|
+
if (call.arguments.length !== 1 || call.arguments[0]?.type !== AST_NODE_TYPES9.Literal || typeof call.arguments[0].value !== "number" || call.callee.type !== AST_NODE_TYPES9.MemberExpression) return null;
|
|
957
|
+
const matcher = ASTUtils7.getPropertyName(call.callee);
|
|
769
958
|
if (matcher === null) return null;
|
|
770
959
|
let object = unwrapExpression(call.callee.object);
|
|
771
|
-
const negative = object.type ===
|
|
772
|
-
if (negative && object.type ===
|
|
773
|
-
if (object.type !==
|
|
960
|
+
const negative = object.type === AST_NODE_TYPES9.MemberExpression && ASTUtils7.getPropertyName(object) === "not";
|
|
961
|
+
if (negative && object.type === AST_NODE_TYPES9.MemberExpression) object = unwrapExpression(object.object);
|
|
962
|
+
if (object.type !== AST_NODE_TYPES9.CallExpression || object.arguments.length !== 1 || object.callee.type !== AST_NODE_TYPES9.Identifier || runtimeTestFrameworkName(source, object.callee, "assertion") !== "expect") return null;
|
|
774
963
|
const argument = object.arguments[0];
|
|
775
|
-
const response = argument === void 0 || argument.type ===
|
|
964
|
+
const response = argument === void 0 || argument.type === AST_NODE_TYPES9.SpreadElement ? null : fetchResponse(source, argument);
|
|
776
965
|
return response === null ? null : { response, expected: call.arguments[0].value, matcher, negative };
|
|
777
966
|
}
|
|
778
967
|
function fetchResponse(source, value) {
|
|
779
968
|
const node = unwrapExpression(value);
|
|
780
|
-
if (node.type !==
|
|
969
|
+
if (node.type !== AST_NODE_TYPES9.MemberExpression || ASTUtils7.getPropertyName(node) !== "status" || node.object.type !== AST_NODE_TYPES9.Identifier) return null;
|
|
781
970
|
return responseBinding(source, node.object);
|
|
782
971
|
}
|
|
783
972
|
function responseBinding(source, node, seen = /* @__PURE__ */ new Set()) {
|
|
784
|
-
const variable =
|
|
973
|
+
const variable = ASTUtils7.findVariable(source.getScope(node), node.name);
|
|
785
974
|
const definition = variable?.defs[0]?.node;
|
|
786
975
|
if (variable?.defs.length !== 1 || seen.has(variable) || variable.references.some((reference) => reference.isWrite() && !reference.init)) return null;
|
|
787
976
|
seen.add(variable);
|
|
788
977
|
const parameter = variable.defs[0];
|
|
789
|
-
if (parameter?.type === "Parameter" && parameter.name.type ===
|
|
978
|
+
if (parameter?.type === "Parameter" && parameter.name.type === AST_NODE_TYPES9.Identifier) {
|
|
790
979
|
const annotation = parameter.name.typeAnnotation?.typeAnnotation;
|
|
791
|
-
return annotation?.type ===
|
|
980
|
+
return annotation?.type === AST_NODE_TYPES9.TSTypeReference && annotation.typeName.type === AST_NODE_TYPES9.Identifier && annotation.typeName.name === "Response" && (ASTUtils7.findVariable(source.getScope(annotation.typeName), "Response")?.defs.length ?? 0) === 0 ? variable : null;
|
|
792
981
|
}
|
|
793
|
-
if (definition?.type !==
|
|
982
|
+
if (definition?.type !== AST_NODE_TYPES9.VariableDeclarator || definition.parent.kind !== "const" || definition.init === null) return null;
|
|
794
983
|
let initial = unwrapExpression(definition.init);
|
|
795
|
-
if (initial.type ===
|
|
796
|
-
if (initial.type ===
|
|
984
|
+
if (initial.type === AST_NODE_TYPES9.AwaitExpression) initial = unwrapExpression(initial.argument);
|
|
985
|
+
if (initial.type === AST_NODE_TYPES9.Identifier) return responseBinding(source, initial, seen);
|
|
797
986
|
return nativeResponse(initial, source) ? variable : null;
|
|
798
987
|
}
|
|
799
988
|
function nativeResponse(initial, source) {
|
|
800
|
-
if (initial.type ===
|
|
801
|
-
if (initial.type ===
|
|
802
|
-
if (initial.type !==
|
|
989
|
+
if (initial.type === AST_NODE_TYPES9.NewExpression && initial.callee.type === AST_NODE_TYPES9.Identifier && initial.callee.name === "Response" && (ASTUtils7.findVariable(source.getScope(initial.callee), "Response")?.defs.length ?? 0) === 0) return true;
|
|
990
|
+
if (initial.type === AST_NODE_TYPES9.CallExpression && nativeFetchReference(initial.callee, source)) return true;
|
|
991
|
+
if (initial.type !== AST_NODE_TYPES9.CallExpression || initial.callee.type !== AST_NODE_TYPES9.Identifier) return false;
|
|
803
992
|
const callee = initial.callee;
|
|
804
|
-
const binding3 =
|
|
993
|
+
const binding3 = ASTUtils7.findVariable(source.getScope(callee), callee.name);
|
|
805
994
|
if ((binding3?.defs.length ?? 0) === 0) return callee.name === "fetch";
|
|
806
995
|
const imported = binding3?.defs[0];
|
|
807
|
-
if (binding3?.defs.length !== 1 || imported?.type !== "ImportBinding" || imported.parent.type !==
|
|
996
|
+
if (binding3?.defs.length !== 1 || imported?.type !== "ImportBinding" || imported.parent.type !== AST_NODE_TYPES9.ImportDeclaration || imported.parent.importKind === "type" || !FETCH_MODULES.has(imported.parent.source.value)) return false;
|
|
808
997
|
const specifier = imported.node;
|
|
809
|
-
if (specifier.type ===
|
|
810
|
-
if (specifier.type !==
|
|
811
|
-
const importedName7 = specifier.imported.type ===
|
|
998
|
+
if (specifier.type === AST_NODE_TYPES9.ImportDefaultSpecifier) return imported.parent.source.value === "node-fetch";
|
|
999
|
+
if (specifier.type !== AST_NODE_TYPES9.ImportSpecifier || specifier.importKind === "type") return false;
|
|
1000
|
+
const importedName7 = specifier.imported.type === AST_NODE_TYPES9.Identifier ? specifier.imported.name : specifier.imported.value;
|
|
812
1001
|
return importedName7 === "fetch";
|
|
813
1002
|
}
|
|
814
1003
|
function enclosingTest(source, node) {
|
|
815
1004
|
for (let current = node.parent; current != null; current = current.parent) {
|
|
816
|
-
if (current.type ===
|
|
817
|
-
if (current.type !==
|
|
1005
|
+
if (current.type === AST_NODE_TYPES9.FunctionDeclaration) return null;
|
|
1006
|
+
if (current.type !== AST_NODE_TYPES9.ArrowFunctionExpression && current.type !== AST_NODE_TYPES9.FunctionExpression) continue;
|
|
818
1007
|
const registration2 = directArgumentCall(current);
|
|
819
1008
|
const callee = registration2?.callee;
|
|
820
|
-
if (callee?.type !==
|
|
1009
|
+
if (callee?.type !== AST_NODE_TYPES9.Identifier) return null;
|
|
821
1010
|
const name = runtimeTestFrameworkName(source, callee, "test") ?? vitestFixtureTestName(source, callee);
|
|
822
1011
|
return name === "test" || name === "it" ? current : null;
|
|
823
1012
|
}
|
|
824
1013
|
return null;
|
|
825
1014
|
}
|
|
826
1015
|
function hasExactStatus(source, test, response) {
|
|
827
|
-
if (test.body.type !==
|
|
1016
|
+
if (test.body.type !== AST_NODE_TYPES9.BlockStatement) return false;
|
|
828
1017
|
return test.body.body.some((statement) => {
|
|
829
|
-
if (statement.type !==
|
|
1018
|
+
if (statement.type !== AST_NODE_TYPES9.ExpressionStatement) return false;
|
|
830
1019
|
let expression = unwrapExpression(statement.expression);
|
|
831
|
-
if (expression.type ===
|
|
832
|
-
if (expression.type !==
|
|
1020
|
+
if (expression.type === AST_NODE_TYPES9.AwaitExpression) expression = unwrapExpression(expression.argument);
|
|
1021
|
+
if (expression.type !== AST_NODE_TYPES9.CallExpression) return false;
|
|
833
1022
|
const assertion = statusAssertion(source, expression);
|
|
834
1023
|
return assertion !== null && assertion.response === response && !assertion.negative && EXACT_MATCHERS.has(assertion.matcher) && Number.isInteger(assertion.expected) && assertion.expected >= HTTP_STATUS_MIN && assertion.expected <= SERVER_ERROR_MAX;
|
|
835
1024
|
});
|
|
@@ -860,7 +1049,7 @@ var no_negative_only_http_status_assertion_default = createRule({
|
|
|
860
1049
|
});
|
|
861
1050
|
|
|
862
1051
|
// src/rules/prefer-test-fixture-reuse.ts
|
|
863
|
-
import { AST_NODE_TYPES as
|
|
1052
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES10, ASTUtils as ASTUtils8 } from "@typescript-eslint/utils";
|
|
864
1053
|
var MAX_DEPTH = 8;
|
|
865
1054
|
var FRAMEWORKS = /* @__PURE__ */ new Set(["vitest", "@playwright/test"]);
|
|
866
1055
|
var TEST_MODIFIERS = /* @__PURE__ */ new Set(["only", "skip", "concurrent", "sequential"]);
|
|
@@ -882,24 +1071,24 @@ var PREFER_TEST_FIXTURE_REUSE_DOCUMENTATION = {
|
|
|
882
1071
|
]
|
|
883
1072
|
};
|
|
884
1073
|
function stableBinding(source, identifier) {
|
|
885
|
-
const variable =
|
|
1074
|
+
const variable = ASTUtils8.findVariable(source.getScope(identifier), identifier.name);
|
|
886
1075
|
if (variable?.defs.length !== 1 || variable.references.some((reference) => reference.isWrite() && !reference.init)) return null;
|
|
887
1076
|
return variable;
|
|
888
1077
|
}
|
|
889
1078
|
function constructorBinding(source, node, depth = 0) {
|
|
890
1079
|
node = unwrapExpression(node);
|
|
891
|
-
if (node.type !==
|
|
1080
|
+
if (node.type !== AST_NODE_TYPES10.Identifier || depth >= MAX_DEPTH) return null;
|
|
892
1081
|
const variable = stableBinding(source, node);
|
|
893
1082
|
const definition = variable?.defs[0];
|
|
894
1083
|
if (variable === null || definition === void 0) return null;
|
|
895
1084
|
if (definition.type === "ClassName") return variable;
|
|
896
|
-
if (definition.type === "ImportBinding" && definition.parent.type ===
|
|
897
|
-
if (definition.node.type ===
|
|
1085
|
+
if (definition.type === "ImportBinding" && definition.parent.type === AST_NODE_TYPES10.ImportDeclaration && definition.parent.importKind !== "type" && (definition.node.type !== AST_NODE_TYPES10.ImportSpecifier || definition.node.importKind !== "type")) return variable;
|
|
1086
|
+
if (definition.node.type === AST_NODE_TYPES10.VariableDeclarator && definition.node.parent.kind === "const" && definition.node.init !== null && definition.node.range[1] < node.range[0]) return constructorBinding(source, definition.node.init, depth + 1);
|
|
898
1087
|
return null;
|
|
899
1088
|
}
|
|
900
1089
|
function fixtureApi(source, expression, depth = 0) {
|
|
901
1090
|
const node = unwrapExpression(expression);
|
|
902
|
-
if (node.type !==
|
|
1091
|
+
if (node.type !== AST_NODE_TYPES10.Identifier || depth >= MAX_DEPTH) return null;
|
|
903
1092
|
const variable = stableBinding(source, node);
|
|
904
1093
|
const definition = variable?.defs[0];
|
|
905
1094
|
if (variable === null || definition === void 0) return null;
|
|
@@ -911,35 +1100,35 @@ function fixtureApi(source, expression, depth = 0) {
|
|
|
911
1100
|
}
|
|
912
1101
|
function importedFixtureApi(variable) {
|
|
913
1102
|
const definition = variable.defs[0];
|
|
914
|
-
if (definition?.type === "ImportBinding" && definition.parent.type ===
|
|
1103
|
+
if (definition?.type === "ImportBinding" && definition.parent.type === AST_NODE_TYPES10.ImportDeclaration && FRAMEWORKS.has(definition.parent.source.value) && definition.parent.importKind !== "type" && definition.node.type === AST_NODE_TYPES10.ImportSpecifier && definition.node.importKind !== "type") {
|
|
915
1104
|
const imported = definition.node.imported;
|
|
916
|
-
const name = imported.type ===
|
|
1105
|
+
const name = imported.type === AST_NODE_TYPES10.Identifier ? imported.name : imported.value;
|
|
917
1106
|
return name === "test" || name === "it";
|
|
918
1107
|
}
|
|
919
1108
|
return false;
|
|
920
1109
|
}
|
|
921
1110
|
function fixtureExtension(declaration, before) {
|
|
922
|
-
if (declaration.type !==
|
|
1111
|
+
if (declaration.type !== AST_NODE_TYPES10.VariableDeclarator || declaration.parent.kind !== "const" || declaration.init === null || declaration.range[1] >= before) return null;
|
|
923
1112
|
const initial = unwrapExpression(declaration.init);
|
|
924
|
-
if (initial.type !==
|
|
1113
|
+
if (initial.type !== AST_NODE_TYPES10.CallExpression || initial.optional || initial.arguments.length !== 1 || initial.callee.type !== AST_NODE_TYPES10.MemberExpression || initial.callee.optional || ASTUtils8.getPropertyName(initial.callee) !== "extend") return null;
|
|
925
1114
|
const declarations = initial.arguments[0];
|
|
926
|
-
if (declarations?.type !==
|
|
1115
|
+
if (declarations?.type !== AST_NODE_TYPES10.ObjectExpression || declarations.properties.some((property) => property.type !== AST_NODE_TYPES10.Property || property.computed || property.kind !== "init")) return null;
|
|
927
1116
|
return { receiver: initial.callee.object, declarations };
|
|
928
1117
|
}
|
|
929
1118
|
function fixtureApiStable(variable) {
|
|
930
1119
|
return !variable.references.some((reference) => {
|
|
931
1120
|
if (reference.isWrite() || reference.isTypeReference && !reference.isValueReference) return false;
|
|
932
1121
|
let use = reference.identifier;
|
|
933
|
-
while (use.parent?.type ===
|
|
934
|
-
return use.parent?.type !==
|
|
1122
|
+
while (use.parent?.type === AST_NODE_TYPES10.MemberExpression && use.parent.object === use) use = use.parent;
|
|
1123
|
+
return use.parent?.type !== AST_NODE_TYPES10.CallExpression || use.parent.callee !== use;
|
|
935
1124
|
});
|
|
936
1125
|
}
|
|
937
1126
|
function fixtureConstructors(source, declarations, inherited) {
|
|
938
1127
|
const result = new Map(inherited);
|
|
939
1128
|
for (const property of declarations.properties) {
|
|
940
|
-
if (property.type !==
|
|
941
|
-
const name =
|
|
942
|
-
if (name === null || property.value.type ===
|
|
1129
|
+
if (property.type !== AST_NODE_TYPES10.Property || property.computed || property.value.type === AST_NODE_TYPES10.AssignmentPattern) continue;
|
|
1130
|
+
const name = ASTUtils8.getPropertyName(property);
|
|
1131
|
+
if (name === null || property.value.type === AST_NODE_TYPES10.TSEmptyBodyFunctionExpression) continue;
|
|
943
1132
|
const constructor = fixtureConstructor(source, property.value);
|
|
944
1133
|
if (constructor === null) result.delete(name);
|
|
945
1134
|
else result.set(name, constructor);
|
|
@@ -948,24 +1137,24 @@ function fixtureConstructors(source, declarations, inherited) {
|
|
|
948
1137
|
}
|
|
949
1138
|
function fixtureConstructor(source, value) {
|
|
950
1139
|
value = unwrapExpression(value);
|
|
951
|
-
if (value.type !==
|
|
1140
|
+
if (value.type !== AST_NODE_TYPES10.ArrowFunctionExpression && value.type !== AST_NODE_TYPES10.FunctionExpression) return newConstructor(source, value);
|
|
952
1141
|
const use = value.params[1];
|
|
953
|
-
if (use?.type !==
|
|
1142
|
+
if (use?.type !== AST_NODE_TYPES10.Identifier) return null;
|
|
954
1143
|
const binding3 = stableBinding(source, use);
|
|
955
|
-
const calls = scopeNodes(value.body, source).filter((node) => node.type ===
|
|
1144
|
+
const calls = scopeNodes(value.body, source).filter((node) => node.type === AST_NODE_TYPES10.CallExpression && !node.optional && node.arguments.length === 1 && node.callee.type === AST_NODE_TYPES10.Identifier && stableBinding(source, node.callee) === binding3);
|
|
956
1145
|
if (calls.length !== 1 || binding3 === null) return null;
|
|
957
1146
|
const argument = calls[0]?.arguments[0];
|
|
958
|
-
return argument === void 0 || argument.type ===
|
|
1147
|
+
return argument === void 0 || argument.type === AST_NODE_TYPES10.SpreadElement ? null : newConstructor(source, argument);
|
|
959
1148
|
}
|
|
960
1149
|
function newConstructor(source, expression) {
|
|
961
1150
|
const value = unwrapExpression(expression);
|
|
962
|
-
if (value.type ===
|
|
963
|
-
if (value.type !==
|
|
1151
|
+
if (value.type === AST_NODE_TYPES10.NewExpression) return constructorBinding(source, value.callee);
|
|
1152
|
+
if (value.type !== AST_NODE_TYPES10.Identifier) return null;
|
|
964
1153
|
const variable = stableBinding(source, value);
|
|
965
1154
|
const declaration = variable?.defs[0]?.node;
|
|
966
|
-
if (declaration?.type !==
|
|
1155
|
+
if (declaration?.type !== AST_NODE_TYPES10.VariableDeclarator || declaration.parent.kind !== "const" || declaration.init === null || declaration.range[1] >= value.range[0]) return null;
|
|
967
1156
|
const initial = unwrapExpression(declaration.init);
|
|
968
|
-
return initial.type ===
|
|
1157
|
+
return initial.type === AST_NODE_TYPES10.NewExpression ? constructorBinding(source, initial.callee) : null;
|
|
969
1158
|
}
|
|
970
1159
|
function scopeNodes(root, source) {
|
|
971
1160
|
const result = [];
|
|
@@ -974,7 +1163,7 @@ function scopeNodes(root, source) {
|
|
|
974
1163
|
const node = pending.pop();
|
|
975
1164
|
if (node === void 0) continue;
|
|
976
1165
|
result.push(node);
|
|
977
|
-
if (node !== root && (node.type ===
|
|
1166
|
+
if (node !== root && (node.type === AST_NODE_TYPES10.ArrowFunctionExpression || node.type === AST_NODE_TYPES10.FunctionExpression || node.type === AST_NODE_TYPES10.FunctionDeclaration || node.type === AST_NODE_TYPES10.ClassDeclaration || node.type === AST_NODE_TYPES10.ClassExpression)) continue;
|
|
978
1167
|
for (const key of source.visitorKeys[node.type] ?? []) {
|
|
979
1168
|
const value = Reflect.get(node, key);
|
|
980
1169
|
if (Array.isArray(value)) pending.push(...value.filter(isNode2));
|
|
@@ -988,13 +1177,13 @@ function isNode2(value) {
|
|
|
988
1177
|
}
|
|
989
1178
|
function testApiCallee(expression) {
|
|
990
1179
|
let node = unwrapExpression(expression);
|
|
991
|
-
while (node.type ===
|
|
1180
|
+
while (node.type === AST_NODE_TYPES10.MemberExpression && !node.optional && TEST_MODIFIERS.has(ASTUtils8.getPropertyName(node) ?? "")) node = unwrapExpression(node.object);
|
|
992
1181
|
return node;
|
|
993
1182
|
}
|
|
994
1183
|
function requestingFunction(node) {
|
|
995
1184
|
for (let current = node.parent; current != null; current = current.parent) {
|
|
996
|
-
if (current.type ===
|
|
997
|
-
if (current.type ===
|
|
1185
|
+
if (current.type === AST_NODE_TYPES10.ArrowFunctionExpression || current.type === AST_NODE_TYPES10.FunctionExpression) return current;
|
|
1186
|
+
if (current.type === AST_NODE_TYPES10.FunctionDeclaration) return null;
|
|
998
1187
|
}
|
|
999
1188
|
return null;
|
|
1000
1189
|
}
|
|
@@ -1016,13 +1205,13 @@ var prefer_test_fixture_reuse_default = createRule({
|
|
|
1016
1205
|
const call = functionNode === null ? null : directArgumentCall(functionNode);
|
|
1017
1206
|
if (functionNode === null || call === null) return;
|
|
1018
1207
|
const parameter = functionNode.params[0];
|
|
1019
|
-
if (parameter?.type !==
|
|
1208
|
+
if (parameter?.type !== AST_NODE_TYPES10.ObjectPattern) return;
|
|
1020
1209
|
const entries = fixtureApi(context.sourceCode, testApiCallee(call.callee));
|
|
1021
1210
|
const constructor = constructorBinding(context.sourceCode, node.callee);
|
|
1022
1211
|
if (entries === null || constructor === null) return;
|
|
1023
1212
|
for (const property of parameter.properties) {
|
|
1024
|
-
if (property.type !==
|
|
1025
|
-
const name =
|
|
1213
|
+
if (property.type !== AST_NODE_TYPES10.Property || property.computed) continue;
|
|
1214
|
+
const name = ASTUtils8.getPropertyName(property);
|
|
1026
1215
|
if (name !== null && entries.get(name) === constructor) {
|
|
1027
1216
|
context.report({ node, messageId: "reuseFixture", data: { fixture: name } });
|
|
1028
1217
|
return;
|
|
@@ -1034,7 +1223,7 @@ var prefer_test_fixture_reuse_default = createRule({
|
|
|
1034
1223
|
});
|
|
1035
1224
|
|
|
1036
1225
|
// src/rules/no-return-disposed-resource.ts
|
|
1037
|
-
import { AST_NODE_TYPES as
|
|
1226
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES11, ASTUtils as ASTUtils9 } from "@typescript-eslint/utils";
|
|
1038
1227
|
var NO_RETURN_DISPOSED_RESOURCE_DOCUMENTATION = {
|
|
1039
1228
|
defaultLevel: "warning",
|
|
1040
1229
|
summary: "Do not return a resource whose using declaration disposes it before the caller receives it.",
|
|
@@ -1054,16 +1243,16 @@ var NO_RETURN_DISPOSED_RESOURCE_DOCUMENTATION = {
|
|
|
1054
1243
|
};
|
|
1055
1244
|
function owningFunction(node) {
|
|
1056
1245
|
for (let current = node.parent; current != null; current = current.parent) {
|
|
1057
|
-
if (current.type ===
|
|
1246
|
+
if (current.type === AST_NODE_TYPES11.FunctionDeclaration || current.type === AST_NODE_TYPES11.FunctionExpression || current.type === AST_NODE_TYPES11.ArrowFunctionExpression) return current;
|
|
1058
1247
|
}
|
|
1059
1248
|
return null;
|
|
1060
1249
|
}
|
|
1061
1250
|
function resourceOwner(source, value, seen = /* @__PURE__ */ new Set()) {
|
|
1062
1251
|
const node = unwrapExpression(value);
|
|
1063
|
-
if (node.type !==
|
|
1064
|
-
const variable =
|
|
1252
|
+
if (node.type !== AST_NODE_TYPES11.Identifier) return null;
|
|
1253
|
+
const variable = ASTUtils9.findVariable(source.getScope(node), node.name);
|
|
1065
1254
|
const definition = variable?.defs[0];
|
|
1066
|
-
if (variable === null || variable?.defs.length !== 1 || definition === void 0 || seen.has(variable) || variable.references.some((reference) => reference.isWrite() && !reference.init) || definition.node.type !==
|
|
1255
|
+
if (variable === null || variable?.defs.length !== 1 || definition === void 0 || seen.has(variable) || variable.references.some((reference) => reference.isWrite() && !reference.init) || definition.node.type !== AST_NODE_TYPES11.VariableDeclarator) return null;
|
|
1067
1256
|
const declaration = definition.node;
|
|
1068
1257
|
if (declaration.parent.kind === "using" || declaration.parent.kind === "await using") return declaration;
|
|
1069
1258
|
if (declaration.parent.kind !== "const" || declaration.init === null || declaration.range[1] >= node.range[0]) return null;
|
|
@@ -1092,7 +1281,7 @@ var no_return_disposed_resource_default = createRule({
|
|
|
1092
1281
|
});
|
|
1093
1282
|
|
|
1094
1283
|
// src/rules/require-jwt-lifetime.ts
|
|
1095
|
-
import { AST_NODE_TYPES as
|
|
1284
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES12, ASTUtils as ASTUtils10 } from "@typescript-eslint/utils";
|
|
1096
1285
|
var REQUIRE_JWT_LIFETIME_DOCUMENTATION = {
|
|
1097
1286
|
defaultLevel: "warning",
|
|
1098
1287
|
summary: "Require an expiration claim or a maximum token age when returning a verified JWT.",
|
|
@@ -1120,36 +1309,36 @@ var require_jwt_lifetime_default = createRule({
|
|
|
1120
1309
|
function inspect(input) {
|
|
1121
1310
|
if (input === null) return;
|
|
1122
1311
|
let node = unwrapExpression(input);
|
|
1123
|
-
if (node.type ===
|
|
1124
|
-
if (node.type !==
|
|
1312
|
+
if (node.type === AST_NODE_TYPES12.AwaitExpression) node = unwrapExpression(node.argument);
|
|
1313
|
+
if (node.type !== AST_NODE_TYPES12.CallExpression || !isVerifier(node.callee)) return;
|
|
1125
1314
|
if (!missingLifetime(node.arguments[2])) return;
|
|
1126
1315
|
context.report({ node, messageId: "lifetime" });
|
|
1127
1316
|
}
|
|
1128
1317
|
function isVerifier(node) {
|
|
1129
1318
|
node = unwrapExpression(node);
|
|
1130
|
-
if (node.type ===
|
|
1131
|
-
const variable =
|
|
1319
|
+
if (node.type === AST_NODE_TYPES12.Identifier) {
|
|
1320
|
+
const variable = ASTUtils10.findVariable(sourceCode.getScope(node), node.name);
|
|
1132
1321
|
const declaration = variable?.defs[0]?.node;
|
|
1133
|
-
return variable?.defs.length === 1 && declaration?.type ===
|
|
1322
|
+
return variable?.defs.length === 1 && declaration?.type === AST_NODE_TYPES12.ImportSpecifier && declaration.parent.type === AST_NODE_TYPES12.ImportDeclaration && declaration.importKind !== "type" && declaration.parent.importKind !== "type" && declaration.parent.source.value === "jose" && declaration.imported.type === AST_NODE_TYPES12.Identifier && declaration.imported.name === "jwtVerify";
|
|
1134
1323
|
}
|
|
1135
|
-
if (node.type !==
|
|
1136
|
-
const definition =
|
|
1137
|
-
return definition?.type ===
|
|
1324
|
+
if (node.type !== AST_NODE_TYPES12.MemberExpression || ASTUtils10.getPropertyName(node) !== "jwtVerify" || node.object.type !== AST_NODE_TYPES12.Identifier) return false;
|
|
1325
|
+
const definition = ASTUtils10.findVariable(sourceCode.getScope(node.object), node.object.name)?.defs[0]?.node;
|
|
1326
|
+
return definition?.type === AST_NODE_TYPES12.ImportNamespaceSpecifier && definition.parent.importKind !== "type" && definition.parent.source.value === "jose";
|
|
1138
1327
|
}
|
|
1139
1328
|
function missingLifetime(options) {
|
|
1140
1329
|
if (options === void 0) return true;
|
|
1141
|
-
if (options.type !==
|
|
1142
|
-
return !options.properties.some((property) => property.type ===
|
|
1330
|
+
if (options.type !== AST_NODE_TYPES12.ObjectExpression || options.properties.some((property) => property.type !== AST_NODE_TYPES12.Property || property.computed)) return false;
|
|
1331
|
+
return !options.properties.some((property) => property.type === AST_NODE_TYPES12.Property && lifetimeProperty(property));
|
|
1143
1332
|
}
|
|
1144
1333
|
function lifetimeProperty(property) {
|
|
1145
|
-
const name = property.key.type ===
|
|
1334
|
+
const name = property.key.type === AST_NODE_TYPES12.Identifier ? property.key.name : property.key.type === AST_NODE_TYPES12.Literal ? property.key.value : null;
|
|
1146
1335
|
if (name === "maxTokenAge") {
|
|
1147
|
-
if (property.value.type !==
|
|
1336
|
+
if (property.value.type !== AST_NODE_TYPES12.Literal) return true;
|
|
1148
1337
|
return typeof property.value.value === "number" && Number.isFinite(property.value.value) || typeof property.value.value === "string" && property.value.value.trim() !== "";
|
|
1149
1338
|
}
|
|
1150
1339
|
if (name !== "requiredClaims") return false;
|
|
1151
|
-
if (property.value.type !==
|
|
1152
|
-
return property.value.elements.some((element) => element?.type ===
|
|
1340
|
+
if (property.value.type !== AST_NODE_TYPES12.ArrayExpression || property.value.elements.some((element) => element?.type !== AST_NODE_TYPES12.Literal)) return true;
|
|
1341
|
+
return property.value.elements.some((element) => element?.type === AST_NODE_TYPES12.Literal && element.value === "exp");
|
|
1153
1342
|
}
|
|
1154
1343
|
return {
|
|
1155
1344
|
ReturnStatement(node) {
|
|
@@ -1163,7 +1352,7 @@ var require_jwt_lifetime_default = createRule({
|
|
|
1163
1352
|
});
|
|
1164
1353
|
|
|
1165
1354
|
// src/rules/no-discarded-validation-result.ts
|
|
1166
|
-
import { AST_NODE_TYPES as
|
|
1355
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES13, ASTUtils as ASTUtils11 } from "@typescript-eslint/utils";
|
|
1167
1356
|
|
|
1168
1357
|
// src/rules/_zod.ts
|
|
1169
1358
|
var ZOD_SCHEMA_NAME_RE = /Schema$|^Z[A-Z]/;
|
|
@@ -1199,52 +1388,52 @@ var no_discarded_validation_result_default = createRule({
|
|
|
1199
1388
|
function schema(node, depth = 0) {
|
|
1200
1389
|
if (depth > 24) return null;
|
|
1201
1390
|
node = unwrapExpression(node);
|
|
1202
|
-
if (node.type ===
|
|
1203
|
-
const variable =
|
|
1391
|
+
if (node.type === AST_NODE_TYPES13.Identifier) {
|
|
1392
|
+
const variable = ASTUtils11.findVariable(sourceCode.getScope(node), node.name);
|
|
1204
1393
|
const definition = variable?.defs[0]?.node;
|
|
1205
1394
|
if (variable?.defs.length !== 1) return null;
|
|
1206
|
-
if (definition?.type ===
|
|
1207
|
-
if (definition?.type ===
|
|
1208
|
-
if (definition?.type ===
|
|
1395
|
+
if (definition?.type === AST_NODE_TYPES13.ImportSpecifier && definition.parent.type === AST_NODE_TYPES13.ImportDeclaration && definition.importKind !== "type" && definition.parent.importKind !== "type" && isZodModule(definition.parent.source.value)) return { changed: false };
|
|
1396
|
+
if (definition?.type === AST_NODE_TYPES13.ImportNamespaceSpecifier && definition.parent.importKind !== "type" && isZodModule(definition.parent.source.value)) return { changed: false };
|
|
1397
|
+
if (definition?.type === AST_NODE_TYPES13.VariableDeclarator && definition.parent.kind === "const" && definition.init !== null && definition.range[1] < node.range[0] && !variable.references.some((reference) => reference.isWrite() && !reference.init)) return schema(definition.init, depth + 1);
|
|
1209
1398
|
return null;
|
|
1210
1399
|
}
|
|
1211
|
-
if (node.type ===
|
|
1400
|
+
if (node.type === AST_NODE_TYPES13.MemberExpression) {
|
|
1212
1401
|
const owner2 = schema(node.object, depth + 1);
|
|
1213
1402
|
return owner2;
|
|
1214
1403
|
}
|
|
1215
|
-
if (node.type !==
|
|
1404
|
+
if (node.type !== AST_NODE_TYPES13.CallExpression) return null;
|
|
1216
1405
|
const owner = schema(node.callee, depth + 1);
|
|
1217
1406
|
if (owner === null) return null;
|
|
1218
|
-
const invokedChange = node.callee.type ===
|
|
1219
|
-
const coerced = node.callee.type ===
|
|
1407
|
+
const invokedChange = node.callee.type === AST_NODE_TYPES13.MemberExpression && CHANGING.has(ASTUtils11.getPropertyName(node.callee) ?? "");
|
|
1408
|
+
const coerced = node.callee.type === AST_NODE_TYPES13.MemberExpression && coercionNamespace(node.callee.object);
|
|
1220
1409
|
const changedArgument = node.arguments.some((argument) => {
|
|
1221
|
-
if (argument.type ===
|
|
1222
|
-
if (argument.type ===
|
|
1410
|
+
if (argument.type === AST_NODE_TYPES13.ArrayExpression) return argument.elements.some((element) => element !== null && schema(element, depth + 1)?.changed === true);
|
|
1411
|
+
if (argument.type === AST_NODE_TYPES13.ObjectExpression) return argument.properties.some((property) => property.type === AST_NODE_TYPES13.Property && schema(property.value, depth + 1)?.changed === true);
|
|
1223
1412
|
return schema(argument, depth + 1)?.changed === true;
|
|
1224
1413
|
});
|
|
1225
1414
|
return { changed: owner.changed || invokedChange || coerced || changedArgument };
|
|
1226
1415
|
}
|
|
1227
1416
|
function coercionNamespace(node) {
|
|
1228
1417
|
let namespace = false;
|
|
1229
|
-
if (node.type ===
|
|
1418
|
+
if (node.type === AST_NODE_TYPES13.MemberExpression && ASTUtils11.getPropertyName(node) === "coerce") {
|
|
1230
1419
|
namespace = true;
|
|
1231
1420
|
node = node.object;
|
|
1232
1421
|
}
|
|
1233
|
-
if (node.type !==
|
|
1234
|
-
const variable =
|
|
1422
|
+
if (node.type !== AST_NODE_TYPES13.Identifier) return false;
|
|
1423
|
+
const variable = ASTUtils11.findVariable(sourceCode.getScope(node), node.name);
|
|
1235
1424
|
const definition = variable?.defs[0]?.node;
|
|
1236
|
-
if (variable?.defs.length !== 1 || definition === void 0 || definition.parent.type !==
|
|
1237
|
-
if (definition.type ===
|
|
1238
|
-
if (definition.type !==
|
|
1239
|
-
const name = definition.imported.type ===
|
|
1425
|
+
if (variable?.defs.length !== 1 || definition === void 0 || definition.parent.type !== AST_NODE_TYPES13.ImportDeclaration || definition.parent.importKind === "type" || !isZodModule(definition.parent.source.value)) return false;
|
|
1426
|
+
if (definition.type === AST_NODE_TYPES13.ImportNamespaceSpecifier) return namespace;
|
|
1427
|
+
if (definition.type !== AST_NODE_TYPES13.ImportSpecifier || definition.importKind === "type") return false;
|
|
1428
|
+
const name = definition.imported.type === AST_NODE_TYPES13.Identifier ? definition.imported.name : definition.imported.value;
|
|
1240
1429
|
return namespace ? name === "z" : name === "coerce";
|
|
1241
1430
|
}
|
|
1242
1431
|
return {
|
|
1243
1432
|
ExpressionStatement(statement) {
|
|
1244
1433
|
let expression = unwrapExpression(statement.expression);
|
|
1245
|
-
if (expression.type ===
|
|
1246
|
-
if (expression.type !==
|
|
1247
|
-
const method =
|
|
1434
|
+
if (expression.type === AST_NODE_TYPES13.AwaitExpression) expression = unwrapExpression(expression.argument);
|
|
1435
|
+
if (expression.type !== AST_NODE_TYPES13.CallExpression || expression.callee.type !== AST_NODE_TYPES13.MemberExpression) return;
|
|
1436
|
+
const method = ASTUtils11.getPropertyName(expression.callee);
|
|
1248
1437
|
if (!(/* @__PURE__ */ new Set(["parse", "parseAsync", "safeParse", "safeParseAsync"])).has(method ?? "")) return;
|
|
1249
1438
|
const owner = schema(expression.callee.object);
|
|
1250
1439
|
if (owner !== null && (owner.changed || method?.startsWith("safe") === true)) context.report({ node: expression, messageId: "discarded" });
|
|
@@ -1254,7 +1443,7 @@ var no_discarded_validation_result_default = createRule({
|
|
|
1254
1443
|
});
|
|
1255
1444
|
|
|
1256
1445
|
// src/rules/production-derived-test-cases.ts
|
|
1257
|
-
import { AST_NODE_TYPES as
|
|
1446
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES14, ASTUtils as ASTUtils12 } from "@typescript-eslint/utils";
|
|
1258
1447
|
var MEMBERSHIP = /(?:^|_)(?:ALLOWED|ELIGIBLE|REQUIRED|SUPPORTED)(?:_|$)/u;
|
|
1259
1448
|
var SUPPORT_PATH = /(?:^|[/_.-])(?:tests?|fixtures?|fakes?|mocks?|stubs?|__tests__)(?:[/_.-]|$)/u;
|
|
1260
1449
|
var PRODUCTION_DERIVED_TEST_CASES_DOCUMENTATION = {
|
|
@@ -1289,52 +1478,52 @@ var production_derived_test_cases_default = createRule({
|
|
|
1289
1478
|
const tables = [];
|
|
1290
1479
|
const asserted = /* @__PURE__ */ new Set();
|
|
1291
1480
|
function binding3(node) {
|
|
1292
|
-
return
|
|
1481
|
+
return ASTUtils12.findVariable(sourceCode.getScope(node), node.name);
|
|
1293
1482
|
}
|
|
1294
1483
|
function importedName7(node, module) {
|
|
1295
1484
|
const variable = binding3(node);
|
|
1296
1485
|
const specifier = variable?.defs[0]?.node;
|
|
1297
|
-
if (variable?.defs.length !== 1 || specifier?.type !==
|
|
1298
|
-
return specifier.imported.type ===
|
|
1486
|
+
if (variable?.defs.length !== 1 || specifier?.type !== AST_NODE_TYPES14.ImportSpecifier || specifier.importKind === "type" || specifier.parent.type !== AST_NODE_TYPES14.ImportDeclaration || specifier.parent.importKind === "type" || specifier.parent.source.value !== module || variable.references.some((reference) => reference.isWrite())) return null;
|
|
1487
|
+
return specifier.imported.type === AST_NODE_TYPES14.Identifier ? specifier.imported.name : specifier.imported.value;
|
|
1299
1488
|
}
|
|
1300
1489
|
function production(node) {
|
|
1301
1490
|
node = unwrapExpression(node);
|
|
1302
|
-
if (node.type !==
|
|
1491
|
+
if (node.type !== AST_NODE_TYPES14.Identifier) return null;
|
|
1303
1492
|
const variable = binding3(node);
|
|
1304
1493
|
const specifier = variable?.defs[0]?.node;
|
|
1305
|
-
if (variable?.defs.length !== 1 || specifier?.type !==
|
|
1306
|
-
const name = specifier.imported.type ===
|
|
1494
|
+
if (variable?.defs.length !== 1 || specifier?.type !== AST_NODE_TYPES14.ImportSpecifier || specifier.importKind === "type" || specifier.parent.type !== AST_NODE_TYPES14.ImportDeclaration || specifier.parent.importKind === "type" || !specifier.parent.source.value.startsWith(".") || SUPPORT_PATH.test(specifier.parent.source.value) || variable.references.some((reference) => reference.isWrite())) return null;
|
|
1495
|
+
const name = specifier.imported.type === AST_NODE_TYPES14.Identifier ? specifier.imported.name : specifier.imported.value;
|
|
1307
1496
|
return MEMBERSHIP.test(name) && !name.endsWith("REGISTRY") ? variable : null;
|
|
1308
1497
|
}
|
|
1309
1498
|
function runner(node) {
|
|
1310
1499
|
node = unwrapExpression(node);
|
|
1311
|
-
while (node.type ===
|
|
1312
|
-
if (node.type !==
|
|
1500
|
+
while (node.type === AST_NODE_TYPES14.MemberExpression && ["only", "skip", "concurrent", "sequential"].includes(ASTUtils12.getPropertyName(node) ?? "")) node = unwrapExpression(node.object);
|
|
1501
|
+
if (node.type !== AST_NODE_TYPES14.Identifier) return false;
|
|
1313
1502
|
const name = importedName7(node, "vitest");
|
|
1314
1503
|
return name === "test" || name === "it" || vitestFixtureTestName(sourceCode, node) !== null;
|
|
1315
1504
|
}
|
|
1316
1505
|
function caseTable(node) {
|
|
1317
|
-
return node.type ===
|
|
1506
|
+
return node.type === AST_NODE_TYPES14.CallExpression && node.callee.type === AST_NODE_TYPES14.MemberExpression && ["each", "for"].includes(ASTUtils12.getPropertyName(node.callee) ?? "") && runner(node.callee.object);
|
|
1318
1507
|
}
|
|
1319
1508
|
function literalTable(node, seen = /* @__PURE__ */ new Set()) {
|
|
1320
1509
|
node = unwrapExpression(node);
|
|
1321
1510
|
if (seen.has(node)) return false;
|
|
1322
1511
|
seen.add(node);
|
|
1323
|
-
if (node.type ===
|
|
1512
|
+
if (node.type === AST_NODE_TYPES14.Identifier) {
|
|
1324
1513
|
const variable = binding3(node);
|
|
1325
1514
|
const definition = variable?.defs[0]?.node;
|
|
1326
|
-
return variable?.defs.length === 1 && definition?.type ===
|
|
1515
|
+
return variable?.defs.length === 1 && definition?.type === AST_NODE_TYPES14.VariableDeclarator && definition.parent.kind === "const" && definition.init !== null && definition.range[1] < node.range[0] && variable.references.every((reference) => reference.init || !reference.isWrite() && reference.identifier.parent.type === AST_NODE_TYPES14.CallExpression && (caseTable(reference.identifier.parent) || reference.identifier.parent.callee.type === AST_NODE_TYPES14.Identifier && importedName7(reference.identifier.parent.callee, "vitest") === "expect" || reference.identifier.parent.callee.type === AST_NODE_TYPES14.MemberExpression && ["toEqual", "toStrictEqual"].includes(ASTUtils12.getPropertyName(reference.identifier.parent.callee) ?? ""))) && literalTable(definition.init, seen);
|
|
1327
1516
|
}
|
|
1328
|
-
return node.type ===
|
|
1517
|
+
return node.type === AST_NODE_TYPES14.ArrayExpression && node.elements.every((element) => element?.type === AST_NODE_TYPES14.Literal && !("regex" in element));
|
|
1329
1518
|
}
|
|
1330
1519
|
function unconditional(node) {
|
|
1331
1520
|
const statement = node.parent;
|
|
1332
|
-
if (statement.type !==
|
|
1333
|
-
if (statement.parent.type ===
|
|
1521
|
+
if (statement.type !== AST_NODE_TYPES14.ExpressionStatement) return false;
|
|
1522
|
+
if (statement.parent.type === AST_NODE_TYPES14.Program) return true;
|
|
1334
1523
|
const block = statement.parent;
|
|
1335
|
-
if (block.type !==
|
|
1524
|
+
if (block.type !== AST_NODE_TYPES14.BlockStatement || block.parent.type !== AST_NODE_TYPES14.ArrowFunctionExpression && block.parent.type !== AST_NODE_TYPES14.FunctionExpression) return false;
|
|
1336
1525
|
const call = block.parent.parent;
|
|
1337
|
-
return call.type ===
|
|
1526
|
+
return call.type === AST_NODE_TYPES14.CallExpression && runner(call.callee);
|
|
1338
1527
|
}
|
|
1339
1528
|
return {
|
|
1340
1529
|
CallExpression(node) {
|
|
@@ -1342,9 +1531,9 @@ var production_derived_test_cases_default = createRule({
|
|
|
1342
1531
|
const variable2 = production(node.arguments[0]);
|
|
1343
1532
|
if (variable2 !== null) tables.push({ node, variable: variable2 });
|
|
1344
1533
|
}
|
|
1345
|
-
if (node.callee.type !==
|
|
1534
|
+
if (node.callee.type !== AST_NODE_TYPES14.MemberExpression || !["toEqual", "toStrictEqual"].includes(ASTUtils12.getPropertyName(node.callee) ?? "") || node.arguments.length !== 1 || node.arguments[0] === void 0 || !literalTable(node.arguments[0]) || !unconditional(node)) return;
|
|
1346
1535
|
const expect = node.callee.object;
|
|
1347
|
-
if (expect.type !==
|
|
1536
|
+
if (expect.type !== AST_NODE_TYPES14.CallExpression || expect.callee.type !== AST_NODE_TYPES14.Identifier || importedName7(expect.callee, "vitest") !== "expect" || expect.arguments.length !== 1 || expect.arguments[0] === void 0) return;
|
|
1348
1537
|
const variable = production(expect.arguments[0]);
|
|
1349
1538
|
if (variable !== null) asserted.add(variable);
|
|
1350
1539
|
},
|
|
@@ -1356,14 +1545,14 @@ var production_derived_test_cases_default = createRule({
|
|
|
1356
1545
|
});
|
|
1357
1546
|
|
|
1358
1547
|
// src/rules/require-constrained-schema-integer.ts
|
|
1359
|
-
import { AST_NODE_TYPES as
|
|
1548
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES15, ASTUtils as ASTUtils13 } from "@typescript-eslint/utils";
|
|
1360
1549
|
var FIELD_MINIMUMS = /* @__PURE__ */ new Map([["limit", 1], ["version", 0]]);
|
|
1361
1550
|
var NUMBER_FACTORIES = /* @__PURE__ */ new Set(["number", "int", "int32", "uint32"]);
|
|
1362
1551
|
var PRESERVING = /* @__PURE__ */ new Set(["optional", "nullable", "nullish", "default", "catch", "readonly", "brand", "describe", "meta", "max", "lte", "lt", "finite", "safe", "multipleOf"]);
|
|
1363
1552
|
function numericLiteral(node) {
|
|
1364
1553
|
node = unwrapExpression(node);
|
|
1365
|
-
if (node.type ===
|
|
1366
|
-
if (node.type ===
|
|
1554
|
+
if (node.type === AST_NODE_TYPES15.Literal && typeof node.value === "number") return node.value;
|
|
1555
|
+
if (node.type === AST_NODE_TYPES15.UnaryExpression && (node.operator === "-" || node.operator === "+")) {
|
|
1367
1556
|
const value = numericLiteral(node.argument);
|
|
1368
1557
|
return value === null ? null : node.operator === "-" ? -value : value;
|
|
1369
1558
|
}
|
|
@@ -1400,35 +1589,35 @@ var require_constrained_schema_integer_default = createRule({
|
|
|
1400
1589
|
const sourceCode = context.sourceCode;
|
|
1401
1590
|
function factory(node) {
|
|
1402
1591
|
node = unwrapExpression(node);
|
|
1403
|
-
if (node.type ===
|
|
1592
|
+
if (node.type === AST_NODE_TYPES15.Identifier) {
|
|
1404
1593
|
const definition2 = imported(node);
|
|
1405
|
-
return definition2?.type ===
|
|
1594
|
+
return definition2?.type === AST_NODE_TYPES15.ImportSpecifier ? definition2.imported.type === AST_NODE_TYPES15.Identifier ? definition2.imported.name : definition2.imported.value : null;
|
|
1406
1595
|
}
|
|
1407
|
-
if (node.type !==
|
|
1596
|
+
if (node.type !== AST_NODE_TYPES15.MemberExpression) return null;
|
|
1408
1597
|
let receiver = unwrapExpression(node.object);
|
|
1409
|
-
if (receiver.type ===
|
|
1410
|
-
if (receiver.type !==
|
|
1598
|
+
if (receiver.type === AST_NODE_TYPES15.MemberExpression && ASTUtils13.getPropertyName(receiver) === "coerce") receiver = unwrapExpression(receiver.object);
|
|
1599
|
+
if (receiver.type !== AST_NODE_TYPES15.Identifier) return null;
|
|
1411
1600
|
const definition = imported(receiver);
|
|
1412
|
-
if (definition === null || definition.type ===
|
|
1413
|
-
return
|
|
1601
|
+
if (definition === null || definition.type === AST_NODE_TYPES15.ImportSpecifier && (definition.imported.type === AST_NODE_TYPES15.Identifier ? definition.imported.name : definition.imported.value) !== "z") return null;
|
|
1602
|
+
return ASTUtils13.getPropertyName(node);
|
|
1414
1603
|
}
|
|
1415
1604
|
function imported(identifier) {
|
|
1416
|
-
const variable =
|
|
1605
|
+
const variable = ASTUtils13.findVariable(sourceCode.getScope(identifier), identifier.name);
|
|
1417
1606
|
const definition = variable?.defs[0]?.node;
|
|
1418
|
-
if (variable?.defs.length !== 1 || definition?.type !==
|
|
1419
|
-
return definition.type ===
|
|
1607
|
+
if (variable?.defs.length !== 1 || definition?.type !== AST_NODE_TYPES15.ImportSpecifier && definition?.type !== AST_NODE_TYPES15.ImportNamespaceSpecifier || definition.parent.type !== AST_NODE_TYPES15.ImportDeclaration || definition.parent.importKind === "type" || !isZodModule(definition.parent.source.value)) return null;
|
|
1608
|
+
return definition.type === AST_NODE_TYPES15.ImportSpecifier && definition.importKind === "type" ? null : definition;
|
|
1420
1609
|
}
|
|
1421
1610
|
function constrained(value, minimum) {
|
|
1422
1611
|
const calls = [];
|
|
1423
1612
|
value = unwrapExpression(value);
|
|
1424
|
-
while (value.type ===
|
|
1613
|
+
while (value.type === AST_NODE_TYPES15.CallExpression) {
|
|
1425
1614
|
const name = factory(value.callee);
|
|
1426
1615
|
if (name !== null) {
|
|
1427
1616
|
return chainContract(name, calls, minimum);
|
|
1428
1617
|
}
|
|
1429
1618
|
const callee = unwrapExpression(value.callee);
|
|
1430
|
-
if (callee.type !==
|
|
1431
|
-
const method =
|
|
1619
|
+
if (callee.type !== AST_NODE_TYPES15.MemberExpression) return null;
|
|
1620
|
+
const method = ASTUtils13.getPropertyName(callee);
|
|
1432
1621
|
if (method === null) return null;
|
|
1433
1622
|
calls.push({ method, call: value });
|
|
1434
1623
|
value = unwrapExpression(callee.object);
|
|
@@ -1453,7 +1642,7 @@ var require_constrained_schema_integer_default = createRule({
|
|
|
1453
1642
|
}
|
|
1454
1643
|
function lowerBound(call, minimum, exclusive) {
|
|
1455
1644
|
const argument = call.arguments[0];
|
|
1456
|
-
if (argument === void 0 || argument.type ===
|
|
1645
|
+
if (argument === void 0 || argument.type === AST_NODE_TYPES15.SpreadElement) return null;
|
|
1457
1646
|
const bound = numericLiteral(argument);
|
|
1458
1647
|
return bound === null || bound >= minimum - (exclusive ? 1 : 0);
|
|
1459
1648
|
}
|
|
@@ -1462,10 +1651,10 @@ var require_constrained_schema_integer_default = createRule({
|
|
|
1462
1651
|
const name = factory(node.callee);
|
|
1463
1652
|
if (name === null || !["object", "strictObject", "looseObject"].includes(name) || node.arguments.length !== 1) return;
|
|
1464
1653
|
const shape = node.arguments[0];
|
|
1465
|
-
if (shape?.type !==
|
|
1654
|
+
if (shape?.type !== AST_NODE_TYPES15.ObjectExpression) return;
|
|
1466
1655
|
for (const property of shape.properties) {
|
|
1467
|
-
if (property.type !==
|
|
1468
|
-
const field =
|
|
1656
|
+
if (property.type !== AST_NODE_TYPES15.Property || property.computed || property.kind !== "init" || property.method) continue;
|
|
1657
|
+
const field = ASTUtils13.getPropertyName(property);
|
|
1469
1658
|
const minimum = field === null ? void 0 : FIELD_MINIMUMS.get(field);
|
|
1470
1659
|
if (minimum === void 0 || field === null || constrained(property.value, minimum) !== false) continue;
|
|
1471
1660
|
context.report({ node: property, messageId: "constrainInteger", data: { field, minimum } });
|
|
@@ -1476,7 +1665,7 @@ var require_constrained_schema_integer_default = createRule({
|
|
|
1476
1665
|
});
|
|
1477
1666
|
|
|
1478
1667
|
// src/rules/no-generic-json-parser.ts
|
|
1479
|
-
import { AST_NODE_TYPES as
|
|
1668
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES16, ASTUtils as ASTUtils14 } from "@typescript-eslint/utils";
|
|
1480
1669
|
var OPEN_FACTORIES = /* @__PURE__ */ new Set(["any", "unknown", "json", "record", "partialRecord"]);
|
|
1481
1670
|
var WRAPPERS = /* @__PURE__ */ new Set(["optional", "nullable", "nullish", "default", "catch", "readonly", "brand", "describe", "meta"]);
|
|
1482
1671
|
var NO_GENERIC_JSON_PARSER_DOCUMENTATION = {
|
|
@@ -1509,60 +1698,60 @@ var no_generic_json_parser_default = createRule({
|
|
|
1509
1698
|
if (isGeneratedFile(context, context.sourceCode.text)) return {};
|
|
1510
1699
|
const sourceCode = context.sourceCode;
|
|
1511
1700
|
function binding3(node) {
|
|
1512
|
-
return
|
|
1701
|
+
return ASTUtils14.findVariable(sourceCode.getScope(node), node.name);
|
|
1513
1702
|
}
|
|
1514
1703
|
function initializer(node) {
|
|
1515
1704
|
const variable = binding3(node);
|
|
1516
1705
|
const definition = variable?.defs[0];
|
|
1517
|
-
if (variable?.defs.length !== 1 || definition?.node.type !==
|
|
1706
|
+
if (variable?.defs.length !== 1 || definition?.node.type !== AST_NODE_TYPES16.VariableDeclarator || definition.node.parent.kind !== "const" || definition.node.init === null || definition.node.range[1] >= node.range[0] || variable.references.some((reference) => reference.isWrite() && !reference.init)) return null;
|
|
1518
1707
|
return definition.node.init;
|
|
1519
1708
|
}
|
|
1520
1709
|
function parser(node, seen = /* @__PURE__ */ new Set(), awaited = false) {
|
|
1521
1710
|
node = unwrapExpression(node);
|
|
1522
1711
|
if (seen.has(node)) return null;
|
|
1523
1712
|
seen.add(node);
|
|
1524
|
-
if (node.type ===
|
|
1525
|
-
if (node.type ===
|
|
1713
|
+
if (node.type === AST_NODE_TYPES16.AwaitExpression) return parser(node.argument, seen, true);
|
|
1714
|
+
if (node.type === AST_NODE_TYPES16.Identifier) {
|
|
1526
1715
|
const value = initializer(node);
|
|
1527
1716
|
return value === null ? null : parser(value, seen, awaited);
|
|
1528
1717
|
}
|
|
1529
|
-
if (node.type !==
|
|
1530
|
-
if (
|
|
1718
|
+
if (node.type !== AST_NODE_TYPES16.CallExpression || node.callee.type !== AST_NODE_TYPES16.MemberExpression || !["parse", "parseAsync"].includes(ASTUtils14.getPropertyName(node.callee) ?? "")) return null;
|
|
1719
|
+
if (ASTUtils14.getPropertyName(node.callee) === "parseAsync" && !awaited) return null;
|
|
1531
1720
|
return openSchema(node.callee.object) ? node : null;
|
|
1532
1721
|
}
|
|
1533
1722
|
function openSchema(node, seen = /* @__PURE__ */ new Set()) {
|
|
1534
1723
|
node = unwrapExpression(node);
|
|
1535
1724
|
if (seen.has(node)) return false;
|
|
1536
1725
|
seen.add(node);
|
|
1537
|
-
if (node.type ===
|
|
1726
|
+
if (node.type === AST_NODE_TYPES16.Identifier) {
|
|
1538
1727
|
const value = initializer(node);
|
|
1539
1728
|
return value !== null && openSchema(value, seen);
|
|
1540
1729
|
}
|
|
1541
|
-
if (node.type !==
|
|
1730
|
+
if (node.type !== AST_NODE_TYPES16.CallExpression) return false;
|
|
1542
1731
|
const name = factory(node.callee);
|
|
1543
1732
|
if (name !== null) return OPEN_FACTORIES.has(name);
|
|
1544
1733
|
const callee = unwrapExpression(node.callee);
|
|
1545
|
-
return callee.type ===
|
|
1734
|
+
return callee.type === AST_NODE_TYPES16.MemberExpression && WRAPPERS.has(ASTUtils14.getPropertyName(callee) ?? "") && openSchema(callee.object, seen);
|
|
1546
1735
|
}
|
|
1547
1736
|
function factory(node) {
|
|
1548
1737
|
node = unwrapExpression(node);
|
|
1549
|
-
if (node.type ===
|
|
1738
|
+
if (node.type === AST_NODE_TYPES16.Identifier) {
|
|
1550
1739
|
const definition2 = binding3(node)?.defs[0]?.node;
|
|
1551
|
-
if (definition2?.type !==
|
|
1552
|
-
return definition2.imported.type ===
|
|
1740
|
+
if (definition2?.type !== AST_NODE_TYPES16.ImportSpecifier || definition2.parent.type !== AST_NODE_TYPES16.ImportDeclaration || definition2.importKind === "type" || definition2.parent.importKind === "type" || !isZodModule(definition2.parent.source.value)) return null;
|
|
1741
|
+
return definition2.imported.type === AST_NODE_TYPES16.Identifier ? definition2.imported.name : definition2.imported.value;
|
|
1553
1742
|
}
|
|
1554
|
-
if (node.type !==
|
|
1743
|
+
if (node.type !== AST_NODE_TYPES16.MemberExpression) return null;
|
|
1555
1744
|
const receiver = unwrapExpression(node.object);
|
|
1556
|
-
if (receiver.type !==
|
|
1745
|
+
if (receiver.type !== AST_NODE_TYPES16.Identifier) return null;
|
|
1557
1746
|
const definition = binding3(receiver)?.defs[0]?.node;
|
|
1558
|
-
if (definition === void 0 || definition.type !==
|
|
1559
|
-
if (definition.type ===
|
|
1560
|
-
return
|
|
1747
|
+
if (definition === void 0 || definition.type !== AST_NODE_TYPES16.ImportSpecifier && definition.type !== AST_NODE_TYPES16.ImportNamespaceSpecifier || definition.parent.type !== AST_NODE_TYPES16.ImportDeclaration || definition.parent.importKind === "type" || !isZodModule(definition.parent.source.value)) return null;
|
|
1748
|
+
if (definition.type === AST_NODE_TYPES16.ImportSpecifier && (definition.importKind === "type" || (definition.imported.type === AST_NODE_TYPES16.Identifier ? definition.imported.name : definition.imported.value) !== "z")) return null;
|
|
1749
|
+
return ASTUtils14.getPropertyName(node);
|
|
1561
1750
|
}
|
|
1562
1751
|
const reported = /* @__PURE__ */ new Set();
|
|
1563
1752
|
return {
|
|
1564
1753
|
MemberExpression(node) {
|
|
1565
|
-
const field =
|
|
1754
|
+
const field = ASTUtils14.getPropertyName(node);
|
|
1566
1755
|
if (field === null) return;
|
|
1567
1756
|
const call = parser(node.object);
|
|
1568
1757
|
if (call === null || reported.has(call)) return;
|
|
@@ -1574,7 +1763,7 @@ var no_generic_json_parser_default = createRule({
|
|
|
1574
1763
|
});
|
|
1575
1764
|
|
|
1576
1765
|
// src/rules/no-redundant-local-alias.ts
|
|
1577
|
-
import { AST_NODE_TYPES as
|
|
1766
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES17, ASTUtils as ASTUtils15 } from "@typescript-eslint/utils";
|
|
1578
1767
|
var NO_REDUNDANT_LOCAL_ALIAS_DOCUMENTATION = {
|
|
1579
1768
|
defaultLevel: "warning",
|
|
1580
1769
|
summary: "Pass the original local into an object field instead of creating a single-use rename.",
|
|
@@ -1593,7 +1782,7 @@ var NO_REDUNDANT_LOCAL_ALIAS_DOCUMENTATION = {
|
|
|
1593
1782
|
function stableSource(variable, alias) {
|
|
1594
1783
|
const definition = variable.defs[0];
|
|
1595
1784
|
if (variable.defs.length !== 1 || definition === void 0 || variable.references.some((reference) => reference.isWrite() && !reference.init)) return false;
|
|
1596
|
-
return definition.type === "Parameter" || definition.node.type ===
|
|
1785
|
+
return definition.type === "Parameter" || definition.node.type === AST_NODE_TYPES17.VariableDeclarator && definition.node.parent.kind === "const" && definition.node.init !== null && definition.node.range[1] < alias.range[0];
|
|
1597
1786
|
}
|
|
1598
1787
|
var no_redundant_local_alias_default = createRule({
|
|
1599
1788
|
name: "no-redundant-local-alias",
|
|
@@ -1609,18 +1798,18 @@ var no_redundant_local_alias_default = createRule({
|
|
|
1609
1798
|
if (isGeneratedFile(context, context.sourceCode.text)) return {};
|
|
1610
1799
|
return {
|
|
1611
1800
|
VariableDeclarator(node) {
|
|
1612
|
-
if (node.parent.kind !== "const" || node.parent.declarations.length !== 1 || node.id.type !==
|
|
1801
|
+
if (node.parent.kind !== "const" || node.parent.declarations.length !== 1 || node.id.type !== AST_NODE_TYPES17.Identifier || node.id.typeAnnotation !== void 0 || node.init?.type !== AST_NODE_TYPES17.Identifier) return;
|
|
1613
1802
|
const scope = context.sourceCode.getScope(node);
|
|
1614
1803
|
if (scope.variableScope.type !== "function") return;
|
|
1615
|
-
const target =
|
|
1616
|
-
const source =
|
|
1804
|
+
const target = ASTUtils15.findVariable(scope, node.id.name);
|
|
1805
|
+
const source = ASTUtils15.findVariable(scope, node.init.name);
|
|
1617
1806
|
if (target === null || source === null || !stableSource(source, node)) return;
|
|
1618
1807
|
const reads = target.references.filter((reference) => reference.isRead());
|
|
1619
1808
|
if (reads.length !== 1 || target.references.some((reference) => reference.isWrite() && !reference.init)) return;
|
|
1620
1809
|
const read = reads[0];
|
|
1621
1810
|
if (read === void 0 || read.from.variableScope !== scope.variableScope) return;
|
|
1622
1811
|
const property = read.identifier.parent;
|
|
1623
|
-
if (property.type !==
|
|
1812
|
+
if (property.type !== AST_NODE_TYPES17.Property || !property.shorthand || property.value !== read.identifier || property.parent.type !== AST_NODE_TYPES17.ObjectExpression || property.computed || property.method || property.kind !== "init") return;
|
|
1624
1813
|
context.report({ node, messageId: "redundantAlias", data: { source: node.init.name, target: node.id.name } });
|
|
1625
1814
|
}
|
|
1626
1815
|
};
|
|
@@ -1628,10 +1817,10 @@ var no_redundant_local_alias_default = createRule({
|
|
|
1628
1817
|
});
|
|
1629
1818
|
|
|
1630
1819
|
// src/rules/no-test-comments.ts
|
|
1631
|
-
import { AST_NODE_TYPES as
|
|
1820
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES19 } from "@typescript-eslint/utils";
|
|
1632
1821
|
|
|
1633
1822
|
// src/rules/_comments.ts
|
|
1634
|
-
import { AST_NODE_TYPES as
|
|
1823
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES18 } from "@typescript-eslint/utils";
|
|
1635
1824
|
var REF_RE = /https?:\/\/|\bRFC[- ]?\d+|\bPEP[- ]?\d+|\bCVE-\d{4}|\b(?!UTF-|SHA-|ISO-|AES-|CRC-|MD-|PCM-|EOF-|API-|BASE-)[A-Z][A-Z0-9]{1,9}-\d[A-Z0-9]{0,5}\b|(?<![&\w])#\d{2,6}\b|@[a-z][\w.-]*\.(?:us|com|ai|io|net|org|dev)\b/;
|
|
1636
1825
|
var VERSION_RE = /(?:>=|<=|==|<|>)\s*v?\d+\.\d+|\bv\d+\.\d+|\b(?:since|until|as of)\s+(?:v?\d+\.\d+|Python\s*\d)/i;
|
|
1637
1826
|
var UNITS_RE = /[~<>]?\d+(?:\.\d+)?\s?(?:ms|s\b|sec\b|seconds?\b|min\b|minutes?\b|hours?\b|days?\b|KB|MB|MiB|GiB|kHz|Hz|bytes?\b|bit\b|-bit\b|%|px\b|rps\b|qps\b)|\b[1-5]xx\b|\b(?:301|302|304|307|308|400|401|403|404|405|409|410|412|422|425|429|500|501|502|503|504)\b/;
|
|
@@ -1717,10 +1906,10 @@ var NARRATION_MAX_WORDS = 6;
|
|
|
1717
1906
|
var NARRATION_MIN_CONTENT = 1;
|
|
1718
1907
|
var TOKEN_PLURAL_MIN = 4;
|
|
1719
1908
|
var RESTATABLE_STATEMENTS = /* @__PURE__ */ new Set([
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1909
|
+
AST_NODE_TYPES18.ExpressionStatement,
|
|
1910
|
+
AST_NODE_TYPES18.ReturnStatement,
|
|
1911
|
+
AST_NODE_TYPES18.ThrowStatement,
|
|
1912
|
+
AST_NODE_TYPES18.VariableDeclaration
|
|
1724
1913
|
]);
|
|
1725
1914
|
var NARRATION_VERB_RE = /^(?:add|append|assign|build|calculate|call|check|clear|close|compute|convert|copy|count|create|declare|decrement|define|delete|extract|fetch|filter|find|format|generate|get|handle|increment|init|initialise|initialize|insert|iterate|join|load|log|loop|make|map|merge|open|parse|print|process|push|read|remove|render|reset|return|save|send|set|setup|sort|split|start|stop|store|update|validate|wrap|write)(?:s|es|d|ed|ing)?$/i;
|
|
1726
1915
|
var NARRATION_STOPWORDS = /* @__PURE__ */ new Set([
|
|
@@ -1779,12 +1968,12 @@ function restatableStatementBelow(comment, sourceCode) {
|
|
|
1779
1968
|
function restatableStatementNodeBelow(comment, sourceCode) {
|
|
1780
1969
|
const token = sourceCode.getTokenAfter(comment, { includeComments: false });
|
|
1781
1970
|
if (token === null || token.loc.start.line !== comment.loc.end.line + 1) return null;
|
|
1782
|
-
for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !==
|
|
1971
|
+
for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !== AST_NODE_TYPES18.Program; node = node.parent) {
|
|
1783
1972
|
if (!RESTATABLE_STATEMENTS.has(node.type)) continue;
|
|
1784
1973
|
if (node.loc.start.line !== token.loc.start.line || node.loc.end.line !== node.loc.start.line) {
|
|
1785
1974
|
return null;
|
|
1786
1975
|
}
|
|
1787
|
-
if (node.type ===
|
|
1976
|
+
if (node.type === AST_NODE_TYPES18.VariableDeclaration && isTrivialInitializer(node)) {
|
|
1788
1977
|
return null;
|
|
1789
1978
|
}
|
|
1790
1979
|
return node;
|
|
@@ -1794,8 +1983,8 @@ function restatableStatementNodeBelow(comment, sourceCode) {
|
|
|
1794
1983
|
function isTrivialInitializer(node) {
|
|
1795
1984
|
return node.declarations.every((declarator) => {
|
|
1796
1985
|
const init = declarator.init;
|
|
1797
|
-
if (init == null || init.type ===
|
|
1798
|
-
return init.type ===
|
|
1986
|
+
if (init == null || init.type === AST_NODE_TYPES18.Literal) return true;
|
|
1987
|
+
return init.type === AST_NODE_TYPES18.ArrayExpression && init.elements.length === 0 || init.type === AST_NODE_TYPES18.ObjectExpression && init.properties.length === 0;
|
|
1799
1988
|
});
|
|
1800
1989
|
}
|
|
1801
1990
|
function restatesStatementHead(body3, statement) {
|
|
@@ -1949,7 +2138,7 @@ var no_test_comments_default = createRule({
|
|
|
1949
2138
|
if (!isTestFile(context) || isGeneratedFile(context, context.sourceCode.text)) return {};
|
|
1950
2139
|
const filename = scopedFilename(context);
|
|
1951
2140
|
const unambiguous = /(?:^|\/)(?:tests?|__tests__|fixtures|__fixtures__|__mocks__)\//u.test(filename) || /\.(?:test|spec|e2e|integration)\.[cm]?[jt]sx?$/u.test(filename);
|
|
1952
|
-
const framework = context.sourceCode.ast.body.some((statement) => statement.type ===
|
|
2141
|
+
const framework = context.sourceCode.ast.body.some((statement) => statement.type === AST_NODE_TYPES19.ImportDeclaration && statement.importKind !== "type" && (statement.specifiers.length === 0 || statement.specifiers.some((specifier) => specifier.type !== AST_NODE_TYPES19.ImportSpecifier || specifier.importKind !== "type")) && ["vitest", "@jest/globals", "@playwright/test", "bun:test", "node:test"].includes(statement.source.value));
|
|
1953
2142
|
if (!unambiguous && !framework) return {};
|
|
1954
2143
|
return {
|
|
1955
2144
|
Program() {
|
|
@@ -1999,14 +2188,14 @@ var no_test_comments_default = createRule({
|
|
|
1999
2188
|
});
|
|
2000
2189
|
|
|
2001
2190
|
// src/rules/no-mutating-container-transform.ts
|
|
2002
|
-
import { AST_NODE_TYPES as
|
|
2191
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES20, ASTUtils as ASTUtils16 } from "@typescript-eslint/utils";
|
|
2003
2192
|
var MUTATORS = /* @__PURE__ */ new Set(["copyWithin", "fill", "pop", "push", "reverse", "shift", "sort", "splice", "unshift"]);
|
|
2004
2193
|
var PRIMITIVES = /* @__PURE__ */ new Set([
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2194
|
+
AST_NODE_TYPES20.TSStringKeyword,
|
|
2195
|
+
AST_NODE_TYPES20.TSNumberKeyword,
|
|
2196
|
+
AST_NODE_TYPES20.TSBooleanKeyword,
|
|
2197
|
+
AST_NODE_TYPES20.TSBigIntKeyword,
|
|
2198
|
+
AST_NODE_TYPES20.TSSymbolKeyword
|
|
2010
2199
|
]);
|
|
2011
2200
|
var NO_MUTATING_CONTAINER_TRANSFORM_DOCUMENTATION = {
|
|
2012
2201
|
defaultLevel: "warning",
|
|
@@ -2025,27 +2214,27 @@ var NO_MUTATING_CONTAINER_TRANSFORM_DOCUMENTATION = {
|
|
|
2025
2214
|
]
|
|
2026
2215
|
};
|
|
2027
2216
|
function arrayElement(node, sourceCode) {
|
|
2028
|
-
if (node.type ===
|
|
2029
|
-
if (node.type ===
|
|
2217
|
+
if (node.type === AST_NODE_TYPES20.TSArrayType) return node.elementType;
|
|
2218
|
+
if (node.type === AST_NODE_TYPES20.TSTypeReference && node.typeName.type === AST_NODE_TYPES20.Identifier && (node.typeName.name === "Array" || node.typeName.name === "ReadonlyArray") && (ASTUtils16.findVariable(sourceCode.getScope(node.typeName), node.typeName.name)?.defs.length ?? 0) === 0 && node.typeArguments?.params.length === 1) return node.typeArguments.params[0] ?? null;
|
|
2030
2219
|
return null;
|
|
2031
2220
|
}
|
|
2032
2221
|
function returnsArray(node, sourceCode) {
|
|
2033
2222
|
let annotation = node.returnType?.typeAnnotation;
|
|
2034
|
-
if (annotation?.type ===
|
|
2223
|
+
if (annotation?.type === AST_NODE_TYPES20.TSTypeReference && annotation.typeName.type === AST_NODE_TYPES20.Identifier && annotation.typeName.name === "Promise" && (ASTUtils16.findVariable(sourceCode.getScope(annotation.typeName), "Promise")?.defs.length ?? 0) === 0 && annotation.typeArguments?.params.length === 1) annotation = annotation.typeArguments.params[0];
|
|
2035
2224
|
return annotation !== void 0 && arrayElement(annotation, sourceCode) !== null;
|
|
2036
2225
|
}
|
|
2037
2226
|
function supported(statements) {
|
|
2038
2227
|
return statements.every((statement) => {
|
|
2039
2228
|
switch (statement.type) {
|
|
2040
|
-
case
|
|
2041
|
-
case
|
|
2042
|
-
case
|
|
2043
|
-
case
|
|
2044
|
-
case
|
|
2229
|
+
case AST_NODE_TYPES20.ExpressionStatement:
|
|
2230
|
+
case AST_NODE_TYPES20.VariableDeclaration:
|
|
2231
|
+
case AST_NODE_TYPES20.ReturnStatement:
|
|
2232
|
+
case AST_NODE_TYPES20.ThrowStatement:
|
|
2233
|
+
case AST_NODE_TYPES20.EmptyStatement:
|
|
2045
2234
|
return true;
|
|
2046
|
-
case
|
|
2235
|
+
case AST_NODE_TYPES20.BlockStatement:
|
|
2047
2236
|
return supported(statement.body);
|
|
2048
|
-
case
|
|
2237
|
+
case AST_NODE_TYPES20.IfStatement:
|
|
2049
2238
|
return supported([statement.consequent]) && (statement.alternate === null || supported([statement.alternate]));
|
|
2050
2239
|
default:
|
|
2051
2240
|
return false;
|
|
@@ -2066,13 +2255,13 @@ var no_mutating_container_transform_default = createRule({
|
|
|
2066
2255
|
if (isGeneratedFile(context, context.sourceCode.text)) return {};
|
|
2067
2256
|
const sourceCode = context.sourceCode;
|
|
2068
2257
|
function binding3(node) {
|
|
2069
|
-
return node.type ===
|
|
2258
|
+
return node.type === AST_NODE_TYPES20.Identifier ? ASTUtils16.findVariable(sourceCode.getScope(node), node.name) : null;
|
|
2070
2259
|
}
|
|
2071
2260
|
function inspect(node) {
|
|
2072
|
-
if (node.body?.type !==
|
|
2261
|
+
if (node.body?.type !== AST_NODE_TYPES20.BlockStatement || !returnsArray(node, sourceCode) || !supported(node.body.body)) return;
|
|
2073
2262
|
const initial = /* @__PURE__ */ new Map();
|
|
2074
2263
|
for (const parameter of node.params) {
|
|
2075
|
-
if (parameter.type !==
|
|
2264
|
+
if (parameter.type !== AST_NODE_TYPES20.Identifier || parameter.typeAnnotation === void 0) continue;
|
|
2076
2265
|
const element = arrayElement(parameter.typeAnnotation.typeAnnotation, sourceCode);
|
|
2077
2266
|
const variable = binding3(parameter);
|
|
2078
2267
|
if (element !== null && PRIMITIVES.has(element.type) && variable !== null) initial.set(variable, parameter.name);
|
|
@@ -2085,26 +2274,26 @@ var no_mutating_container_transform_default = createRule({
|
|
|
2085
2274
|
}
|
|
2086
2275
|
function expression(current, state) {
|
|
2087
2276
|
switch (current.type) {
|
|
2088
|
-
case
|
|
2089
|
-
case
|
|
2090
|
-
case
|
|
2277
|
+
case AST_NODE_TYPES20.FunctionExpression:
|
|
2278
|
+
case AST_NODE_TYPES20.ArrowFunctionExpression:
|
|
2279
|
+
case AST_NODE_TYPES20.ClassExpression:
|
|
2091
2280
|
return;
|
|
2092
|
-
case
|
|
2281
|
+
case AST_NODE_TYPES20.AssignmentExpression:
|
|
2093
2282
|
assignment(current, state);
|
|
2094
2283
|
return;
|
|
2095
|
-
case
|
|
2284
|
+
case AST_NODE_TYPES20.LogicalExpression:
|
|
2096
2285
|
logical(current, state);
|
|
2097
2286
|
return;
|
|
2098
|
-
case
|
|
2287
|
+
case AST_NODE_TYPES20.ConditionalExpression:
|
|
2099
2288
|
conditional(current, state);
|
|
2100
2289
|
return;
|
|
2101
|
-
case
|
|
2290
|
+
case AST_NODE_TYPES20.UpdateExpression:
|
|
2102
2291
|
write(current.argument, state);
|
|
2103
2292
|
break;
|
|
2104
|
-
case
|
|
2293
|
+
case AST_NODE_TYPES20.UnaryExpression:
|
|
2105
2294
|
if (current.operator === "delete") write(current.argument, state);
|
|
2106
2295
|
break;
|
|
2107
|
-
case
|
|
2296
|
+
case AST_NODE_TYPES20.CallExpression:
|
|
2108
2297
|
mutationCall(current, state);
|
|
2109
2298
|
break;
|
|
2110
2299
|
default:
|
|
@@ -2124,13 +2313,13 @@ var no_mutating_container_transform_default = createRule({
|
|
|
2124
2313
|
function logical(current, state) {
|
|
2125
2314
|
expression(current.left, state);
|
|
2126
2315
|
const left = unwrapExpression(current.left);
|
|
2127
|
-
if (left.type ===
|
|
2316
|
+
if (left.type === AST_NODE_TYPES20.Literal && (current.operator === "&&" && !left.value || current.operator === "||" && !!left.value || current.operator === "??" && left.value !== null)) return;
|
|
2128
2317
|
expression(current.right, state);
|
|
2129
2318
|
}
|
|
2130
2319
|
function conditional(current, state) {
|
|
2131
2320
|
expression(current.test, state);
|
|
2132
2321
|
const test = unwrapExpression(current.test);
|
|
2133
|
-
if (test.type ===
|
|
2322
|
+
if (test.type === AST_NODE_TYPES20.Literal) {
|
|
2134
2323
|
expression(test.value ? current.consequent : current.alternate, state);
|
|
2135
2324
|
return;
|
|
2136
2325
|
}
|
|
@@ -2138,13 +2327,13 @@ var no_mutating_container_transform_default = createRule({
|
|
|
2138
2327
|
expression(current.alternate, state);
|
|
2139
2328
|
}
|
|
2140
2329
|
function mutationCall(current, state) {
|
|
2141
|
-
if (current.callee.type !==
|
|
2330
|
+
if (current.callee.type !== AST_NODE_TYPES20.MemberExpression || !MUTATORS.has(ASTUtils16.getPropertyName(current.callee) ?? "")) return;
|
|
2142
2331
|
const parameter = origin(current.callee.object, state);
|
|
2143
2332
|
if (parameter !== void 0 && first === null) first = { node: current, parameter };
|
|
2144
2333
|
}
|
|
2145
2334
|
function write(target, state) {
|
|
2146
2335
|
target = unwrapExpression(target);
|
|
2147
|
-
if (target.type !==
|
|
2336
|
+
if (target.type !== AST_NODE_TYPES20.MemberExpression || !target.computed && ASTUtils16.getPropertyName(target) !== "length") return;
|
|
2148
2337
|
const parameter = origin(target.object, state);
|
|
2149
2338
|
if (parameter !== void 0 && first === null) first = { node: target, parameter };
|
|
2150
2339
|
}
|
|
@@ -2154,18 +2343,18 @@ var no_mutating_container_transform_default = createRule({
|
|
|
2154
2343
|
}
|
|
2155
2344
|
function statement(current, state) {
|
|
2156
2345
|
switch (current.type) {
|
|
2157
|
-
case
|
|
2346
|
+
case AST_NODE_TYPES20.BlockStatement:
|
|
2158
2347
|
return statements(current.body, state);
|
|
2159
|
-
case
|
|
2348
|
+
case AST_NODE_TYPES20.IfStatement:
|
|
2160
2349
|
return branch(current, state);
|
|
2161
|
-
case
|
|
2350
|
+
case AST_NODE_TYPES20.VariableDeclaration:
|
|
2162
2351
|
declarations(current, state);
|
|
2163
2352
|
return false;
|
|
2164
|
-
case
|
|
2165
|
-
case
|
|
2353
|
+
case AST_NODE_TYPES20.ReturnStatement:
|
|
2354
|
+
case AST_NODE_TYPES20.ThrowStatement:
|
|
2166
2355
|
if (current.argument !== null) expression(current.argument, state);
|
|
2167
2356
|
return true;
|
|
2168
|
-
case
|
|
2357
|
+
case AST_NODE_TYPES20.ExpressionStatement:
|
|
2169
2358
|
expression(current.expression, state);
|
|
2170
2359
|
return false;
|
|
2171
2360
|
default:
|
|
@@ -2174,7 +2363,7 @@ var no_mutating_container_transform_default = createRule({
|
|
|
2174
2363
|
}
|
|
2175
2364
|
function branch(current, state) {
|
|
2176
2365
|
expression(current.test, state);
|
|
2177
|
-
if (current.test.type ===
|
|
2366
|
+
if (current.test.type === AST_NODE_TYPES20.Literal) return current.test.value ? statements([current.consequent], state) : current.alternate !== null && statements([current.alternate], state);
|
|
2178
2367
|
const left = new Map(state);
|
|
2179
2368
|
const right = new Map(state);
|
|
2180
2369
|
const leftEnds = statements([current.consequent], left);
|
|
@@ -2206,7 +2395,7 @@ var no_mutating_container_transform_default = createRule({
|
|
|
2206
2395
|
});
|
|
2207
2396
|
|
|
2208
2397
|
// src/rules/no-redundant-consumer-union.ts
|
|
2209
|
-
import { AST_NODE_TYPES as
|
|
2398
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES24, ESLintUtils as ESLintUtils2 } from "@typescript-eslint/utils";
|
|
2210
2399
|
import ts7 from "typescript";
|
|
2211
2400
|
|
|
2212
2401
|
// src/rules/_checked-native-source.ts
|
|
@@ -2317,11 +2506,11 @@ function finiteMember(member3, checker) {
|
|
|
2317
2506
|
}
|
|
2318
2507
|
|
|
2319
2508
|
// src/rules/_private-consumer-fix.ts
|
|
2320
|
-
import { AST_NODE_TYPES as
|
|
2509
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES22 } from "@typescript-eslint/utils";
|
|
2321
2510
|
import ts3 from "typescript";
|
|
2322
2511
|
|
|
2323
2512
|
// src/rules/_type-binding.ts
|
|
2324
|
-
import { AST_NODE_TYPES as
|
|
2513
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES21 } from "@typescript-eslint/utils";
|
|
2325
2514
|
function typeBinding(source, identifier) {
|
|
2326
2515
|
let scope = source.getScope(identifier);
|
|
2327
2516
|
while (scope !== null) {
|
|
@@ -2347,12 +2536,12 @@ function retainsNamedTypeUses(source, removed) {
|
|
|
2347
2536
|
function publicTypeUse(identifier) {
|
|
2348
2537
|
let node = identifier;
|
|
2349
2538
|
while (node.parent) {
|
|
2350
|
-
if (node.type ===
|
|
2351
|
-
if (node.type ===
|
|
2352
|
-
return node.parent.type ===
|
|
2539
|
+
if (node.type === AST_NODE_TYPES21.TSTypeAnnotation || node.type === AST_NODE_TYPES21.TSTypePredicate || node.type === AST_NODE_TYPES21.TSAsExpression || node.type === AST_NODE_TYPES21.TSTypeAssertion) return false;
|
|
2540
|
+
if (node.type === AST_NODE_TYPES21.TSTypeAliasDeclaration) {
|
|
2541
|
+
return node.parent.type === AST_NODE_TYPES21.ExportNamedDeclaration && node.parent.declaration === node && node.parent.parent.type === AST_NODE_TYPES21.Program;
|
|
2353
2542
|
}
|
|
2354
|
-
if (node.type ===
|
|
2355
|
-
return node.parent.type ===
|
|
2543
|
+
if (node.type === AST_NODE_TYPES21.ExportSpecifier) {
|
|
2544
|
+
return node.parent.type === AST_NODE_TYPES21.ExportNamedDeclaration && node.parent.source === null && node.parent.parent.type === AST_NODE_TYPES21.Program;
|
|
2356
2545
|
}
|
|
2357
2546
|
node = node.parent;
|
|
2358
2547
|
}
|
|
@@ -2366,8 +2555,8 @@ function insideTypeRange(node, range) {
|
|
|
2366
2555
|
var UNSAFE = ts3.TypeFlags.Any | ts3.TypeFlags.Unknown | ts3.TypeFlags.Never | ts3.TypeFlags.TypeParameter | ts3.TypeFlags.Conditional | ts3.TypeFlags.IndexedAccess | ts3.TypeFlags.Substitution;
|
|
2367
2556
|
function validConsumerFixCalls(node, parameter, sourceCode, services) {
|
|
2368
2557
|
if (sourceCode.getAllComments().some((comment) => /@ts-(?:expect-error|ignore|nocheck)\b/u.test(comment.value))) return false;
|
|
2369
|
-
const owner = node.type ===
|
|
2370
|
-
if (owner.type !==
|
|
2558
|
+
const owner = node.type === AST_NODE_TYPES22.FunctionDeclaration ? node : node.parent;
|
|
2559
|
+
if (owner.type !== AST_NODE_TYPES22.FunctionDeclaration && owner.type !== AST_NODE_TYPES22.VariableDeclarator) return false;
|
|
2371
2560
|
const binding3 = sourceCode.getDeclaredVariables(owner).find((variable) => variable.defs.some((definition) => definition.node === owner && (definition.type === "FunctionName" || definition.type === "Variable")));
|
|
2372
2561
|
if (!binding3) return false;
|
|
2373
2562
|
const checker = services.program.getTypeChecker();
|
|
@@ -2385,7 +2574,7 @@ function validConsumerFixCalls(node, parameter, sourceCode, services) {
|
|
|
2385
2574
|
continue;
|
|
2386
2575
|
}
|
|
2387
2576
|
const call = reference.identifier.parent;
|
|
2388
|
-
if (reference.isTypeReference || !reference.isReadOnly() || call.type !==
|
|
2577
|
+
if (reference.isTypeReference || !reference.isReadOnly() || call.type !== AST_NODE_TYPES22.CallExpression || call.callee !== reference.identifier || call.optional || call.typeArguments || call.arguments.length !== 1 || call.arguments[0]?.type !== AST_NODE_TYPES22.Identifier) return false;
|
|
2389
2578
|
const argument = services.esTreeNodeToTSNodeMap.get(call.arguments[0]);
|
|
2390
2579
|
const type = checker.getTypeAtLocation(argument);
|
|
2391
2580
|
if (!knownArgument(type, argument, fields2, checker) || !checker.isTypeAssignableTo(type, original)) return false;
|
|
@@ -2440,7 +2629,7 @@ function minimalConsumerFix(sourceCode, annotation, removed) {
|
|
|
2440
2629
|
}
|
|
2441
2630
|
|
|
2442
2631
|
// src/rules/_private-scalar-consumer.ts
|
|
2443
|
-
import { AST_NODE_TYPES as
|
|
2632
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES23 } from "@typescript-eslint/utils";
|
|
2444
2633
|
import ts6 from "typescript";
|
|
2445
2634
|
|
|
2446
2635
|
// src/rules/_scalar-parameter-view.ts
|
|
@@ -2586,31 +2775,11 @@ function intrinsicAttribute(attribute, view) {
|
|
|
2586
2775
|
return ts5.isJsxAttribute(attribute) && ts5.isIdentifier(attribute.name) && attribute.name.text !== "is" && (!attribute.initializer || scalarView(attribute.initializer, view));
|
|
2587
2776
|
}
|
|
2588
2777
|
|
|
2589
|
-
// src/rules/_stable-value-binding.ts
|
|
2590
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES20 } from "@typescript-eslint/utils";
|
|
2591
|
-
function typeOnlyReference(reference) {
|
|
2592
|
-
if (reference.isTypeReference && !reference.isValueReference) return true;
|
|
2593
|
-
let current = outerExpression(reference.identifier);
|
|
2594
|
-
while (current.parent?.type === AST_NODE_TYPES20.TSQualifiedName && current.parent.left === current) {
|
|
2595
|
-
current = current.parent;
|
|
2596
|
-
}
|
|
2597
|
-
return current.parent?.type === AST_NODE_TYPES20.TSTypeQuery && current.parent.exprName === current;
|
|
2598
|
-
}
|
|
2599
|
-
function stableValueBinding(variable, acceptRead) {
|
|
2600
|
-
let initializer;
|
|
2601
|
-
return variable.references.every((reference) => {
|
|
2602
|
-
if (!reference.isWrite()) return acceptRead?.(reference) ?? true;
|
|
2603
|
-
if (reference.init !== true || initializer !== void 0 && initializer !== reference.identifier) return false;
|
|
2604
|
-
initializer = reference.identifier;
|
|
2605
|
-
return true;
|
|
2606
|
-
});
|
|
2607
|
-
}
|
|
2608
|
-
|
|
2609
2778
|
// src/rules/_private-scalar-consumer.ts
|
|
2610
2779
|
function directEval(node) {
|
|
2611
2780
|
let callee = unwrapExpression(node.callee);
|
|
2612
|
-
while (callee.type ===
|
|
2613
|
-
return callee.type ===
|
|
2781
|
+
while (callee.type === AST_NODE_TYPES23.TSInstantiationExpression) callee = unwrapExpression(callee.expression);
|
|
2782
|
+
return callee.type === AST_NODE_TYPES23.Identifier && callee.name === "eval";
|
|
2614
2783
|
}
|
|
2615
2784
|
function primitiveKeyword(node) {
|
|
2616
2785
|
return node !== void 0 && (node.kind === ts6.SyntaxKind.StringKeyword || node.kind === ts6.SyntaxKind.NumberKeyword || node.kind === ts6.SyntaxKind.BooleanKeyword || node.kind === ts6.SyntaxKind.BigIntKeyword);
|
|
@@ -2621,7 +2790,7 @@ function nullishPrimitiveUnion(node) {
|
|
|
2621
2790
|
function consumerAnnotation(node) {
|
|
2622
2791
|
if (node.params.length !== 1) return void 0;
|
|
2623
2792
|
const parameter = node.params[0];
|
|
2624
|
-
return parameter?.type ===
|
|
2793
|
+
return parameter?.type === AST_NODE_TYPES23.Identifier || parameter?.type === AST_NODE_TYPES23.ObjectPattern ? parameter.typeAnnotation?.typeAnnotation : void 0;
|
|
2625
2794
|
}
|
|
2626
2795
|
function exportedSymbols(source, checker) {
|
|
2627
2796
|
const symbol = checker.getSymbolAtLocation(source);
|
|
@@ -2652,12 +2821,12 @@ function independentSignature(native) {
|
|
|
2652
2821
|
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");
|
|
2653
2822
|
}
|
|
2654
2823
|
function callableBinding(node, sourceCode) {
|
|
2655
|
-
if (node.type ===
|
|
2656
|
-
if (node.parent.type !==
|
|
2824
|
+
if (node.type === AST_NODE_TYPES23.FunctionDeclaration) {
|
|
2825
|
+
if (node.parent.type !== AST_NODE_TYPES23.Program) return void 0;
|
|
2657
2826
|
return sourceCode.getDeclaredVariables(node).find((variable) => variable.defs.some((definition) => definition.type === "FunctionName" && definition.node === node));
|
|
2658
2827
|
}
|
|
2659
2828
|
const declaration = node.parent;
|
|
2660
|
-
if (declaration.type !==
|
|
2829
|
+
if (declaration.type !== AST_NODE_TYPES23.VariableDeclarator || declaration.init !== node || declaration.id.type !== AST_NODE_TYPES23.Identifier || declaration.id.typeAnnotation || declaration.parent.kind !== "const" || declaration.parent.parent.type !== AST_NODE_TYPES23.Program) return void 0;
|
|
2661
2830
|
return sourceCode.getDeclaredVariables(declaration).find((variable) => variable.defs.some((definition) => definition.type === "Variable" && definition.node === declaration));
|
|
2662
2831
|
}
|
|
2663
2832
|
function directCalls(binding3) {
|
|
@@ -2665,7 +2834,7 @@ function directCalls(binding3) {
|
|
|
2665
2834
|
const stable2 = stableValueBinding(binding3, (reference) => {
|
|
2666
2835
|
const identifier = reference.identifier;
|
|
2667
2836
|
const call = identifier.parent;
|
|
2668
|
-
if (reference.isTypeReference || !reference.isReadOnly() || call.type !==
|
|
2837
|
+
if (reference.isTypeReference || !reference.isReadOnly() || call.type !== AST_NODE_TYPES23.CallExpression || call.callee !== identifier || call.optional || call.typeArguments || call.arguments.length !== 1 || call.arguments[0]?.type !== AST_NODE_TYPES23.Identifier) return false;
|
|
2669
2838
|
calls += 1;
|
|
2670
2839
|
return true;
|
|
2671
2840
|
});
|
|
@@ -2676,6 +2845,7 @@ function directCalls(binding3) {
|
|
|
2676
2845
|
var CONFIG = { path: "tsconfig.json", source: '{"compilerOptions":{"strict":true,"target":"ESNext","module":"ESNext","moduleResolution":"Bundler"}}' };
|
|
2677
2846
|
var EXAMPLE = 'export {}; interface Animal {readonly name: string} interface Dog extends Animal {readonly breed: string} export type KeptDog = Dog; const dog: Dog = {name: "Ada", breed: "Collie"}; function label(value: Dog | Animal): string {return value.name;} label(dog);';
|
|
2678
2847
|
var NULLABLE_EXAMPLE = EXAMPLE.replace("readonly name: string", "readonly name: string | null").replace("return value.name;", "return value.name ?? '';");
|
|
2848
|
+
var OPTIONAL_EXAMPLE = EXAMPLE.replace("readonly breed: string", "readonly breed?: string");
|
|
2679
2849
|
var NO_REDUNDANT_CONSUMER_UNION_DOCUMENTATION = {
|
|
2680
2850
|
defaultLevel: "warning",
|
|
2681
2851
|
summary: "Keep the covering object contract in a private scalar consumer union.",
|
|
@@ -2687,12 +2857,14 @@ var NO_REDUNDANT_CONSUMER_UNION_DOCUMENTATION = {
|
|
|
2687
2857
|
"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. Removed named types/imports must retain an independent top-level exported type-alias or direct type-export read. Other removable annotations/assertions, the covering annotation and own-definition/self references cannot keep one another live; otherwise simultaneous fixes can introduce unused-type errors. The exact authored covering type and terminator token sequence are retained; edits that would merge distinct CR and LF terminators remain manual; no producer, call or function body is rewritten.",
|
|
2688
2858
|
"Only an inline binary parameter union in a strict module's top-level private scalar consumer is supported. Exactly one parameter, an explicit broad primitive return annotation, a single pure returned scalar expression and direct identifier-argument callers are required. Type queries or type-only exports of the callable, public APIs, callbacks, contextual signatures, overloads, generics, decorators, async functions, direct eval and fresh-object callers prevent findings.",
|
|
2689
2859
|
"Both alternatives must have complete ordinary finite structural surfaces consisting only of explicitly readonly broad string, number, boolean or bigint properties, optionally paired directly with null or undefined in an exact two-part union. Required and optional nullable fields may be read under the same native coverage proof. Every field must have one actual declaration origin throughout each alternative's inheritance/intersection graph. Shared ancestors retain that origin; repeated merged fields, explicit overrides and independently declared overlapping fields abstain, including valid compatible declarations. This excludes recovered conflicting properties without claiming whole-source health. Aliases, imports, re-exports and ordinary inheritance are resolved by the parser-owned TypeScript checker. Any, unknown, missing imports, open/generic/mapped/indexed types, classes, brands, literal discriminants, methods, properties with scalar type aliases, parenthesized or more complex property unions, callbacks and recursive or nested object fields are unsupported.",
|
|
2690
|
-
"Reports
|
|
2860
|
+
"Reports proper native assignability, where covered is assignable to covering and the reverse is false, or mutual native assignability with a strict smaller declared covering surface and only optional covered-only members. Every covering member, including optional members, must exist in the covered type's enumerated declared surface. Otherwise an existing identifier may carry an incompatible extra field and be rejected after simplification; implicit Object members containing Any cannot replace explicit declared coverage or the native Optional requirement. The covering type must declare every read field and a read required field; an all-optional reduced contract can reject existing callers. Identical alternatives and primitive/top/bottom redundancy remain upstream-owned; equal-key and incomparable mutually assignable structures are excluded. The mutual case additionally requires inline contracts or locally bound interfaces/type aliases whose alias and heritage references can be traced through the parser-owned type scope. Merged interface fragments must all resolve to the reference's same native symbol; mixed exported/local recovery abstains. Imported, global and qualified-namespace references in that path abstain; proper one-way coverage retains its existing alias/import support.",
|
|
2691
2861
|
"General union simplification can change Extract, conditional types, in-narrowing, fresh-literal checking and public presentation. Those contexts are excluded even when ordinary assignment succeeds. Flat destructuring counts every bound field as read; whole-object escape, mutation, helpers, closures, reflection, serialization, dynamic reads, implicit Object capabilities and JSX prevent findings. Imported Python protocol assignability is not approximated by this rule."
|
|
2692
2862
|
],
|
|
2693
2863
|
examples: [
|
|
2694
2864
|
{ id: "covered-alternative", title: "The private consumer needs the covering Animal contract", outcome: "match", files: [{ path: "src/case.ts", source: EXAMPLE }, CONFIG], focusPath: "src/case.ts", expectedCount: 1, public: true, fixedFiles: [{ path: "src/case.ts", source: EXAMPLE.replace("Dog | Animal", "Animal") }] },
|
|
2695
2865
|
{ id: "public-contract", title: "A public union retains its observable alternatives", outcome: "no-match", files: [{ path: "src/case.ts", source: EXAMPLE.replace("function label", "export function label") }, CONFIG], focusPath: "src/case.ts", expectedCount: 0, public: true },
|
|
2866
|
+
{ id: "optional-covered-alternative", scenarioId: "optional-readonly-contract", title: "An unread optional breed retains the smaller Animal surface", outcome: "match", files: [{ path: "src/case.ts", source: OPTIONAL_EXAMPLE }, CONFIG], focusPath: "src/case.ts", expectedCount: 1, public: true, fixedFiles: [{ path: "src/case.ts", source: OPTIONAL_EXAMPLE.replace("Dog | Animal", "Animal") }] },
|
|
2867
|
+
{ id: "optional-public-contract", scenarioId: "optional-readonly-contract", title: "A public optional union retains its observable alternatives", outcome: "no-match", files: [{ path: "src/case.ts", source: OPTIONAL_EXAMPLE.replace("function label", "export function label") }, CONFIG], focusPath: "src/case.ts", expectedCount: 0, public: true },
|
|
2696
2868
|
{ id: "nullable-covered-alternative", scenarioId: "nullable-readonly-contract", title: "A nullable name retains the covering Animal contract", outcome: "match", files: [{ path: "src/case.ts", source: NULLABLE_EXAMPLE }, CONFIG], focusPath: "src/case.ts", expectedCount: 1, public: true, fixedFiles: [{ path: "src/case.ts", source: NULLABLE_EXAMPLE.replace("Dog | Animal", "Animal") }] },
|
|
2697
2869
|
{ id: "nullable-domain-contract", scenarioId: "nullable-readonly-contract", title: "A literal breed keeps the authored domain contract", outcome: "no-match", files: [{ path: "src/case.ts", source: NULLABLE_EXAMPLE.replace("readonly breed: string", "readonly breed: 'Collie'") }, CONFIG], focusPath: "src/case.ts", expectedCount: 0, public: true }
|
|
2698
2870
|
]
|
|
@@ -2707,6 +2879,68 @@ function scalarFields(type, checker) {
|
|
|
2707
2879
|
}
|
|
2708
2880
|
return fields2.size ? fields2 : null;
|
|
2709
2881
|
}
|
|
2882
|
+
function localContractBindings(roots, source, services) {
|
|
2883
|
+
const pending = [...roots];
|
|
2884
|
+
const visited = /* @__PURE__ */ new Set();
|
|
2885
|
+
for (let index = 0; index < pending.length; index++) {
|
|
2886
|
+
const node = pending[index];
|
|
2887
|
+
if (!node || visited.has(node)) continue;
|
|
2888
|
+
visited.add(node);
|
|
2889
|
+
const references = localContractReferences(node, source, services);
|
|
2890
|
+
if (references === null) return false;
|
|
2891
|
+
pending.push(...references);
|
|
2892
|
+
}
|
|
2893
|
+
return true;
|
|
2894
|
+
}
|
|
2895
|
+
function localContractReferences(node, source, services) {
|
|
2896
|
+
switch (node.type) {
|
|
2897
|
+
case AST_NODE_TYPES24.TSTypeLiteral:
|
|
2898
|
+
return [];
|
|
2899
|
+
case AST_NODE_TYPES24.TSIntersectionType:
|
|
2900
|
+
return node.types;
|
|
2901
|
+
case AST_NODE_TYPES24.TSTypeReference:
|
|
2902
|
+
return !node.typeArguments && node.typeName.type === AST_NODE_TYPES24.Identifier ? [node.typeName] : null;
|
|
2903
|
+
case AST_NODE_TYPES24.Identifier:
|
|
2904
|
+
return localBindingReferences(node, source, services);
|
|
2905
|
+
default:
|
|
2906
|
+
return null;
|
|
2907
|
+
}
|
|
2908
|
+
}
|
|
2909
|
+
function localBindingReferences(identifier, source, services) {
|
|
2910
|
+
const definitions2 = typeBinding(source, identifier)?.defs.filter((definition) => definition.isTypeDefinition).map((definition) => definition.node);
|
|
2911
|
+
if (!definitions2?.length || !definitions2.every(moduleTypeDeclaration)) return null;
|
|
2912
|
+
const first = definitions2[0];
|
|
2913
|
+
if (definitions2.length === 1 && first?.type === AST_NODE_TYPES24.TSTypeAliasDeclaration && !first.typeParameters) return [first.typeAnnotation];
|
|
2914
|
+
const interfaces = definitions2.filter((definition) => definition.type === AST_NODE_TYPES24.TSInterfaceDeclaration);
|
|
2915
|
+
if (interfaces.length !== definitions2.length || interfaces.some((declaration) => declaration.typeParameters)) return null;
|
|
2916
|
+
if (interfaces.length > 1) {
|
|
2917
|
+
const checker = services.program.getTypeChecker();
|
|
2918
|
+
const symbol = checker.getSymbolAtLocation(services.esTreeNodeToTSNodeMap.get(identifier));
|
|
2919
|
+
if (!symbol || interfaces.some((declaration) => checker.getSymbolAtLocation(services.esTreeNodeToTSNodeMap.get(declaration.id)) !== symbol)) return null;
|
|
2920
|
+
}
|
|
2921
|
+
const bases = interfaces.flatMap((declaration) => declaration.extends.map((base) => base.expression));
|
|
2922
|
+
return bases.every((base) => base.type === AST_NODE_TYPES24.Identifier) ? bases : null;
|
|
2923
|
+
}
|
|
2924
|
+
function moduleTypeDeclaration(node) {
|
|
2925
|
+
const parent = node.parent;
|
|
2926
|
+
if (parent?.type === AST_NODE_TYPES24.Program) return true;
|
|
2927
|
+
if (parent?.type !== AST_NODE_TYPES24.ExportNamedDeclaration && parent?.type !== AST_NODE_TYPES24.ExportDefaultDeclaration) return false;
|
|
2928
|
+
return parent.parent.type === AST_NODE_TYPES24.Program;
|
|
2929
|
+
}
|
|
2930
|
+
function coveringAlternative(leftNode, rightNode, checker, fieldsOf, reads) {
|
|
2931
|
+
const left = checker.getTypeFromTypeNode(leftNode);
|
|
2932
|
+
const right = checker.getTypeFromTypeNode(rightNode);
|
|
2933
|
+
const leftFields = fieldsOf(left);
|
|
2934
|
+
const rightFields = fieldsOf(right);
|
|
2935
|
+
if (!leftFields || !rightFields) return null;
|
|
2936
|
+
const forward = checker.isTypeAssignableTo(left, right);
|
|
2937
|
+
const reverse = checker.isTypeAssignableTo(right, left);
|
|
2938
|
+
const mutual = forward && reverse;
|
|
2939
|
+
if (!forward && !reverse || mutual && leftFields.size === rightFields.size) return null;
|
|
2940
|
+
const [covered2, covering, coveredFields, coveringFields] = forward && (!reverse || leftFields.size > rightFields.size) ? [leftNode, rightNode, leftFields, rightFields] : [rightNode, leftNode, rightFields, leftFields];
|
|
2941
|
+
if ([...coveringFields.keys()].some((key) => !coveredFields.has(key)) || mutual && [...coveredFields].some(([key, required]) => required && !coveringFields.has(key)) || [...reads].some((key) => !coveringFields.has(key)) || ![...reads].some((key) => coveringFields.get(key))) return null;
|
|
2942
|
+
return { covered: covered2, covering, mutual };
|
|
2943
|
+
}
|
|
2710
2944
|
function privateUnionFix(sourceCode, services, proof) {
|
|
2711
2945
|
const covering = services.tsNodeToESTreeNodeMap.get(proof.covering);
|
|
2712
2946
|
if (!validConsumerFixCalls(proof.candidate, proof.parameter, sourceCode, services)) return null;
|
|
@@ -2726,7 +2960,7 @@ var no_redundant_consumer_union_default = createRule({
|
|
|
2726
2960
|
let dynamic = false;
|
|
2727
2961
|
const remember = (node) => {
|
|
2728
2962
|
const annotation = consumerAnnotation(node);
|
|
2729
|
-
if (annotation?.type ===
|
|
2963
|
+
if (annotation?.type === AST_NODE_TYPES24.TSUnionType && annotation.types.length === 2) candidates.push(node);
|
|
2730
2964
|
};
|
|
2731
2965
|
return {
|
|
2732
2966
|
FunctionDeclaration: remember,
|
|
@@ -2757,17 +2991,11 @@ var no_redundant_consumer_union_default = createRule({
|
|
|
2757
2991
|
const leftNode = annotation.types[0];
|
|
2758
2992
|
const rightNode = annotation.types[1];
|
|
2759
2993
|
if (!leftNode || !rightNode) continue;
|
|
2760
|
-
const
|
|
2761
|
-
|
|
2762
|
-
const leftFields = fieldsOf(left);
|
|
2763
|
-
const rightFields = fieldsOf(right);
|
|
2764
|
-
if (!leftFields || !rightFields) continue;
|
|
2765
|
-
const forward = checker.isTypeAssignableTo(left, right);
|
|
2766
|
-
const reverse = checker.isTypeAssignableTo(right, left);
|
|
2767
|
-
if (forward === reverse) continue;
|
|
2768
|
-
const [coveredNode, coveringNode, coveredFields, coveringFields] = forward ? [leftNode, rightNode, leftFields, rightFields] : [rightNode, leftNode, rightFields, leftFields];
|
|
2769
|
-
if ([...coveringFields.keys()].some((key) => !coveredFields.has(key)) || [...consumer.reads].some((key) => !coveringFields.has(key)) || ![...consumer.reads].some((key) => coveringFields.get(key))) continue;
|
|
2994
|
+
const coverage = coveringAlternative(leftNode, rightNode, checker, fieldsOf, consumer.reads);
|
|
2995
|
+
if (!coverage) continue;
|
|
2770
2996
|
const reportNode = services.tsNodeToESTreeNodeMap.get(annotation);
|
|
2997
|
+
if (coverage.mutual && (reportNode.type !== AST_NODE_TYPES24.TSUnionType || !localContractBindings(reportNode.types, context.sourceCode, services))) continue;
|
|
2998
|
+
const { covered: coveredNode, covering: coveringNode } = coverage;
|
|
2771
2999
|
const fix = privateUnionFix(context.sourceCode, services, {
|
|
2772
3000
|
candidate: candidate2,
|
|
2773
3001
|
parameter: consumer.parameter,
|
|
@@ -2784,7 +3012,7 @@ var no_redundant_consumer_union_default = createRule({
|
|
|
2784
3012
|
});
|
|
2785
3013
|
|
|
2786
3014
|
// src/rules/prefer-minimal-parameter-contract.ts
|
|
2787
|
-
import { AST_NODE_TYPES as
|
|
3015
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES25, ESLintUtils as ESLintUtils3 } from "@typescript-eslint/utils";
|
|
2788
3016
|
import ts8 from "typescript";
|
|
2789
3017
|
var CONFIG2 = { path: "tsconfig.json", source: '{"compilerOptions":{"strict":true,"target":"ESNext","module":"ESNext","moduleResolution":"Bundler"}}' };
|
|
2790
3018
|
var EXAMPLE2 = 'export {}; const account = {name: "Ada", email: "a"}; function label(user: {readonly email: string; readonly name: string}): string {return user.name;} label(account);';
|
|
@@ -2835,7 +3063,7 @@ var prefer_minimal_parameter_contract_default = createRule({
|
|
|
2835
3063
|
const candidates = [];
|
|
2836
3064
|
let dynamic = false;
|
|
2837
3065
|
const remember = (node) => {
|
|
2838
|
-
if (consumerAnnotation(node)?.type ===
|
|
3066
|
+
if (consumerAnnotation(node)?.type === AST_NODE_TYPES25.TSTypeLiteral) candidates.push(node);
|
|
2839
3067
|
};
|
|
2840
3068
|
return {
|
|
2841
3069
|
FunctionDeclaration: remember,
|
|
@@ -2869,7 +3097,7 @@ var prefer_minimal_parameter_contract_default = createRule({
|
|
|
2869
3097
|
});
|
|
2870
3098
|
|
|
2871
3099
|
// src/rules/no-excess-jsx-props.ts
|
|
2872
|
-
import { AST_NODE_TYPES as
|
|
3100
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES26, ESLintUtils as ESLintUtils4 } from "@typescript-eslint/utils";
|
|
2873
3101
|
import ts10 from "typescript";
|
|
2874
3102
|
|
|
2875
3103
|
// src/rules/_ordinary-object-effects.ts
|
|
@@ -3211,11 +3439,11 @@ var PRIMITIVE_OPERATORS = /* @__PURE__ */ new Set([
|
|
|
3211
3439
|
function plainLiteralFields(node) {
|
|
3212
3440
|
const fields2 = /* @__PURE__ */ new Map();
|
|
3213
3441
|
for (const property of node.properties) {
|
|
3214
|
-
if (property.type !==
|
|
3442
|
+
if (property.type !== AST_NODE_TYPES26.Property || property.kind !== "init") return null;
|
|
3215
3443
|
const key = property.key;
|
|
3216
3444
|
let name;
|
|
3217
|
-
if (!property.computed && key.type ===
|
|
3218
|
-
else if (key.type ===
|
|
3445
|
+
if (!property.computed && key.type === AST_NODE_TYPES26.Identifier) name = key.name;
|
|
3446
|
+
else if (key.type === AST_NODE_TYPES26.Literal && (typeof key.value === "string" || typeof key.value === "number")) name = String(key.value);
|
|
3219
3447
|
else return null;
|
|
3220
3448
|
if (name === "__proto__") return null;
|
|
3221
3449
|
fields2.set(name, property);
|
|
@@ -3327,35 +3555,35 @@ function localObjectFields(symbol, source, proof) {
|
|
|
3327
3555
|
if (!native || native.getSourceFile() !== source || !initializer || !ts10.isObjectLiteralExpression(initializer)) return null;
|
|
3328
3556
|
const declaration = proof.services.tsNodeToESTreeNodeMap.get(native);
|
|
3329
3557
|
const literal2 = proof.services.tsNodeToESTreeNodeMap.get(initializer);
|
|
3330
|
-
if (declaration.type !==
|
|
3558
|
+
if (declaration.type !== AST_NODE_TYPES26.VariableDeclarator || declaration.parent.kind !== "const" || declaration.id.type !== AST_NODE_TYPES26.Identifier || literal2.type !== AST_NODE_TYPES26.ObjectExpression || declaration.parent.parent.type === AST_NODE_TYPES26.ExportNamedDeclaration) return null;
|
|
3331
3559
|
const fields2 = plainLiteralFields(literal2);
|
|
3332
3560
|
const binding3 = proof.sourceCode.getDeclaredVariables(declaration).find((variable) => variable.defs.some((definition) => definition.type === "Variable" && definition.node === declaration));
|
|
3333
3561
|
if (!fields2 || !binding3 || binding3.defs.length !== 1 || !stableValueBinding(binding3, (reference) => {
|
|
3334
3562
|
if (!reference.isReadOnly() || reference.isTypeReference) return false;
|
|
3335
3563
|
const member3 = reference.identifier.parent;
|
|
3336
|
-
return member3.type ===
|
|
3564
|
+
return member3.type === AST_NODE_TYPES26.MemberExpression && member3.object === reference.identifier && readonlyFieldValue(member3, fields2);
|
|
3337
3565
|
})) return null;
|
|
3338
3566
|
return fields2;
|
|
3339
3567
|
}
|
|
3340
3568
|
function staticMemberKey(member3) {
|
|
3341
3569
|
const property = member3.property;
|
|
3342
|
-
return !member3.computed && property.type ===
|
|
3570
|
+
return !member3.computed && property.type === AST_NODE_TYPES26.Identifier ? property.name : property.type === AST_NODE_TYPES26.Literal && (typeof property.value === "string" || typeof property.value === "number") ? String(property.value) : void 0;
|
|
3343
3571
|
}
|
|
3344
3572
|
function readonlyFieldValue(member3, fields2) {
|
|
3345
3573
|
const key = staticMemberKey(member3);
|
|
3346
3574
|
if (key === void 0 || !fields2.has(key)) return false;
|
|
3347
3575
|
const parent = member3.parent;
|
|
3348
|
-
if (parent.type ===
|
|
3576
|
+
if (parent.type === AST_NODE_TYPES26.Property && parent.value === member3 && parent.parent.type === AST_NODE_TYPES26.ObjectExpression) {
|
|
3349
3577
|
const object = parent.parent;
|
|
3350
3578
|
const owner = object.parent;
|
|
3351
|
-
return owner.type ===
|
|
3579
|
+
return owner.type === AST_NODE_TYPES26.JSXSpreadAttribute && owner.argument === object || owner.type === AST_NODE_TYPES26.VariableDeclarator && owner.init === object;
|
|
3352
3580
|
}
|
|
3353
|
-
return parent.type ===
|
|
3581
|
+
return parent.type === AST_NODE_TYPES26.JSXExpressionContainer && parent.expression === member3 || parent.type === AST_NODE_TYPES26.VariableDeclarator && parent.init === member3;
|
|
3354
3582
|
}
|
|
3355
3583
|
function privateElementDeclaration(opening) {
|
|
3356
3584
|
const value = outerExpression(opening.parent);
|
|
3357
3585
|
const declaration = value.parent;
|
|
3358
|
-
return declaration.type ===
|
|
3586
|
+
return declaration.type === AST_NODE_TYPES26.VariableDeclarator && declaration.init === value && declaration.id.type === AST_NODE_TYPES26.Identifier && declaration.parent.kind === "const" && declaration.parent.parent.type !== AST_NODE_TYPES26.ExportNamedDeclaration ? declaration : null;
|
|
3359
3587
|
}
|
|
3360
3588
|
function closedElementValue(opening, declaration, fields2, reads, proof) {
|
|
3361
3589
|
if (!proof.staticScope || !closedInvocation(opening, proof) || !constInitializer(proof.services.esTreeNodeToTSNodeMap.get(declaration))) return false;
|
|
@@ -3381,10 +3609,10 @@ function closedInvocation(node, proof) {
|
|
|
3381
3609
|
}
|
|
3382
3610
|
function independentInvocation(scope, proof) {
|
|
3383
3611
|
const block = scope.block;
|
|
3384
|
-
if (block.type !==
|
|
3612
|
+
if (block.type !== AST_NODE_TYPES26.ArrowFunctionExpression && block.type !== AST_NODE_TYPES26.FunctionDeclaration && block.type !== AST_NODE_TYPES26.FunctionExpression) return false;
|
|
3385
3613
|
if (block.async || block.generator || scope.set.get("arguments")?.references.some((reference) => !typeOnlyReference(reference))) return false;
|
|
3386
3614
|
for (const parameter of block.params) {
|
|
3387
|
-
if (parameter.type !==
|
|
3615
|
+
if (parameter.type !== AST_NODE_TYPES26.Identifier || parameter.name === "this") return false;
|
|
3388
3616
|
const binding3 = scope.set.get(parameter.name);
|
|
3389
3617
|
if (!binding3 || binding3.references.some((reference) => !typeOnlyReference(reference))) return false;
|
|
3390
3618
|
}
|
|
@@ -3392,16 +3620,16 @@ function independentInvocation(scope, proof) {
|
|
|
3392
3620
|
if (typeOnlyReference(reference)) return true;
|
|
3393
3621
|
const value = outerExpression(reference.identifier);
|
|
3394
3622
|
const parent = value.parent;
|
|
3395
|
-
const read = parent?.type ===
|
|
3623
|
+
const read = parent?.type === AST_NODE_TYPES26.MemberExpression && parent.object === value ? parent : value;
|
|
3396
3624
|
return primitiveValue(proof.services.esTreeNodeToTSNodeMap.get(read), proof, /* @__PURE__ */ new Set());
|
|
3397
3625
|
});
|
|
3398
3626
|
}
|
|
3399
3627
|
function consumedElementRead(node, fields2, reads) {
|
|
3400
3628
|
const identifier = outerExpression(node);
|
|
3401
3629
|
const props = identifier.parent;
|
|
3402
|
-
if (!props || props.type !==
|
|
3630
|
+
if (!props || props.type !== AST_NODE_TYPES26.MemberExpression || props.object !== identifier || props.optional || staticMemberKey(props) !== "props") return false;
|
|
3403
3631
|
const member3 = props.parent;
|
|
3404
|
-
if (member3.type !==
|
|
3632
|
+
if (member3.type !== AST_NODE_TYPES26.MemberExpression || member3.object !== props || member3.optional) return false;
|
|
3405
3633
|
const key = staticMemberKey(member3);
|
|
3406
3634
|
return key !== void 0 && reads.has(key) && readonlyFieldValue(member3, fields2);
|
|
3407
3635
|
}
|
|
@@ -3462,9 +3690,9 @@ var no_excess_jsx_props_default = createRule({
|
|
|
3462
3690
|
};
|
|
3463
3691
|
return {
|
|
3464
3692
|
JSXSpreadAttribute(node) {
|
|
3465
|
-
if (node.argument.type !==
|
|
3693
|
+
if (node.argument.type !== AST_NODE_TYPES26.ObjectExpression) return;
|
|
3466
3694
|
const opening = node.parent;
|
|
3467
|
-
if (!opening.selfClosing || opening.attributes.length !== 1 || opening.name.type !==
|
|
3695
|
+
if (!opening.selfClosing || opening.attributes.length !== 1 || opening.name.type !== AST_NODE_TYPES26.JSXIdentifier || /^[a-z]/u.test(opening.name.name)) return;
|
|
3468
3696
|
const declaration = privateElementDeclaration(opening);
|
|
3469
3697
|
if (!declaration) return;
|
|
3470
3698
|
const fields2 = literalFields(node.argument);
|
|
@@ -3485,7 +3713,7 @@ var no_excess_jsx_props_default = createRule({
|
|
|
3485
3713
|
});
|
|
3486
3714
|
|
|
3487
3715
|
// src/rules/prefer-native-fetch-in-server-actions.ts
|
|
3488
|
-
import { AST_NODE_TYPES as
|
|
3716
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES27 } from "@typescript-eslint/utils";
|
|
3489
3717
|
var KY_MODULE = /^ky(?:\/.*)?$/u;
|
|
3490
3718
|
var PREFER_NATIVE_FETCH_IN_SERVER_ACTIONS_DOCUMENTATION = {
|
|
3491
3719
|
defaultLevel: "warning",
|
|
@@ -3549,19 +3777,19 @@ var prefer_native_fetch_in_server_actions_default = createRule({
|
|
|
3549
3777
|
});
|
|
3550
3778
|
function hasUseServerDirective(program) {
|
|
3551
3779
|
for (const statement of program.body) {
|
|
3552
|
-
if (statement.type !==
|
|
3780
|
+
if (statement.type !== AST_NODE_TYPES27.ExpressionStatement || statement.directive === void 0) return false;
|
|
3553
3781
|
if (statement.directive === "use server") return true;
|
|
3554
3782
|
}
|
|
3555
3783
|
return false;
|
|
3556
3784
|
}
|
|
3557
3785
|
function isTypeOnly(node) {
|
|
3558
3786
|
return node.importKind === "type" || node.specifiers.length > 0 && node.specifiers.every(
|
|
3559
|
-
(specifier) => specifier.type ===
|
|
3787
|
+
(specifier) => specifier.type === AST_NODE_TYPES27.ImportSpecifier && specifier.importKind === "type"
|
|
3560
3788
|
);
|
|
3561
3789
|
}
|
|
3562
3790
|
|
|
3563
3791
|
// src/rules/no-credential-in-browser-storage.ts
|
|
3564
|
-
import { AST_NODE_TYPES as
|
|
3792
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES28, ASTUtils as ASTUtils17 } from "@typescript-eslint/utils";
|
|
3565
3793
|
|
|
3566
3794
|
// src/rules/_secret-names.ts
|
|
3567
3795
|
var SECRET_WORDS = /* @__PURE__ */ new Set([
|
|
@@ -3705,54 +3933,10 @@ function isAuthSecretName(identifier) {
|
|
|
3705
3933
|
return hasApiKey(tokens);
|
|
3706
3934
|
}
|
|
3707
3935
|
|
|
3708
|
-
// src/rules/_static-string.ts
|
|
3709
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES26, ASTUtils as ASTUtils15 } from "@typescript-eslint/utils";
|
|
3710
|
-
function staticString(node) {
|
|
3711
|
-
if (node === void 0) return null;
|
|
3712
|
-
const value = unwrapExpression(node);
|
|
3713
|
-
if (value.type === AST_NODE_TYPES26.Literal && typeof value.value === "string") return value.value;
|
|
3714
|
-
return value.type === AST_NODE_TYPES26.TemplateLiteral && value.expressions.length === 0 ? value.quasis[0]?.value.cooked ?? null : null;
|
|
3715
|
-
}
|
|
3716
|
-
var SCOPED_STRING_VALUES = /* @__PURE__ */ new WeakMap();
|
|
3717
|
-
function scopedStaticString(node, sourceCode) {
|
|
3718
|
-
let value = unwrapExpression(node);
|
|
3719
|
-
if (value.type !== AST_NODE_TYPES26.Identifier) return staticString(value);
|
|
3720
|
-
let values = SCOPED_STRING_VALUES.get(sourceCode);
|
|
3721
|
-
if (values === void 0) {
|
|
3722
|
-
values = /* @__PURE__ */ new WeakMap();
|
|
3723
|
-
SCOPED_STRING_VALUES.set(sourceCode, values);
|
|
3724
|
-
}
|
|
3725
|
-
const seen = /* @__PURE__ */ new Set();
|
|
3726
|
-
const pending = [];
|
|
3727
|
-
let result = null;
|
|
3728
|
-
while (value.type === AST_NODE_TYPES26.Identifier) {
|
|
3729
|
-
const binding3 = ASTUtils15.findVariable(sourceCode.getScope(value), value.name);
|
|
3730
|
-
if (binding3 === null || seen.has(binding3)) break;
|
|
3731
|
-
if (values.has(binding3)) {
|
|
3732
|
-
result = values.get(binding3) ?? null;
|
|
3733
|
-
break;
|
|
3734
|
-
}
|
|
3735
|
-
seen.add(binding3);
|
|
3736
|
-
pending.push(binding3);
|
|
3737
|
-
const definition = binding3.defs.length === 1 ? binding3.defs[0] : void 0;
|
|
3738
|
-
if (definition?.type !== "Variable" || definition.node.id.type !== AST_NODE_TYPES26.Identifier || definition.node.init === null || binding3.references.some((reference) => reference.isWrite() && reference.init !== true)) break;
|
|
3739
|
-
value = unwrapExpression(definition.node.init);
|
|
3740
|
-
if (value.type !== AST_NODE_TYPES26.Identifier) result = staticString(value);
|
|
3741
|
-
}
|
|
3742
|
-
for (const binding3 of pending) values.set(binding3, result);
|
|
3743
|
-
return result;
|
|
3744
|
-
}
|
|
3745
|
-
function staticPropertyName(node, sourceCode) {
|
|
3746
|
-
const direct = ASTUtils15.getPropertyName(node);
|
|
3747
|
-
if (direct !== null || !node.computed) return direct;
|
|
3748
|
-
const key = node.type === AST_NODE_TYPES26.MemberExpression ? node.property : node.key;
|
|
3749
|
-
return scopedStaticString(key, sourceCode);
|
|
3750
|
-
}
|
|
3751
|
-
|
|
3752
3936
|
// src/rules/no-credential-in-browser-storage.ts
|
|
3753
3937
|
var STORAGE_NAMES = /* @__PURE__ */ new Set(["localStorage", "sessionStorage"]);
|
|
3754
3938
|
var METADATA_WORDS = /* @__PURE__ */ new Set(["page", "cursor", "next", "hint", "expires", "expiry", "expiration"]);
|
|
3755
|
-
var
|
|
3939
|
+
var GLOBAL_OBJECTS2 = /* @__PURE__ */ new Set(["window", "globalThis", "self"]);
|
|
3756
3940
|
var NO_CREDENTIAL_IN_BROWSER_STORAGE_DOCUMENTATION = {
|
|
3757
3941
|
defaultLevel: "warning",
|
|
3758
3942
|
summary: "Do not write credential-named values to browser storage or script-readable cookies.",
|
|
@@ -3810,7 +3994,7 @@ var no_credential_in_browser_storage_default = createRule({
|
|
|
3810
3994
|
return {
|
|
3811
3995
|
CallExpression(node) {
|
|
3812
3996
|
const callee = unwrapExpression(node.callee);
|
|
3813
|
-
if (callee.type !==
|
|
3997
|
+
if (callee.type !== AST_NODE_TYPES28.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES28.Identifier || callee.property.name !== "setItem" || !isStorage(sourceCode, callee.object)) {
|
|
3814
3998
|
return;
|
|
3815
3999
|
}
|
|
3816
4000
|
const [key] = node.arguments;
|
|
@@ -3818,12 +4002,12 @@ var no_credential_in_browser_storage_default = createRule({
|
|
|
3818
4002
|
},
|
|
3819
4003
|
AssignmentExpression(node) {
|
|
3820
4004
|
const target = node.left;
|
|
3821
|
-
if (target.type !==
|
|
4005
|
+
if (target.type !== AST_NODE_TYPES28.MemberExpression) return;
|
|
3822
4006
|
if (isStorage(sourceCode, target.object)) {
|
|
3823
4007
|
report2(node, storedPropertyKey(sourceCode, target));
|
|
3824
4008
|
return;
|
|
3825
4009
|
}
|
|
3826
|
-
if (!target.computed && target.property.type ===
|
|
4010
|
+
if (!target.computed && target.property.type === AST_NODE_TYPES28.Identifier && target.property.name === "cookie" && globalMemberName(sourceCode, target.object) === "document") {
|
|
3827
4011
|
report2(node, cookieName(node.right));
|
|
3828
4012
|
}
|
|
3829
4013
|
}
|
|
@@ -3836,36 +4020,36 @@ function isStorage(sourceCode, node) {
|
|
|
3836
4020
|
}
|
|
3837
4021
|
function globalMemberName(sourceCode, node) {
|
|
3838
4022
|
const value = unwrapExpression(node);
|
|
3839
|
-
if (value.type ===
|
|
3840
|
-
if (value.type ===
|
|
4023
|
+
if (value.type === AST_NODE_TYPES28.Identifier) return isUnshadowed(sourceCode, value) ? value.name : null;
|
|
4024
|
+
if (value.type === AST_NODE_TYPES28.MemberExpression && !value.computed && value.object.type === AST_NODE_TYPES28.Identifier && GLOBAL_OBJECTS2.has(value.object.name) && value.property.type === AST_NODE_TYPES28.Identifier && isUnshadowed(sourceCode, value.object)) {
|
|
3841
4025
|
return value.property.name;
|
|
3842
4026
|
}
|
|
3843
4027
|
return null;
|
|
3844
4028
|
}
|
|
3845
4029
|
function isUnshadowed(sourceCode, node) {
|
|
3846
|
-
const variable =
|
|
4030
|
+
const variable = ASTUtils17.findVariable(sourceCode.getScope(node), node.name);
|
|
3847
4031
|
return variable === null || variable.defs.length === 0;
|
|
3848
4032
|
}
|
|
3849
4033
|
function storedPropertyKey(sourceCode, target) {
|
|
3850
|
-
if (!target.computed) return target.property.type ===
|
|
4034
|
+
if (!target.computed) return target.property.type === AST_NODE_TYPES28.Identifier ? target.property.name : null;
|
|
3851
4035
|
return scopedStaticString(target.property, sourceCode);
|
|
3852
4036
|
}
|
|
3853
4037
|
function cookieName(value) {
|
|
3854
4038
|
let expression = unwrapExpression(value);
|
|
3855
|
-
while (expression.type ===
|
|
4039
|
+
while (expression.type === AST_NODE_TYPES28.BinaryExpression && expression.operator === "+") {
|
|
3856
4040
|
expression = unwrapExpression(expression.left);
|
|
3857
4041
|
}
|
|
3858
4042
|
let text = null;
|
|
3859
|
-
if (expression.type ===
|
|
3860
|
-
if (expression.type ===
|
|
4043
|
+
if (expression.type === AST_NODE_TYPES28.Literal && typeof expression.value === "string") text = expression.value;
|
|
4044
|
+
if (expression.type === AST_NODE_TYPES28.TemplateLiteral) text = expression.quasis[0]?.value.cooked ?? null;
|
|
3861
4045
|
if (text === null || !text.includes("=")) return null;
|
|
3862
4046
|
return text.slice(0, text.indexOf("=")).trim();
|
|
3863
4047
|
}
|
|
3864
4048
|
|
|
3865
4049
|
// src/rules/no-numeric-search-param-coercion.ts
|
|
3866
4050
|
import {
|
|
3867
|
-
AST_NODE_TYPES as
|
|
3868
|
-
ASTUtils as
|
|
4051
|
+
AST_NODE_TYPES as AST_NODE_TYPES29,
|
|
4052
|
+
ASTUtils as ASTUtils18,
|
|
3869
4053
|
ESLintUtils as ESLintUtils5
|
|
3870
4054
|
} from "@typescript-eslint/utils";
|
|
3871
4055
|
var GLOBAL_PARSERS = /* @__PURE__ */ new Set(["parseInt", "parseFloat", "Number"]);
|
|
@@ -3946,27 +4130,27 @@ var no_numeric_search_param_coercion_default = createRule({
|
|
|
3946
4130
|
}
|
|
3947
4131
|
});
|
|
3948
4132
|
function isNumericParser(sourceCode, callee) {
|
|
3949
|
-
if (callee.type ===
|
|
4133
|
+
if (callee.type === AST_NODE_TYPES29.Identifier) {
|
|
3950
4134
|
return GLOBAL_PARSERS.has(callee.name) && isUnshadowedGlobal(sourceCode, callee);
|
|
3951
4135
|
}
|
|
3952
|
-
return callee.type ===
|
|
4136
|
+
return callee.type === AST_NODE_TYPES29.MemberExpression && !callee.computed && callee.object.type === AST_NODE_TYPES29.Identifier && callee.object.name === "Number" && callee.property.type === AST_NODE_TYPES29.Identifier && NUMBER_PARSERS.has(callee.property.name) && isUnshadowedGlobal(sourceCode, callee.object);
|
|
3953
4137
|
}
|
|
3954
4138
|
function isUnshadowedGlobal(sourceCode, node) {
|
|
3955
|
-
const variable =
|
|
4139
|
+
const variable = ASTUtils18.findVariable(sourceCode.getScope(node), node.name);
|
|
3956
4140
|
return variable === null || variable.defs.length === 0;
|
|
3957
4141
|
}
|
|
3958
4142
|
function searchParamGetCall(argument) {
|
|
3959
4143
|
let value = unwrapExpression(argument);
|
|
3960
|
-
if (value.type ===
|
|
3961
|
-
if (value.type ===
|
|
3962
|
-
if (value.type ===
|
|
3963
|
-
if (value.type !==
|
|
4144
|
+
if (value.type === AST_NODE_TYPES29.AwaitExpression) value = unwrapExpression(value.argument);
|
|
4145
|
+
if (value.type === AST_NODE_TYPES29.LogicalExpression && value.operator === "??") value = unwrapExpression(value.left);
|
|
4146
|
+
if (value.type === AST_NODE_TYPES29.ChainExpression) value = value.expression;
|
|
4147
|
+
if (value.type !== AST_NODE_TYPES29.CallExpression || value.callee.type !== AST_NODE_TYPES29.MemberExpression || value.callee.computed || value.callee.property.type !== AST_NODE_TYPES29.Identifier || value.callee.property.name !== "get") {
|
|
3964
4148
|
return null;
|
|
3965
4149
|
}
|
|
3966
4150
|
return value;
|
|
3967
4151
|
}
|
|
3968
4152
|
function isSearchParamReceiver(call, services) {
|
|
3969
|
-
if (call.callee.type !==
|
|
4153
|
+
if (call.callee.type !== AST_NODE_TYPES29.MemberExpression) return false;
|
|
3970
4154
|
const checker = services.program.getTypeChecker();
|
|
3971
4155
|
const type = checker.getNonNullableType(
|
|
3972
4156
|
checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(call.callee.object))
|
|
@@ -3978,7 +4162,7 @@ function isSearchParamReceiver(call, services) {
|
|
|
3978
4162
|
// package.json
|
|
3979
4163
|
var package_default = {
|
|
3980
4164
|
name: "@sarj/eslint-plugin",
|
|
3981
|
-
version: "16.
|
|
4165
|
+
version: "16.38.50",
|
|
3982
4166
|
packageManager: "npm@12.2.1",
|
|
3983
4167
|
description: "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
|
|
3984
4168
|
type: "module",
|
|
@@ -4101,15 +4285,15 @@ var package_default = {
|
|
|
4101
4285
|
|
|
4102
4286
|
// src/rules/require-explicit-contract-implementation.ts
|
|
4103
4287
|
import {
|
|
4104
|
-
AST_NODE_TYPES as
|
|
4288
|
+
AST_NODE_TYPES as AST_NODE_TYPES31,
|
|
4105
4289
|
ESLintUtils as ESLintUtils6
|
|
4106
4290
|
} from "@typescript-eslint/utils";
|
|
4107
4291
|
import * as ts12 from "typescript";
|
|
4108
4292
|
|
|
4109
4293
|
// src/rules/_closed-nominal-inheritance-fix.ts
|
|
4110
4294
|
import {
|
|
4111
|
-
AST_NODE_TYPES as
|
|
4112
|
-
ASTUtils as
|
|
4295
|
+
AST_NODE_TYPES as AST_NODE_TYPES30,
|
|
4296
|
+
ASTUtils as ASTUtils19
|
|
4113
4297
|
} from "@typescript-eslint/utils";
|
|
4114
4298
|
import ts11 from "typescript";
|
|
4115
4299
|
function closedNominalInheritanceFix(sourceCode, call, consumer, implementation, contract) {
|
|
@@ -4184,7 +4368,7 @@ function exactRejection(sourceCode, statement) {
|
|
|
4184
4368
|
const identifier = sourceCode.getNodeByRangeIndex(
|
|
4185
4369
|
rejected.expression.expression.getStart()
|
|
4186
4370
|
);
|
|
4187
|
-
return identifier?.type ===
|
|
4371
|
+
return identifier?.type === AST_NODE_TYPES30.Identifier && identifier.name === "TypeError" && (ASTUtils19.findVariable(sourceCode.getScope(identifier), identifier.name)?.defs.length ?? 0) === 0;
|
|
4188
4372
|
}
|
|
4189
4373
|
function exactConstruction(node, consumer, implementation) {
|
|
4190
4374
|
if (!ts11.isIdentifier(node.expression) || node.expression.text !== consumer || node.typeArguments !== void 0 || node.arguments?.length !== 1)
|
|
@@ -4565,7 +4749,7 @@ var require_explicit_contract_implementation_default = createRule({
|
|
|
4565
4749
|
return;
|
|
4566
4750
|
const parameters = signature.getParameters();
|
|
4567
4751
|
for (const [index, argument] of node.arguments.entries()) {
|
|
4568
|
-
if (argument.type !==
|
|
4752
|
+
if (argument.type !== AST_NODE_TYPES31.NewExpression) continue;
|
|
4569
4753
|
const parameter = parameters[index];
|
|
4570
4754
|
if (parameter === void 0) continue;
|
|
4571
4755
|
const tsArgument = services.esTreeNodeToTSNodeMap.get(argument);
|
|
@@ -4616,17 +4800,17 @@ import "@typescript-eslint/utils";
|
|
|
4616
4800
|
|
|
4617
4801
|
// src/rules/_existing-factory-contract-fix.ts
|
|
4618
4802
|
import {
|
|
4619
|
-
AST_NODE_TYPES as
|
|
4620
|
-
ASTUtils as
|
|
4803
|
+
AST_NODE_TYPES as AST_NODE_TYPES32,
|
|
4804
|
+
ASTUtils as ASTUtils20
|
|
4621
4805
|
} from "@typescript-eslint/utils";
|
|
4622
4806
|
function existingFactoryContractFix(sourceCode, candidate2) {
|
|
4623
4807
|
if (sourceCode.ast.body.length !== 4 || sourceCode.getAllComments().length !== 0)
|
|
4624
4808
|
return null;
|
|
4625
4809
|
const [contractStatement, worker, classStatement, factoryStatement] = sourceCode.ast.body;
|
|
4626
|
-
const contract = contractStatement?.type ===
|
|
4627
|
-
const implementation = classStatement?.type ===
|
|
4628
|
-
const factory = factoryStatement?.type ===
|
|
4629
|
-
if (contract?.type !==
|
|
4810
|
+
const contract = contractStatement?.type === AST_NODE_TYPES32.ExportNamedDeclaration ? contractStatement.declaration : null;
|
|
4811
|
+
const implementation = classStatement?.type === AST_NODE_TYPES32.ExportNamedDeclaration ? classStatement.declaration : classStatement;
|
|
4812
|
+
const factory = factoryStatement?.type === AST_NODE_TYPES32.ExportNamedDeclaration ? factoryStatement.declaration : null;
|
|
4813
|
+
if (contract?.type !== AST_NODE_TYPES32.TSTypeAliasDeclaration || worker?.type !== AST_NODE_TYPES32.TSInterfaceDeclaration || implementation?.type !== AST_NODE_TYPES32.ClassDeclaration || implementation !== candidate2 || !ordinaryClass(implementation) || !ordinaryFactory(factory))
|
|
4630
4814
|
return null;
|
|
4631
4815
|
const operation2 = contractOperation(contract);
|
|
4632
4816
|
if (operation2 === null || interfaceOperation(worker) !== operation2)
|
|
@@ -4645,17 +4829,17 @@ function ordinaryClass(node) {
|
|
|
4645
4829
|
return node.id !== null && !node.declare && !node.abstract && node.decorators.length === 0 && node.superClass === null && node.implements.length === 0 && node.typeParameters === void 0 && node.body.body.length === 2;
|
|
4646
4830
|
}
|
|
4647
4831
|
function ordinaryFactory(node) {
|
|
4648
|
-
return node?.type ===
|
|
4832
|
+
return node?.type === AST_NODE_TYPES32.FunctionDeclaration && node.id !== null && !node.declare && !node.async && !node.generator && node.typeParameters === void 0 && node.params.length === 1 && node.body.body.length === 1;
|
|
4649
4833
|
}
|
|
4650
4834
|
function interfaceOperation(node) {
|
|
4651
4835
|
return !node.declare && node.extends.length === 0 && node.typeParameters === void 0 ? singletonOperation(node.body.body) : null;
|
|
4652
4836
|
}
|
|
4653
4837
|
function contractOperation(node) {
|
|
4654
|
-
return !node.declare && node.typeParameters === void 0 && node.typeAnnotation.type ===
|
|
4838
|
+
return !node.declare && node.typeParameters === void 0 && node.typeAnnotation.type === AST_NODE_TYPES32.TSTypeLiteral ? singletonOperation(node.typeAnnotation.members) : null;
|
|
4655
4839
|
}
|
|
4656
4840
|
function singletonOperation(members) {
|
|
4657
4841
|
const member3 = members[0];
|
|
4658
|
-
return members.length === 1 && member3?.type ===
|
|
4842
|
+
return members.length === 1 && member3?.type === AST_NODE_TYPES32.TSMethodSignature && member3.kind === "method" && !member3.computed && !member3.optional && member3.key.type === AST_NODE_TYPES32.Identifier && member3.params.length === 0 && member3.typeParameters === void 0 && member3.returnType?.typeAnnotation.type === AST_NODE_TYPES32.TSVoidKeyword ? member3.key.name : null;
|
|
4659
4843
|
}
|
|
4660
4844
|
function uniqueDeclarations(sourceCode, declarations) {
|
|
4661
4845
|
const names = declarations.flatMap(
|
|
@@ -4666,7 +4850,7 @@ function uniqueDeclarations(sourceCode, declarations) {
|
|
|
4666
4850
|
);
|
|
4667
4851
|
}
|
|
4668
4852
|
function sameBinding(sourceCode, reference, declaration) {
|
|
4669
|
-
const binding3 =
|
|
4853
|
+
const binding3 = ASTUtils20.findVariable(
|
|
4670
4854
|
sourceCode.getScope(reference),
|
|
4671
4855
|
reference.name
|
|
4672
4856
|
);
|
|
@@ -4674,47 +4858,47 @@ function sameBinding(sourceCode, reference, declaration) {
|
|
|
4674
4858
|
}
|
|
4675
4859
|
function retainedWorker(sourceCode, implementation, worker) {
|
|
4676
4860
|
const constructor = implementation.body.body[0];
|
|
4677
|
-
if (constructor?.type !==
|
|
4861
|
+
if (constructor?.type !== AST_NODE_TYPES32.MethodDefinition || constructor.value.type !== AST_NODE_TYPES32.FunctionExpression || constructor.kind !== "constructor" || constructor.computed || constructor.static || constructor.decorators.length !== 0 || constructor.optional || constructor.accessibility !== void 0 && constructor.accessibility !== "public" || constructor.value.async || constructor.value.generator || constructor.value.typeParameters !== void 0 || constructor.value.returnType !== void 0 || constructor.value.body.body.length !== 0 || constructor.value.params.length !== 1)
|
|
4678
4862
|
return null;
|
|
4679
4863
|
const property = constructor.value.params[0];
|
|
4680
|
-
if (property?.type !==
|
|
4864
|
+
if (property?.type !== AST_NODE_TYPES32.TSParameterProperty || property.accessibility !== "private" || !property.readonly || property.override || property.decorators.length !== 0 || property.parameter.type !== AST_NODE_TYPES32.Identifier || property.parameter.optional || !typeReference(sourceCode, property.parameter.typeAnnotation, worker))
|
|
4681
4865
|
return null;
|
|
4682
4866
|
return property.parameter.name;
|
|
4683
4867
|
}
|
|
4684
4868
|
function typeReference(sourceCode, annotation, declaration) {
|
|
4685
4869
|
const type = annotation?.typeAnnotation;
|
|
4686
|
-
return type?.type ===
|
|
4870
|
+
return type?.type === AST_NODE_TYPES32.TSTypeReference && type.typeArguments === void 0 && type.typeName.type === AST_NODE_TYPES32.Identifier && sameBinding(sourceCode, type.typeName, declaration);
|
|
4687
4871
|
}
|
|
4688
4872
|
function forwardsOperation(implementation, field, operation2) {
|
|
4689
4873
|
const method = implementation.body.body[1];
|
|
4690
|
-
if (method?.type !==
|
|
4874
|
+
if (method?.type !== AST_NODE_TYPES32.MethodDefinition || method.kind !== "method" || method.value.type !== AST_NODE_TYPES32.FunctionExpression || method.computed || method.static || method.optional || method.override || method.decorators.length !== 0 || method.accessibility !== void 0 && method.accessibility !== "public" || method.key.type !== AST_NODE_TYPES32.Identifier || method.key.name !== operation2 || method.value.async || method.value.generator || method.value.typeParameters !== void 0 || method.value.params.length !== 0 || method.value.body.body.length !== 1 || method.value.returnType?.typeAnnotation.type !== AST_NODE_TYPES32.TSVoidKeyword)
|
|
4691
4875
|
return false;
|
|
4692
4876
|
const statement = method.value.body.body[0];
|
|
4693
|
-
const call = statement?.type ===
|
|
4694
|
-
return call?.type ===
|
|
4877
|
+
const call = statement?.type === AST_NODE_TYPES32.ExpressionStatement ? statement.expression : null;
|
|
4878
|
+
return call?.type === AST_NODE_TYPES32.CallExpression && !call.optional && call.typeArguments === void 0 && call.arguments.length === 0 && forwardedMember(call.callee, field, operation2);
|
|
4695
4879
|
}
|
|
4696
4880
|
function forwardedMember(node, field, operation2) {
|
|
4697
|
-
if (node.type !==
|
|
4881
|
+
if (node.type !== AST_NODE_TYPES32.MemberExpression || node.computed || node.optional || node.property.type !== AST_NODE_TYPES32.Identifier || node.property.name !== operation2)
|
|
4698
4882
|
return false;
|
|
4699
4883
|
const receiver = node.object;
|
|
4700
|
-
return receiver.type ===
|
|
4884
|
+
return receiver.type === AST_NODE_TYPES32.MemberExpression && !receiver.computed && !receiver.optional && receiver.object.type === AST_NODE_TYPES32.ThisExpression && receiver.property.type === AST_NODE_TYPES32.Identifier && receiver.property.name === field;
|
|
4701
4885
|
}
|
|
4702
4886
|
function factoryAuthority(sourceCode, factory, contract, worker, implementation) {
|
|
4703
4887
|
const parameter = factory.params[0];
|
|
4704
|
-
if (parameter?.type !==
|
|
4888
|
+
if (parameter?.type !== AST_NODE_TYPES32.Identifier || parameter.optional || !typeReference(sourceCode, parameter.typeAnnotation, worker) || !typeReference(sourceCode, factory.returnType, contract))
|
|
4705
4889
|
return false;
|
|
4706
4890
|
const statement = factory.body.body[0];
|
|
4707
|
-
const constructed = statement?.type ===
|
|
4708
|
-
if (constructed?.type !==
|
|
4891
|
+
const constructed = statement?.type === AST_NODE_TYPES32.ReturnStatement ? statement.argument : null;
|
|
4892
|
+
if (constructed?.type !== AST_NODE_TYPES32.NewExpression || constructed.typeArguments !== void 0 || constructed.callee.type !== AST_NODE_TYPES32.Identifier || !sameBinding(sourceCode, constructed.callee, implementation) || constructed.arguments.length !== 1)
|
|
4709
4893
|
return false;
|
|
4710
4894
|
const argument = constructed.arguments[0];
|
|
4711
|
-
return argument?.type ===
|
|
4895
|
+
return argument?.type === AST_NODE_TYPES32.Identifier && argument.name === parameter.name && sameBinding(sourceCode, argument, factory);
|
|
4712
4896
|
}
|
|
4713
4897
|
|
|
4714
4898
|
// src/rules/require-port-for-service.ts
|
|
4715
4899
|
import {
|
|
4716
|
-
ASTUtils as
|
|
4717
|
-
AST_NODE_TYPES as
|
|
4900
|
+
ASTUtils as ASTUtils21,
|
|
4901
|
+
AST_NODE_TYPES as AST_NODE_TYPES33
|
|
4718
4902
|
} from "@typescript-eslint/utils";
|
|
4719
4903
|
var REQUIRE_PORT_FOR_SERVICE_DOCUMENTATION = {
|
|
4720
4904
|
summary: "Advise when an exported service with injected collaborators has public methods not covered by its declared ports.",
|
|
@@ -4799,50 +4983,50 @@ var STORAGE_ASSIGNMENT_OPERATORS = /* @__PURE__ */ new Set([
|
|
|
4799
4983
|
"||="
|
|
4800
4984
|
]);
|
|
4801
4985
|
var staticMemberName = (member3) => {
|
|
4802
|
-
if (member3.property.type ===
|
|
4986
|
+
if (member3.property.type === AST_NODE_TYPES33.PrivateIdentifier)
|
|
4803
4987
|
return `#${member3.property.name}`;
|
|
4804
|
-
return
|
|
4988
|
+
return ASTUtils21.getPropertyName(member3);
|
|
4805
4989
|
};
|
|
4806
4990
|
var detachedValueExports = (program) => {
|
|
4807
4991
|
const names = /* @__PURE__ */ new Set();
|
|
4808
4992
|
for (const statement of program.body) {
|
|
4809
|
-
if (statement.type ===
|
|
4993
|
+
if (statement.type === AST_NODE_TYPES33.ExportNamedDeclaration && statement.declaration === null && statement.source === null && statement.exportKind !== "type") {
|
|
4810
4994
|
for (const specifier of statement.specifiers) {
|
|
4811
4995
|
if (specifier.exportKind !== "type") names.add(specifier.local.name);
|
|
4812
4996
|
}
|
|
4813
|
-
} else if (statement.type ===
|
|
4997
|
+
} else if (statement.type === AST_NODE_TYPES33.ExportDefaultDeclaration && statement.declaration.type === AST_NODE_TYPES33.Identifier) {
|
|
4814
4998
|
names.add(statement.declaration.name);
|
|
4815
|
-
} else if (statement.type ===
|
|
4999
|
+
} else if (statement.type === AST_NODE_TYPES33.TSExportAssignment && statement.expression.type === AST_NODE_TYPES33.Identifier) {
|
|
4816
5000
|
names.add(statement.expression.name);
|
|
4817
5001
|
}
|
|
4818
5002
|
}
|
|
4819
5003
|
return names;
|
|
4820
5004
|
};
|
|
4821
|
-
var isExportedClass = (node, detached) => node.parent.type ===
|
|
5005
|
+
var isExportedClass = (node, detached) => node.parent.type === AST_NODE_TYPES33.ExportNamedDeclaration || node.parent.type === AST_NODE_TYPES33.ExportDefaultDeclaration || node.id !== null && detached.has(node.id.name);
|
|
4822
5006
|
var createExportedServiceClassResolver = (program) => {
|
|
4823
5007
|
const detached = detachedValueExports(program);
|
|
4824
5008
|
return (node) => isExportedClass(node, detached);
|
|
4825
5009
|
};
|
|
4826
5010
|
var readTypeReference = (annotation) => {
|
|
4827
|
-
if (annotation?.type ===
|
|
5011
|
+
if (annotation?.type === AST_NODE_TYPES33.TSUnionType) {
|
|
4828
5012
|
const members = annotation.types.filter(
|
|
4829
|
-
(member3) => member3.type !==
|
|
5013
|
+
(member3) => member3.type !== AST_NODE_TYPES33.TSUndefinedKeyword && member3.type !== AST_NODE_TYPES33.TSNullKeyword
|
|
4830
5014
|
);
|
|
4831
5015
|
annotation = members.length === 1 ? members[0] : void 0;
|
|
4832
5016
|
}
|
|
4833
|
-
if (annotation === void 0 || annotation.type !==
|
|
5017
|
+
if (annotation === void 0 || annotation.type !== AST_NODE_TYPES33.TSTypeReference)
|
|
4834
5018
|
return null;
|
|
4835
5019
|
const { typeName } = annotation;
|
|
4836
|
-
const rightmost = typeName.type ===
|
|
5020
|
+
const rightmost = typeName.type === AST_NODE_TYPES33.Identifier ? typeName.name : typeName.type === AST_NODE_TYPES33.TSQualifiedName ? typeName.right.name : null;
|
|
4837
5021
|
if (rightmost === null) return null;
|
|
4838
5022
|
return { typeName: rightmost, display: qualifiedName(typeName) };
|
|
4839
5023
|
};
|
|
4840
|
-
var qualifiedName = (name) => name.type ===
|
|
5024
|
+
var qualifiedName = (name) => name.type === AST_NODE_TYPES33.Identifier ? name.name : name.type === AST_NODE_TYPES33.TSQualifiedName ? `${qualifiedName(name.left)}.${name.right.name}` : "";
|
|
4841
5025
|
var propertySignatureTypes = (members) => {
|
|
4842
5026
|
const types = /* @__PURE__ */ new Map();
|
|
4843
5027
|
for (const member3 of members) {
|
|
4844
|
-
if (member3.type !==
|
|
4845
|
-
if (member3.computed || member3.key.type !==
|
|
5028
|
+
if (member3.type !== AST_NODE_TYPES33.TSPropertySignature) continue;
|
|
5029
|
+
if (member3.computed || member3.key.type !== AST_NODE_TYPES33.Identifier)
|
|
4846
5030
|
continue;
|
|
4847
5031
|
const reference = readTypeReference(member3.typeAnnotation?.typeAnnotation);
|
|
4848
5032
|
if (reference === null) continue;
|
|
@@ -4854,18 +5038,18 @@ var fileTypeIndex = (program) => {
|
|
|
4854
5038
|
const objects = /* @__PURE__ */ new Map();
|
|
4855
5039
|
const functionAliases = localFunctionAliases(program);
|
|
4856
5040
|
function collectDeclaredType(statement) {
|
|
4857
|
-
const declaration = statement.type ===
|
|
4858
|
-
if (declaration?.type ===
|
|
5041
|
+
const declaration = statement.type === AST_NODE_TYPES33.ExportNamedDeclaration ? statement.declaration : statement;
|
|
5042
|
+
if (declaration?.type === AST_NODE_TYPES33.TSInterfaceDeclaration) {
|
|
4859
5043
|
objects.set(
|
|
4860
5044
|
declaration.id.name,
|
|
4861
5045
|
propertySignatureTypes(declaration.body.body)
|
|
4862
5046
|
);
|
|
4863
5047
|
return;
|
|
4864
5048
|
}
|
|
4865
|
-
if (declaration?.type !==
|
|
5049
|
+
if (declaration?.type !== AST_NODE_TYPES33.TSTypeAliasDeclaration) return;
|
|
4866
5050
|
const aliased = declaration.typeAnnotation;
|
|
4867
|
-
const literals = aliased.type ===
|
|
4868
|
-
(part) => part.type ===
|
|
5051
|
+
const literals = aliased.type === AST_NODE_TYPES33.TSTypeLiteral ? [aliased] : aliased.type === AST_NODE_TYPES33.TSIntersectionType ? aliased.types.filter(
|
|
5052
|
+
(part) => part.type === AST_NODE_TYPES33.TSTypeLiteral
|
|
4869
5053
|
) : [];
|
|
4870
5054
|
if (literals.length === 0) return;
|
|
4871
5055
|
const merged = /* @__PURE__ */ new Map();
|
|
@@ -4885,12 +5069,12 @@ function localFunctionAliases(program) {
|
|
|
4885
5069
|
const names = /* @__PURE__ */ new Set();
|
|
4886
5070
|
const parents = /* @__PURE__ */ new Map();
|
|
4887
5071
|
for (const statement of program.body) {
|
|
4888
|
-
const declaration = statement.type ===
|
|
4889
|
-
if (declaration?.type !==
|
|
5072
|
+
const declaration = statement.type === AST_NODE_TYPES33.ExportNamedDeclaration ? statement.declaration : statement;
|
|
5073
|
+
if (declaration?.type !== AST_NODE_TYPES33.TSTypeAliasDeclaration) continue;
|
|
4890
5074
|
const annotation = declaration.typeAnnotation;
|
|
4891
|
-
if (annotation.type ===
|
|
5075
|
+
if (annotation.type === AST_NODE_TYPES33.TSFunctionType || annotation.type === AST_NODE_TYPES33.TSConstructorType)
|
|
4892
5076
|
names.add(declaration.id.name);
|
|
4893
|
-
if (annotation.type ===
|
|
5077
|
+
if (annotation.type === AST_NODE_TYPES33.TSTypeReference && annotation.typeName.type === AST_NODE_TYPES33.Identifier)
|
|
4894
5078
|
parents.set(declaration.id.name, annotation.typeName.name);
|
|
4895
5079
|
}
|
|
4896
5080
|
for (let pass = 0; pass < parents.size; pass += 1) {
|
|
@@ -4926,32 +5110,32 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
4926
5110
|
function scanStoredFields(body4) {
|
|
4927
5111
|
const pending = [...body4.body];
|
|
4928
5112
|
function recordStoredField(current) {
|
|
4929
|
-
if (current.type ===
|
|
5113
|
+
if (current.type === AST_NODE_TYPES33.ArrowFunctionExpression || current.type === AST_NODE_TYPES33.FunctionExpression || current.type === AST_NODE_TYPES33.FunctionDeclaration || current.type === AST_NODE_TYPES33.ClassExpression || current.type === AST_NODE_TYPES33.ClassDeclaration)
|
|
4930
5114
|
return;
|
|
4931
|
-
if (current.type ===
|
|
5115
|
+
if (current.type === AST_NODE_TYPES33.VariableDeclarator && current.id.type === AST_NODE_TYPES33.Identifier)
|
|
4932
5116
|
localBindings2.add(current.id.name);
|
|
4933
|
-
const expression = current.type ===
|
|
5117
|
+
const expression = current.type === AST_NODE_TYPES33.AssignmentExpression ? current : null;
|
|
4934
5118
|
const storedField = writtenInstanceField(current);
|
|
4935
5119
|
if (storedField !== null) {
|
|
4936
5120
|
if (writtenFieldNames.has(storedField))
|
|
4937
5121
|
unstableFieldNames.add(storedField);
|
|
4938
5122
|
writtenFieldNames.add(storedField);
|
|
4939
|
-
if (expression?.operator !== "=" || expression.parent.type !==
|
|
5123
|
+
if (expression?.operator !== "=" || expression.parent.type !== AST_NODE_TYPES33.ExpressionStatement || expression.parent.parent !== body4)
|
|
4940
5124
|
unstableFieldNames.add(storedField);
|
|
4941
5125
|
}
|
|
4942
|
-
if (expression?.type !==
|
|
5126
|
+
if (expression?.type !== AST_NODE_TYPES33.AssignmentExpression || !STORAGE_ASSIGNMENT_OPERATORS.has(expression.operator) || expression.left.type !== AST_NODE_TYPES33.MemberExpression || expression.left.object.type !== AST_NODE_TYPES33.ThisExpression || storedField === null) {
|
|
4943
5127
|
enqueueChildren(current);
|
|
4944
5128
|
return;
|
|
4945
5129
|
}
|
|
4946
5130
|
const source = unwrapExpression(expression.right);
|
|
4947
|
-
if (source.type ===
|
|
5131
|
+
if (source.type === AST_NODE_TYPES33.NewExpression) {
|
|
4948
5132
|
constructedFields += 1;
|
|
4949
5133
|
constructedFieldNames.add(storedField);
|
|
4950
|
-
} else if (source.type ===
|
|
5134
|
+
} else if (source.type === AST_NODE_TYPES33.Identifier) {
|
|
4951
5135
|
const fields2 = storedFieldsFrom.get(source.name) ?? /* @__PURE__ */ new Set();
|
|
4952
5136
|
fields2.add(storedField);
|
|
4953
5137
|
storedFieldsFrom.set(source.name, fields2);
|
|
4954
|
-
} else if (source.type ===
|
|
5138
|
+
} else if (source.type === AST_NODE_TYPES33.MemberExpression && source.object.type === AST_NODE_TYPES33.Identifier) {
|
|
4955
5139
|
const fields2 = storedFieldsFrom.get(source.object.name) ?? /* @__PURE__ */ new Set();
|
|
4956
5140
|
fields2.add(storedField);
|
|
4957
5141
|
storedFieldsFrom.set(source.object.name, fields2);
|
|
@@ -4986,7 +5170,7 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
4986
5170
|
)) {
|
|
4987
5171
|
if (localBindings2.has(reference.name)) continue;
|
|
4988
5172
|
let fields2 = reference.fields;
|
|
4989
|
-
if (parameter.type ===
|
|
5173
|
+
if (parameter.type === AST_NODE_TYPES33.TSParameterProperty) {
|
|
4990
5174
|
if (writtenFieldNames.has(reference.name)) continue;
|
|
4991
5175
|
fields2 = [reference.name];
|
|
4992
5176
|
} else if (fields2.length === 0)
|
|
@@ -5009,8 +5193,8 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
5009
5193
|
};
|
|
5010
5194
|
var parameterCollaborators = (parameter, declared, storedMemberFieldsFrom) => {
|
|
5011
5195
|
let target = parameter;
|
|
5012
|
-
if (target.type ===
|
|
5013
|
-
if (target.type ===
|
|
5196
|
+
if (target.type === AST_NODE_TYPES33.AssignmentPattern) target = target.left;
|
|
5197
|
+
if (target.type === AST_NODE_TYPES33.ObjectPattern) {
|
|
5014
5198
|
return objectPatternCollaborators(target, declared);
|
|
5015
5199
|
}
|
|
5016
5200
|
const named3 = namedParameterCollaborator(parameter);
|
|
@@ -5020,10 +5204,10 @@ var parameterCollaborators = (parameter, declared, storedMemberFieldsFrom) => {
|
|
|
5020
5204
|
};
|
|
5021
5205
|
var namedBagCollaborators = (annotated, declared, storedMemberFieldsFrom) => {
|
|
5022
5206
|
let target = annotated;
|
|
5023
|
-
if (target.type ===
|
|
5207
|
+
if (target.type === AST_NODE_TYPES33.TSParameterProperty)
|
|
5024
5208
|
target = target.parameter;
|
|
5025
|
-
if (target.type ===
|
|
5026
|
-
if (target.type !==
|
|
5209
|
+
if (target.type === AST_NODE_TYPES33.AssignmentPattern) target = target.left;
|
|
5210
|
+
if (target.type !== AST_NODE_TYPES33.Identifier) return [];
|
|
5027
5211
|
const members = bagMemberTypes(
|
|
5028
5212
|
target.typeAnnotation?.typeAnnotation,
|
|
5029
5213
|
declared
|
|
@@ -5042,10 +5226,10 @@ var namedBagCollaborators = (annotated, declared, storedMemberFieldsFrom) => {
|
|
|
5042
5226
|
};
|
|
5043
5227
|
var namedParameterCollaborator = (annotated) => {
|
|
5044
5228
|
let target = annotated;
|
|
5045
|
-
if (target.type ===
|
|
5229
|
+
if (target.type === AST_NODE_TYPES33.TSParameterProperty)
|
|
5046
5230
|
target = target.parameter;
|
|
5047
|
-
if (target.type ===
|
|
5048
|
-
if (target.type !==
|
|
5231
|
+
if (target.type === AST_NODE_TYPES33.AssignmentPattern) target = target.left;
|
|
5232
|
+
if (target.type !== AST_NODE_TYPES33.Identifier) return null;
|
|
5049
5233
|
const reference = readTypeReference(target.typeAnnotation?.typeAnnotation);
|
|
5050
5234
|
if (reference === null) return null;
|
|
5051
5235
|
return { name: target.name, ...reference, fields: [] };
|
|
@@ -5057,12 +5241,12 @@ var objectPatternCollaborators = (pattern, declared) => {
|
|
|
5057
5241
|
if (members === null) return [];
|
|
5058
5242
|
const collaborators = [];
|
|
5059
5243
|
for (const property of pattern.properties) {
|
|
5060
|
-
if (property.type !==
|
|
5244
|
+
if (property.type !== AST_NODE_TYPES33.Property || property.computed)
|
|
5061
5245
|
continue;
|
|
5062
|
-
if (property.key.type !==
|
|
5246
|
+
if (property.key.type !== AST_NODE_TYPES33.Identifier) continue;
|
|
5063
5247
|
const key = property.key.name;
|
|
5064
|
-
const bound = property.value.type ===
|
|
5065
|
-
if (bound.type !==
|
|
5248
|
+
const bound = property.value.type === AST_NODE_TYPES33.AssignmentPattern ? property.value.left : property.value;
|
|
5249
|
+
if (bound.type !== AST_NODE_TYPES33.Identifier) continue;
|
|
5066
5250
|
if (CONFIGISH_NAME_RE.test(key)) continue;
|
|
5067
5251
|
const reference = members.get(key);
|
|
5068
5252
|
if (reference === void 0) continue;
|
|
@@ -5072,22 +5256,22 @@ var objectPatternCollaborators = (pattern, declared) => {
|
|
|
5072
5256
|
};
|
|
5073
5257
|
var bagMemberTypes = (annotation, declared) => {
|
|
5074
5258
|
if (annotation === void 0) return null;
|
|
5075
|
-
if (annotation.type ===
|
|
5259
|
+
if (annotation.type === AST_NODE_TYPES33.TSTypeLiteral) {
|
|
5076
5260
|
return propertySignatureTypes(annotation.members);
|
|
5077
5261
|
}
|
|
5078
|
-
if (annotation.type !==
|
|
5262
|
+
if (annotation.type !== AST_NODE_TYPES33.TSTypeReference || annotation.typeName.type !== AST_NODE_TYPES33.Identifier) {
|
|
5079
5263
|
return null;
|
|
5080
5264
|
}
|
|
5081
5265
|
return declared().objects.get(annotation.typeName.name) ?? null;
|
|
5082
5266
|
};
|
|
5083
5267
|
var isFrameworkWiring = (body3) => subtreeHas(body3, (node) => {
|
|
5084
|
-
if (node.type ===
|
|
5268
|
+
if (node.type === AST_NODE_TYPES33.CallExpression) {
|
|
5085
5269
|
const { callee } = node;
|
|
5086
|
-
if (callee.type ===
|
|
5270
|
+
if (callee.type === AST_NODE_TYPES33.Identifier)
|
|
5087
5271
|
return callee.name === ROUTER_FACTORY_NAME;
|
|
5088
|
-
return callee.type ===
|
|
5272
|
+
return callee.type === AST_NODE_TYPES33.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES33.Identifier && callee.property.name === ROUTER_FACTORY_NAME;
|
|
5089
5273
|
}
|
|
5090
|
-
return node.type ===
|
|
5274
|
+
return node.type === AST_NODE_TYPES33.TSTypeReference && node.typeName.type === AST_NODE_TYPES33.TSQualifiedName && FRAMEWORK_HTTP_TYPES.has(node.typeName.right.name);
|
|
5091
5275
|
});
|
|
5092
5276
|
var subtreeHas = (root, found) => {
|
|
5093
5277
|
let hit = false;
|
|
@@ -5107,26 +5291,26 @@ var subtreeHas = (root, found) => {
|
|
|
5107
5291
|
};
|
|
5108
5292
|
var invokedInstanceField = (call) => {
|
|
5109
5293
|
let callee = unwrapExpression(call.callee);
|
|
5110
|
-
while (callee.type ===
|
|
5294
|
+
while (callee.type === AST_NODE_TYPES33.ChainExpression)
|
|
5111
5295
|
callee = unwrapExpression(callee.expression);
|
|
5112
5296
|
const direct = instanceField(callee);
|
|
5113
5297
|
if (direct !== null) return direct;
|
|
5114
|
-
return callee.type ===
|
|
5298
|
+
return callee.type === AST_NODE_TYPES33.MemberExpression ? instanceField(unwrapExpression(callee.object)) : null;
|
|
5115
5299
|
};
|
|
5116
5300
|
var instanceField = (candidate2) => {
|
|
5117
5301
|
let node = candidate2;
|
|
5118
|
-
while (node.type ===
|
|
5302
|
+
while (node.type === AST_NODE_TYPES33.ChainExpression || node.type === AST_NODE_TYPES33.TSAsExpression || node.type === AST_NODE_TYPES33.TSNonNullExpression || node.type === AST_NODE_TYPES33.TSSatisfiesExpression || node.type === AST_NODE_TYPES33.TSTypeAssertion)
|
|
5119
5303
|
node = node.expression;
|
|
5120
|
-
return node.type ===
|
|
5304
|
+
return node.type === AST_NODE_TYPES33.MemberExpression && node.object.type === AST_NODE_TYPES33.ThisExpression ? staticMemberName(node) : null;
|
|
5121
5305
|
};
|
|
5122
5306
|
function writtenInstanceField(node) {
|
|
5123
|
-
if (node.type ===
|
|
5307
|
+
if (node.type === AST_NODE_TYPES33.AssignmentExpression || node.type === AST_NODE_TYPES33.ForOfStatement || node.type === AST_NODE_TYPES33.ForInStatement)
|
|
5124
5308
|
return instanceField(node.left);
|
|
5125
|
-
if (node.type ===
|
|
5309
|
+
if (node.type === AST_NODE_TYPES33.UpdateExpression)
|
|
5126
5310
|
return instanceField(node.argument);
|
|
5127
|
-
if (node.type ===
|
|
5311
|
+
if (node.type === AST_NODE_TYPES33.UnaryExpression && node.operator === "delete")
|
|
5128
5312
|
return instanceField(node.argument);
|
|
5129
|
-
if (node.type ===
|
|
5313
|
+
if (node.type === AST_NODE_TYPES33.MemberExpression && isDestructuredWriteTarget(node))
|
|
5130
5314
|
return instanceField(node);
|
|
5131
5315
|
return null;
|
|
5132
5316
|
}
|
|
@@ -5135,39 +5319,39 @@ function isDestructuredWriteTarget(node) {
|
|
|
5135
5319
|
let target = access;
|
|
5136
5320
|
for (; ; ) {
|
|
5137
5321
|
const parent = target.parent;
|
|
5138
|
-
if (parent.type ===
|
|
5322
|
+
if (parent.type === AST_NODE_TYPES33.Property && parent.value === target && parent.parent.type === AST_NODE_TYPES33.ObjectPattern) {
|
|
5139
5323
|
target = parent.parent;
|
|
5140
5324
|
continue;
|
|
5141
5325
|
}
|
|
5142
|
-
if (parent.type ===
|
|
5326
|
+
if (parent.type === AST_NODE_TYPES33.ArrayPattern || parent.type === AST_NODE_TYPES33.ObjectPattern || parent.type === AST_NODE_TYPES33.RestElement && parent.argument === target || parent.type === AST_NODE_TYPES33.AssignmentPattern && parent.left === target) {
|
|
5143
5327
|
target = parent;
|
|
5144
5328
|
continue;
|
|
5145
5329
|
}
|
|
5146
|
-
return target !== access && (parent.type ===
|
|
5330
|
+
return target !== access && (parent.type === AST_NODE_TYPES33.AssignmentExpression || parent.type === AST_NODE_TYPES33.ForOfStatement || parent.type === AST_NODE_TYPES33.ForInStatement) && parent.left === target;
|
|
5147
5331
|
}
|
|
5148
5332
|
}
|
|
5149
5333
|
var behaviorallyInvokedFields = (body3) => {
|
|
5150
5334
|
const invoked = /* @__PURE__ */ new Set();
|
|
5151
5335
|
const visit = (current) => {
|
|
5152
|
-
if (current.type ===
|
|
5336
|
+
if (current.type === AST_NODE_TYPES33.ClassDeclaration || current.type === AST_NODE_TYPES33.ClassExpression || current.type === AST_NODE_TYPES33.FunctionDeclaration || current.type === AST_NODE_TYPES33.FunctionExpression)
|
|
5153
5337
|
return;
|
|
5154
|
-
if (current.type ===
|
|
5338
|
+
if (current.type === AST_NODE_TYPES33.CallExpression) {
|
|
5155
5339
|
const field = invokedInstanceField(current);
|
|
5156
5340
|
if (field !== null) invoked.add(field);
|
|
5157
5341
|
}
|
|
5158
5342
|
forEachOwnAstChild(current, visit);
|
|
5159
5343
|
};
|
|
5160
5344
|
for (const member3 of body3.body) {
|
|
5161
|
-
if (member3.type ===
|
|
5162
|
-
if (member3.type ===
|
|
5345
|
+
if (member3.type === AST_NODE_TYPES33.StaticBlock || member3.static) continue;
|
|
5346
|
+
if (member3.type === AST_NODE_TYPES33.MethodDefinition) {
|
|
5163
5347
|
if (member3.value.body !== null && member3.value.body !== void 0)
|
|
5164
5348
|
visit(member3.value.body);
|
|
5165
5349
|
continue;
|
|
5166
5350
|
}
|
|
5167
|
-
if (member3.type !==
|
|
5351
|
+
if (member3.type !== AST_NODE_TYPES33.PropertyDefinition || member3.value === null)
|
|
5168
5352
|
continue;
|
|
5169
5353
|
visit(
|
|
5170
|
-
member3.value.type ===
|
|
5354
|
+
member3.value.type === AST_NODE_TYPES33.ArrowFunctionExpression ? member3.value.body : member3.value
|
|
5171
5355
|
);
|
|
5172
5356
|
}
|
|
5173
5357
|
return invoked;
|
|
@@ -5187,8 +5371,8 @@ var isTransportWrapper = (className, collaborators, program) => {
|
|
|
5187
5371
|
var fileInterfaceNames = (program) => {
|
|
5188
5372
|
const names = [];
|
|
5189
5373
|
for (const statement of program.body) {
|
|
5190
|
-
const declaration = statement.type ===
|
|
5191
|
-
if (declaration?.type ===
|
|
5374
|
+
const declaration = statement.type === AST_NODE_TYPES33.ExportNamedDeclaration ? statement.declaration : statement;
|
|
5375
|
+
if (declaration?.type === AST_NODE_TYPES33.TSInterfaceDeclaration)
|
|
5192
5376
|
names.push(declaration.id.name);
|
|
5193
5377
|
}
|
|
5194
5378
|
return names;
|
|
@@ -5196,22 +5380,22 @@ var fileInterfaceNames = (program) => {
|
|
|
5196
5380
|
var publicMethodNames = (body3, functionAliases) => {
|
|
5197
5381
|
const names = [];
|
|
5198
5382
|
function collectPublicCallable(member3) {
|
|
5199
|
-
if (member3.type ===
|
|
5383
|
+
if (member3.type === AST_NODE_TYPES33.PropertyDefinition) {
|
|
5200
5384
|
if (member3.static || member3.accessibility === "private" || member3.accessibility === "protected")
|
|
5201
5385
|
return;
|
|
5202
|
-
if (member3.key.type ===
|
|
5203
|
-
if (member3.value?.type !==
|
|
5386
|
+
if (member3.key.type === AST_NODE_TYPES33.PrivateIdentifier) return;
|
|
5387
|
+
if (member3.value?.type !== AST_NODE_TYPES33.ArrowFunctionExpression && member3.value?.type !== AST_NODE_TYPES33.FunctionExpression && member3.typeAnnotation?.typeAnnotation.type !== AST_NODE_TYPES33.TSFunctionType && !(member3.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES33.TSTypeReference && member3.typeAnnotation.typeAnnotation.typeName.type === AST_NODE_TYPES33.Identifier && functionAliases.has(
|
|
5204
5388
|
member3.typeAnnotation.typeAnnotation.typeName.name
|
|
5205
5389
|
)))
|
|
5206
5390
|
return;
|
|
5207
5391
|
names.push(declaredMemberName(member3) ?? "\u2026");
|
|
5208
5392
|
return;
|
|
5209
5393
|
}
|
|
5210
|
-
if (member3.type !==
|
|
5394
|
+
if (member3.type !== AST_NODE_TYPES33.MethodDefinition) return;
|
|
5211
5395
|
if (member3.kind !== "method" || member3.static) return;
|
|
5212
5396
|
if (member3.accessibility === "private" || member3.accessibility === "protected")
|
|
5213
5397
|
return;
|
|
5214
|
-
if (member3.key.type ===
|
|
5398
|
+
if (member3.key.type === AST_NODE_TYPES33.PrivateIdentifier) return;
|
|
5215
5399
|
names.push(declaredMemberName(member3) ?? "\u2026");
|
|
5216
5400
|
}
|
|
5217
5401
|
for (const member3 of body3.body) {
|
|
@@ -5222,13 +5406,13 @@ var publicMethodNames = (body3, functionAliases) => {
|
|
|
5222
5406
|
var isFluentConstructionObject = (node, getText) => {
|
|
5223
5407
|
if (node.id === null) return false;
|
|
5224
5408
|
const methods = node.body.body.filter(
|
|
5225
|
-
(member3) => member3.type ===
|
|
5409
|
+
(member3) => member3.type === AST_NODE_TYPES33.MethodDefinition && member3.kind === "method" && !member3.static && member3.accessibility !== "private" && member3.accessibility !== "protected" && member3.value.body !== null
|
|
5226
5410
|
);
|
|
5227
5411
|
if (methods.length === 0) return false;
|
|
5228
5412
|
return methods.every((member3) => {
|
|
5229
5413
|
const result = member3.value.returnType?.typeAnnotation;
|
|
5230
5414
|
if (result === void 0) return false;
|
|
5231
|
-
const returnsOwnType = result.type ===
|
|
5415
|
+
const returnsOwnType = result.type === AST_NODE_TYPES33.TSTypeReference && result.typeName.type === AST_NODE_TYPES33.Identifier && result.typeName.name === node.id?.name;
|
|
5232
5416
|
return returnsOwnType || FLUENT_BUILDER_NAME_RE.test(node.id?.name ?? "") && FLUENT_RESULT_TYPE_RE.test(getText(result));
|
|
5233
5417
|
});
|
|
5234
5418
|
};
|
|
@@ -5236,10 +5420,10 @@ function localClassAbstractness(program) {
|
|
|
5236
5420
|
const classes = /* @__PURE__ */ new Map();
|
|
5237
5421
|
const parents = /* @__PURE__ */ new Map();
|
|
5238
5422
|
for (const statement of program.body) {
|
|
5239
|
-
const declaration = statement.type ===
|
|
5240
|
-
if (declaration?.type ===
|
|
5423
|
+
const declaration = statement.type === AST_NODE_TYPES33.ExportNamedDeclaration || statement.type === AST_NODE_TYPES33.ExportDefaultDeclaration ? statement.declaration : statement;
|
|
5424
|
+
if (declaration?.type === AST_NODE_TYPES33.ClassDeclaration && declaration.id !== null) {
|
|
5241
5425
|
classes.set(declaration.id.name, declaration.abstract === true);
|
|
5242
|
-
if (declaration.superClass?.type ===
|
|
5426
|
+
if (declaration.superClass?.type === AST_NODE_TYPES33.Identifier) {
|
|
5243
5427
|
parents.set(declaration.id.name, declaration.superClass.name);
|
|
5244
5428
|
}
|
|
5245
5429
|
}
|
|
@@ -5257,9 +5441,9 @@ function localClassAbstractness(program) {
|
|
|
5257
5441
|
return classes;
|
|
5258
5442
|
}
|
|
5259
5443
|
function declaredMemberName(member3) {
|
|
5260
|
-
if (!member3.computed && member3.key.type ===
|
|
5444
|
+
if (!member3.computed && member3.key.type === AST_NODE_TYPES33.Identifier)
|
|
5261
5445
|
return member3.key.name;
|
|
5262
|
-
if (member3.key.type ===
|
|
5446
|
+
if (member3.key.type === AST_NODE_TYPES33.Literal && typeof member3.key.value === "string")
|
|
5263
5447
|
return member3.key.value;
|
|
5264
5448
|
return null;
|
|
5265
5449
|
}
|
|
@@ -5268,35 +5452,35 @@ function localInterfaceSurfaces(program) {
|
|
|
5268
5452
|
const parents = /* @__PURE__ */ new Map();
|
|
5269
5453
|
const functionAliases = localFunctionAliases(program);
|
|
5270
5454
|
function collectInterfaceSurface(statement) {
|
|
5271
|
-
const declaration = statement.type ===
|
|
5272
|
-
if (declaration?.type ===
|
|
5455
|
+
const declaration = statement.type === AST_NODE_TYPES33.ExportNamedDeclaration ? statement.declaration : statement;
|
|
5456
|
+
if (declaration?.type === AST_NODE_TYPES33.TSTypeAliasDeclaration) {
|
|
5273
5457
|
const callables2 = interfaces.get(declaration.id.name) ?? /* @__PURE__ */ new Set();
|
|
5274
|
-
const parts = declaration.typeAnnotation.type ===
|
|
5458
|
+
const parts = declaration.typeAnnotation.type === AST_NODE_TYPES33.TSIntersectionType ? declaration.typeAnnotation.types : [declaration.typeAnnotation];
|
|
5275
5459
|
const inherited = parents.get(declaration.id.name) ?? [];
|
|
5276
5460
|
for (const part of parts) {
|
|
5277
|
-
if (part.type ===
|
|
5461
|
+
if (part.type === AST_NODE_TYPES33.TSTypeReference && part.typeName.type === AST_NODE_TYPES33.Identifier) {
|
|
5278
5462
|
inherited.push(part.typeName.name);
|
|
5279
5463
|
continue;
|
|
5280
5464
|
}
|
|
5281
|
-
if (part.type ===
|
|
5465
|
+
if (part.type === AST_NODE_TYPES33.TSTypeReference) {
|
|
5282
5466
|
inherited.push("*");
|
|
5283
5467
|
continue;
|
|
5284
5468
|
}
|
|
5285
|
-
if (part.type !==
|
|
5469
|
+
if (part.type !== AST_NODE_TYPES33.TSTypeLiteral) continue;
|
|
5286
5470
|
addCallableMembers(part.members, callables2);
|
|
5287
5471
|
}
|
|
5288
5472
|
interfaces.set(declaration.id.name, callables2);
|
|
5289
5473
|
parents.set(declaration.id.name, inherited);
|
|
5290
5474
|
return;
|
|
5291
5475
|
}
|
|
5292
|
-
if (declaration?.type !==
|
|
5476
|
+
if (declaration?.type !== AST_NODE_TYPES33.TSInterfaceDeclaration) return;
|
|
5293
5477
|
const callables = interfaces.get(declaration.id.name) ?? /* @__PURE__ */ new Set();
|
|
5294
5478
|
addCallableMembers(declaration.body.body, callables);
|
|
5295
5479
|
interfaces.set(declaration.id.name, callables);
|
|
5296
5480
|
parents.set(declaration.id.name, [
|
|
5297
5481
|
...parents.get(declaration.id.name) ?? [],
|
|
5298
5482
|
...declaration.extends.flatMap(
|
|
5299
|
-
(heritage) => heritage.expression.type ===
|
|
5483
|
+
(heritage) => heritage.expression.type === AST_NODE_TYPES33.Identifier ? [heritage.expression.name] : ["*"]
|
|
5300
5484
|
)
|
|
5301
5485
|
]);
|
|
5302
5486
|
}
|
|
@@ -5305,17 +5489,17 @@ function localInterfaceSurfaces(program) {
|
|
|
5305
5489
|
}
|
|
5306
5490
|
function addCallableMembers(members, callables) {
|
|
5307
5491
|
for (const member3 of members) {
|
|
5308
|
-
if (member3.type !==
|
|
5492
|
+
if (member3.type !== AST_NODE_TYPES33.TSMethodSignature && member3.type !== AST_NODE_TYPES33.TSPropertySignature)
|
|
5309
5493
|
continue;
|
|
5310
5494
|
const name = declaredMemberName(member3);
|
|
5311
5495
|
if (name === null) continue;
|
|
5312
|
-
if (member3.type ===
|
|
5496
|
+
if (member3.type === AST_NODE_TYPES33.TSMethodSignature) {
|
|
5313
5497
|
callables.add(name);
|
|
5314
5498
|
continue;
|
|
5315
5499
|
}
|
|
5316
|
-
if (member3.type !==
|
|
5500
|
+
if (member3.type !== AST_NODE_TYPES33.TSPropertySignature) continue;
|
|
5317
5501
|
const annotation = member3.typeAnnotation?.typeAnnotation;
|
|
5318
|
-
if (annotation?.type ===
|
|
5502
|
+
if (annotation?.type === AST_NODE_TYPES33.TSFunctionType || annotation?.type === AST_NODE_TYPES33.TSTypeReference && annotation.typeName.type === AST_NODE_TYPES33.Identifier && functionAliases.has(annotation.typeName.name))
|
|
5319
5503
|
callables.add(name);
|
|
5320
5504
|
}
|
|
5321
5505
|
}
|
|
@@ -5345,7 +5529,7 @@ function localInterfaceSurfaces(program) {
|
|
|
5345
5529
|
}
|
|
5346
5530
|
function hasServicePort(node, methods, classes, interfaces) {
|
|
5347
5531
|
if (node.superClass !== null) {
|
|
5348
|
-
if (node.superClass.type !==
|
|
5532
|
+
if (node.superClass.type !== AST_NODE_TYPES33.Identifier) return true;
|
|
5349
5533
|
const localAbstract = classes.get(node.superClass.name);
|
|
5350
5534
|
if (localAbstract === void 0 || localAbstract) return true;
|
|
5351
5535
|
}
|
|
@@ -5384,7 +5568,7 @@ var require_port_for_service_default = createRule({
|
|
|
5384
5568
|
if (node.abstract === true) return;
|
|
5385
5569
|
if (node.decorators.length > 0) return;
|
|
5386
5570
|
const ctor = node.body.body.find(
|
|
5387
|
-
(member3) => member3.type ===
|
|
5571
|
+
(member3) => member3.type === AST_NODE_TYPES33.MethodDefinition && member3.kind === "constructor" && member3.value.body !== null && member3.value.body !== void 0
|
|
5388
5572
|
);
|
|
5389
5573
|
if (ctor === void 0) return;
|
|
5390
5574
|
const constructorFacts = readConstructor(
|
|
@@ -5434,7 +5618,7 @@ var require_port_for_service_default = createRule({
|
|
|
5434
5618
|
function implementedSurfaceCovers(node, methods, classes, interfaces) {
|
|
5435
5619
|
const combined = /* @__PURE__ */ new Set();
|
|
5436
5620
|
for (const implementation of node.implements) {
|
|
5437
|
-
if (implementation.expression.type !==
|
|
5621
|
+
if (implementation.expression.type !== AST_NODE_TYPES33.Identifier)
|
|
5438
5622
|
return true;
|
|
5439
5623
|
const name = implementation.expression.name;
|
|
5440
5624
|
const localAbstract = classes.get(name);
|
|
@@ -5451,7 +5635,7 @@ function createServiceOperationResolver(program) {
|
|
|
5451
5635
|
let declaredTypes = null;
|
|
5452
5636
|
return (node) => {
|
|
5453
5637
|
const ctor = node.body.body.find(
|
|
5454
|
-
(member3) => member3.type ===
|
|
5638
|
+
(member3) => member3.type === AST_NODE_TYPES33.MethodDefinition && member3.kind === "constructor" && member3.value.body !== null
|
|
5455
5639
|
);
|
|
5456
5640
|
if (ctor === void 0) return [];
|
|
5457
5641
|
const declared = () => declaredTypes ??= fileTypeIndex(program);
|
|
@@ -5469,7 +5653,7 @@ function createServiceOperationResolver(program) {
|
|
|
5469
5653
|
for (const [name, body3] of serviceOperationBodies(node)) {
|
|
5470
5654
|
forEachServiceCall(body3, (call) => {
|
|
5471
5655
|
if (retained.has(invokedInstanceField(call) ?? "")) active.add(name);
|
|
5472
|
-
if (call.callee.type ===
|
|
5656
|
+
if (call.callee.type === AST_NODE_TYPES33.MemberExpression && call.callee.object.type === AST_NODE_TYPES33.ThisExpression) {
|
|
5473
5657
|
const callee = staticMemberName(call.callee);
|
|
5474
5658
|
if (callee !== null) {
|
|
5475
5659
|
const linked = callers.get(callee) ?? /* @__PURE__ */ new Set();
|
|
@@ -5508,11 +5692,11 @@ function serviceOperationBodies(node) {
|
|
|
5508
5692
|
});
|
|
5509
5693
|
}
|
|
5510
5694
|
for (const member3 of node.body.body) {
|
|
5511
|
-
if (member3.type !==
|
|
5695
|
+
if (member3.type !== AST_NODE_TYPES33.MethodDefinition && member3.type !== AST_NODE_TYPES33.PropertyDefinition)
|
|
5512
5696
|
continue;
|
|
5513
|
-
if (member3.static || member3.decorators.length > 0 || member3.type ===
|
|
5697
|
+
if (member3.static || member3.decorators.length > 0 || member3.type === AST_NODE_TYPES33.MethodDefinition && member3.kind !== "method")
|
|
5514
5698
|
continue;
|
|
5515
|
-
if (member3.value?.type !==
|
|
5699
|
+
if (member3.value?.type !== AST_NODE_TYPES33.FunctionExpression && member3.value?.type !== AST_NODE_TYPES33.ArrowFunctionExpression)
|
|
5516
5700
|
continue;
|
|
5517
5701
|
const name = declaredMemberName(member3);
|
|
5518
5702
|
if (name !== null && !written.has(name) && member3.value.body !== null)
|
|
@@ -5521,9 +5705,9 @@ function serviceOperationBodies(node) {
|
|
|
5521
5705
|
return bodies;
|
|
5522
5706
|
}
|
|
5523
5707
|
function forEachServiceCall(node, onCall) {
|
|
5524
|
-
if (node.type ===
|
|
5708
|
+
if (node.type === AST_NODE_TYPES33.FunctionDeclaration || node.type === AST_NODE_TYPES33.FunctionExpression || node.type === AST_NODE_TYPES33.ArrowFunctionExpression || node.type === AST_NODE_TYPES33.ClassDeclaration || node.type === AST_NODE_TYPES33.ClassExpression)
|
|
5525
5709
|
return;
|
|
5526
|
-
if (node.type ===
|
|
5710
|
+
if (node.type === AST_NODE_TYPES33.BlockStatement) {
|
|
5527
5711
|
for (const statement of node.body) {
|
|
5528
5712
|
forEachServiceCall(statement, onCall);
|
|
5529
5713
|
if (terminatesOperation(statement)) break;
|
|
@@ -5535,29 +5719,29 @@ function forEachServiceCall(node, onCall) {
|
|
|
5535
5719
|
forEachServiceCall(branch, onCall);
|
|
5536
5720
|
return;
|
|
5537
5721
|
}
|
|
5538
|
-
if (node.type ===
|
|
5722
|
+
if (node.type === AST_NODE_TYPES33.CallExpression) onCall(node);
|
|
5539
5723
|
forEachOwnAstChild(node, (child) => {
|
|
5540
5724
|
forEachServiceCall(child, onCall);
|
|
5541
5725
|
});
|
|
5542
5726
|
}
|
|
5543
5727
|
function literalExecutionBranch(node) {
|
|
5544
|
-
if (node.type ===
|
|
5728
|
+
if (node.type === AST_NODE_TYPES33.WhileStatement && node.test.type === AST_NODE_TYPES33.Literal && node.test.value === false)
|
|
5545
5729
|
return node.test;
|
|
5546
|
-
if ((node.type ===
|
|
5730
|
+
if ((node.type === AST_NODE_TYPES33.IfStatement || node.type === AST_NODE_TYPES33.ConditionalExpression) && node.test.type === AST_NODE_TYPES33.Literal && typeof node.test.value === "boolean") {
|
|
5547
5731
|
return node.test.value ? node.consequent : node.alternate ?? node.test;
|
|
5548
5732
|
}
|
|
5549
|
-
if (node.type !==
|
|
5733
|
+
if (node.type !== AST_NODE_TYPES33.LogicalExpression || node.left.type !== AST_NODE_TYPES33.Literal || typeof node.left.value !== "boolean")
|
|
5550
5734
|
return null;
|
|
5551
5735
|
if (node.operator === "&&") return node.left.value ? node.right : node.left;
|
|
5552
5736
|
if (node.operator === "||") return node.left.value ? node.left : node.right;
|
|
5553
5737
|
return node.left;
|
|
5554
5738
|
}
|
|
5555
5739
|
function terminatesOperation(node) {
|
|
5556
|
-
if (node.type ===
|
|
5740
|
+
if (node.type === AST_NODE_TYPES33.ReturnStatement || node.type === AST_NODE_TYPES33.ThrowStatement)
|
|
5557
5741
|
return true;
|
|
5558
|
-
if (node.type ===
|
|
5742
|
+
if (node.type === AST_NODE_TYPES33.BlockStatement)
|
|
5559
5743
|
return node.body.some(terminatesOperation);
|
|
5560
|
-
if (node.type !==
|
|
5744
|
+
if (node.type !== AST_NODE_TYPES33.IfStatement) return false;
|
|
5561
5745
|
const branch = literalExecutionBranch(node);
|
|
5562
5746
|
if (branch !== null) return terminatesOperation(branch);
|
|
5563
5747
|
return node.alternate !== null && terminatesOperation(node.consequent) && terminatesOperation(node.alternate);
|
|
@@ -5571,7 +5755,7 @@ function hasDeclaredServiceContract(node, operations, program) {
|
|
|
5571
5755
|
const seen = /* @__PURE__ */ new Set();
|
|
5572
5756
|
function addImplementedContracts(current) {
|
|
5573
5757
|
for (const implementation of current.implements) {
|
|
5574
|
-
if (implementation.expression.type !==
|
|
5758
|
+
if (implementation.expression.type !== AST_NODE_TYPES33.Identifier)
|
|
5575
5759
|
return false;
|
|
5576
5760
|
const name = implementation.expression.name;
|
|
5577
5761
|
const surface = interfaces.get(name);
|
|
@@ -5594,7 +5778,7 @@ function hasDeclaredServiceContract(node, operations, program) {
|
|
|
5594
5778
|
}
|
|
5595
5779
|
if (!addImplementedContracts(current)) return null;
|
|
5596
5780
|
if (current.superClass === null) continue;
|
|
5597
|
-
if (current.superClass.type !==
|
|
5781
|
+
if (current.superClass.type !== AST_NODE_TYPES33.Identifier) return null;
|
|
5598
5782
|
const base = classes.get(current.superClass.name);
|
|
5599
5783
|
if (base === void 0) return null;
|
|
5600
5784
|
pending.push(base);
|
|
@@ -5604,8 +5788,8 @@ function hasDeclaredServiceContract(node, operations, program) {
|
|
|
5604
5788
|
function localClassDeclarations(program) {
|
|
5605
5789
|
const classes = /* @__PURE__ */ new Map();
|
|
5606
5790
|
for (const statement of program.body) {
|
|
5607
|
-
const declaration = statement.type ===
|
|
5608
|
-
if (declaration?.type ===
|
|
5791
|
+
const declaration = statement.type === AST_NODE_TYPES33.ExportNamedDeclaration || statement.type === AST_NODE_TYPES33.ExportDefaultDeclaration ? statement.declaration : statement;
|
|
5792
|
+
if (declaration?.type === AST_NODE_TYPES33.ClassDeclaration && declaration.id !== null)
|
|
5609
5793
|
classes.set(declaration.id.name, declaration);
|
|
5610
5794
|
}
|
|
5611
5795
|
return classes;
|
|
@@ -5613,13 +5797,13 @@ function localClassDeclarations(program) {
|
|
|
5613
5797
|
function abstractContractOperations(node, functionAliases) {
|
|
5614
5798
|
const methods = new Set(publicMethodNames(node.body, functionAliases));
|
|
5615
5799
|
for (const member3 of node.body.body) {
|
|
5616
|
-
if (member3.type !==
|
|
5800
|
+
if (member3.type !== AST_NODE_TYPES33.TSAbstractMethodDefinition && member3.type !== AST_NODE_TYPES33.TSAbstractPropertyDefinition)
|
|
5617
5801
|
continue;
|
|
5618
5802
|
if (member3.static || member3.accessibility === "private" || member3.accessibility === "protected")
|
|
5619
5803
|
continue;
|
|
5620
|
-
if (member3.type ===
|
|
5804
|
+
if (member3.type === AST_NODE_TYPES33.TSAbstractPropertyDefinition) {
|
|
5621
5805
|
const annotation = member3.typeAnnotation?.typeAnnotation;
|
|
5622
|
-
if (annotation?.type !==
|
|
5806
|
+
if (annotation?.type !== AST_NODE_TYPES33.TSFunctionType && !(annotation?.type === AST_NODE_TYPES33.TSTypeReference && annotation.typeName.type === AST_NODE_TYPES33.Identifier && functionAliases.has(annotation.typeName.name)))
|
|
5623
5807
|
continue;
|
|
5624
5808
|
}
|
|
5625
5809
|
const name = declaredMemberName(member3);
|
|
@@ -5755,7 +5939,7 @@ function isServiceRole(name, filename) {
|
|
|
5755
5939
|
}
|
|
5756
5940
|
|
|
5757
5941
|
// src/rules/no-conditional-empty-object-spread.ts
|
|
5758
|
-
import { AST_NODE_TYPES as
|
|
5942
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES34 } from "@typescript-eslint/utils";
|
|
5759
5943
|
var NO_CONDITIONAL_EMPTY_OBJECT_SPREAD_DOCUMENTATION = {
|
|
5760
5944
|
summary: "Build conditional properties explicitly instead of spreading an empty-object branch.",
|
|
5761
5945
|
rationale: "An empty-object conditional spread hides whether a property is omitted, which differs from assigning undefined.",
|
|
@@ -5807,7 +5991,7 @@ var NO_CONDITIONAL_EMPTY_OBJECT_SPREAD_DOCUMENTATION = {
|
|
|
5807
5991
|
]
|
|
5808
5992
|
};
|
|
5809
5993
|
function isEmptyObject(node) {
|
|
5810
|
-
return node.type ===
|
|
5994
|
+
return node.type === AST_NODE_TYPES34.ObjectExpression && node.properties.length === 0;
|
|
5811
5995
|
}
|
|
5812
5996
|
var no_conditional_empty_object_spread_default = createRule({
|
|
5813
5997
|
name: "no-conditional-empty-object-spread",
|
|
@@ -5828,13 +6012,13 @@ var no_conditional_empty_object_spread_default = createRule({
|
|
|
5828
6012
|
if (isGeneratedFile(context, context.sourceCode.text)) return {};
|
|
5829
6013
|
return {
|
|
5830
6014
|
SpreadElement(node) {
|
|
5831
|
-
if (node.parent.type !==
|
|
6015
|
+
if (node.parent.type !== AST_NODE_TYPES34.ObjectExpression || node.argument.type !== AST_NODE_TYPES34.ConditionalExpression)
|
|
5832
6016
|
return;
|
|
5833
6017
|
if (isEmptyObject(node.argument.consequent) || isEmptyObject(node.argument.alternate)) {
|
|
5834
6018
|
const conditional = node.argument;
|
|
5835
6019
|
const emptyConsequent = isEmptyObject(conditional.consequent);
|
|
5836
6020
|
const populated = emptyConsequent ? conditional.alternate : conditional.consequent;
|
|
5837
|
-
const canFix = populated.type ===
|
|
6021
|
+
const canFix = populated.type === AST_NODE_TYPES34.ObjectExpression && populated.properties.length > 0 && context.sourceCode.getCommentsInside(conditional).length === 0;
|
|
5838
6022
|
context.report({
|
|
5839
6023
|
node,
|
|
5840
6024
|
messageId: "avoid",
|
|
@@ -5851,8 +6035,8 @@ var no_conditional_empty_object_spread_default = createRule({
|
|
|
5851
6035
|
|
|
5852
6036
|
// src/rules/prefer-typed-reflection.ts
|
|
5853
6037
|
import {
|
|
5854
|
-
AST_NODE_TYPES as
|
|
5855
|
-
ASTUtils as
|
|
6038
|
+
AST_NODE_TYPES as AST_NODE_TYPES35,
|
|
6039
|
+
ASTUtils as ASTUtils22,
|
|
5856
6040
|
ESLintUtils as ESLintUtils7
|
|
5857
6041
|
} from "@typescript-eslint/utils";
|
|
5858
6042
|
import ts13 from "typescript";
|
|
@@ -5930,17 +6114,17 @@ var prefer_typed_reflection_default = createRule({
|
|
|
5930
6114
|
const services = ESLintUtils7.getParserServices(context);
|
|
5931
6115
|
if (!services.program) return {};
|
|
5932
6116
|
const checker = services.program.getTypeChecker();
|
|
5933
|
-
const isReflect = (node) => globalName(node, "Reflect") || node.type ===
|
|
5934
|
-
const globalName = (node, name) => node.type ===
|
|
6117
|
+
const isReflect = (node) => globalName(node, "Reflect") || node.type === AST_NODE_TYPES35.MemberExpression && ASTUtils22.getPropertyName(node) === "Reflect" && globalName(node.object, "globalThis");
|
|
6118
|
+
const globalName = (node, name) => node.type === AST_NODE_TYPES35.Identifier && node.name === name && !ASTUtils22.findVariable(context.sourceCode.getScope(node), name)?.defs.length;
|
|
5935
6119
|
const closedObject = (type) => {
|
|
5936
6120
|
if (type.isUnion()) return type.types.every(closedObject);
|
|
5937
6121
|
return knownType(type) && type.getProperties().length > 0 && checker.getIndexInfosOfType(type).length === 0;
|
|
5938
6122
|
};
|
|
5939
6123
|
const inspectGet = (node, type) => {
|
|
5940
6124
|
const key = node.arguments[1] === void 0 ? void 0 : unwrapExpression(node.arguments[1]);
|
|
5941
|
-
return node.arguments.length === 2 && (staticString(key) !== null || key?.type ===
|
|
6125
|
+
return node.arguments.length === 2 && (staticString(key) !== null || key?.type === AST_NODE_TYPES35.Literal && typeof key.value === "number") && closedObject(type);
|
|
5942
6126
|
};
|
|
5943
|
-
const inspectApply = (node, type) => node.arguments.length === 3 && node.arguments[2]?.type ===
|
|
6127
|
+
const inspectApply = (node, type) => node.arguments.length === 3 && node.arguments[2]?.type === AST_NODE_TYPES35.ArrayExpression && knownType(type) && type.getCallSignatures().some(
|
|
5944
6128
|
(signature) => signature.typeParameters === void 0 && signature.parameters.every(
|
|
5945
6129
|
(parameter) => knownType(
|
|
5946
6130
|
checker.getTypeOfSymbolAtLocation(
|
|
@@ -5951,25 +6135,25 @@ var prefer_typed_reflection_default = createRule({
|
|
|
5951
6135
|
)
|
|
5952
6136
|
);
|
|
5953
6137
|
const getReplacement = (node, type, target) => {
|
|
5954
|
-
if (node.optional || node.callee.type !==
|
|
6138
|
+
if (node.optional || node.callee.type !== AST_NODE_TYPES35.MemberExpression || node.callee.optional || context.sourceCode.getCommentsInside(node).length > 0) return null;
|
|
5955
6139
|
let outer = node;
|
|
5956
|
-
while (outer.parent.type ===
|
|
5957
|
-
if (outer.parent.type ===
|
|
6140
|
+
while (outer.parent.type === AST_NODE_TYPES35.TSAsExpression || outer.parent.type === AST_NODE_TYPES35.TSTypeAssertion || outer.parent.type === AST_NODE_TYPES35.TSSatisfiesExpression || outer.parent.type === AST_NODE_TYPES35.TSNonNullExpression || outer.parent.type === AST_NODE_TYPES35.ChainExpression) outer = outer.parent;
|
|
6141
|
+
if (outer.parent.type === AST_NODE_TYPES35.UnaryExpression && outer.parent.operator === "delete" || outer.parent.type === AST_NODE_TYPES35.CallExpression && outer.parent.callee === outer || outer.parent.type === AST_NODE_TYPES35.TaggedTemplateExpression && outer.parent.tag === outer) return null;
|
|
5958
6142
|
const writtenKey = node.arguments[1];
|
|
5959
|
-
if (writtenKey === void 0 || writtenKey.type ===
|
|
6143
|
+
if (writtenKey === void 0 || writtenKey.type === AST_NODE_TYPES35.SpreadElement) return null;
|
|
5960
6144
|
const key = unwrapExpression(writtenKey);
|
|
5961
|
-
const name = staticString(key) ?? (key.type ===
|
|
6145
|
+
const name = staticString(key) ?? (key.type === AST_NODE_TYPES35.Literal && typeof key.value === "number" ? String(key.value) : null);
|
|
5962
6146
|
const members = type.isUnion() ? type.types : [type];
|
|
5963
6147
|
if (name === null || !members.every((member3) => (member3.flags & ts13.TypeFlags.Object) !== 0 && checker.getPropertyOfType(member3, name) !== void 0)) return null;
|
|
5964
6148
|
return `(${context.sourceCode.getText(target)})[${context.sourceCode.getText(writtenKey)}]`;
|
|
5965
6149
|
};
|
|
5966
6150
|
return {
|
|
5967
6151
|
CallExpression(node) {
|
|
5968
|
-
if (node.callee.type !==
|
|
6152
|
+
if (node.callee.type !== AST_NODE_TYPES35.MemberExpression || !isReflect(node.callee.object))
|
|
5969
6153
|
return;
|
|
5970
|
-
const method =
|
|
6154
|
+
const method = ASTUtils22.getPropertyName(node.callee);
|
|
5971
6155
|
const target = node.arguments[0];
|
|
5972
|
-
if (!target || target.type ===
|
|
6156
|
+
if (!target || target.type === AST_NODE_TYPES35.SpreadElement || method !== "get" && method !== "apply")
|
|
5973
6157
|
return;
|
|
5974
6158
|
const type = checker.getTypeAtLocation(
|
|
5975
6159
|
services.esTreeNodeToTSNodeMap.get(target)
|
|
@@ -5985,30 +6169,30 @@ var prefer_typed_reflection_default = createRule({
|
|
|
5985
6169
|
|
|
5986
6170
|
// src/rules/no-broad-return-type.ts
|
|
5987
6171
|
import {
|
|
5988
|
-
AST_NODE_TYPES as
|
|
6172
|
+
AST_NODE_TYPES as AST_NODE_TYPES37,
|
|
5989
6173
|
ESLintUtils as ESLintUtils8
|
|
5990
6174
|
} from "@typescript-eslint/utils";
|
|
5991
6175
|
import ts14 from "typescript";
|
|
5992
6176
|
|
|
5993
6177
|
// src/rules/_unused-private-binding.ts
|
|
5994
|
-
import { AST_NODE_TYPES as
|
|
6178
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES36 } from "@typescript-eslint/utils";
|
|
5995
6179
|
function isUnusedPrivateBinding(sourceCode, declaration, identifier, filename, allowedDeclarations = [declaration]) {
|
|
5996
6180
|
if (/\.d\.[cm]?ts$/u.test(filename)) return false;
|
|
5997
6181
|
const bindings = sourceCode.getDeclaredVariables(declaration).filter((binding3) => binding3.name === identifier.name);
|
|
5998
6182
|
if (bindings.length === 0 || bindings.some((binding3) => binding3.defs.length !== allowedDeclarations.length || binding3.defs.some((definition) => !allowedDeclarations.includes(definition.node)) || binding3.eslintUsed || binding3.references.some((reference) => reference.isRead() || reference.init !== true))) return false;
|
|
5999
6183
|
if (hasIdentifierNamed(sourceCode.ast, "eval")) return false;
|
|
6000
|
-
const statement = declaration.type ===
|
|
6001
|
-
if (statement.parent.type ===
|
|
6002
|
-
if (statement.parent.type !==
|
|
6003
|
-
return sourceCode.ast.body.some((node) => node.type ===
|
|
6184
|
+
const statement = declaration.type === AST_NODE_TYPES36.VariableDeclarator ? declaration.parent : declaration;
|
|
6185
|
+
if (statement.parent.type === AST_NODE_TYPES36.ExportNamedDeclaration || statement.parent.type === AST_NODE_TYPES36.ExportDefaultDeclaration) return false;
|
|
6186
|
+
if (statement.parent.type !== AST_NODE_TYPES36.Program) return statement.parent.type === AST_NODE_TYPES36.BlockStatement;
|
|
6187
|
+
return sourceCode.ast.body.some((node) => node.type === AST_NODE_TYPES36.ImportDeclaration || node.type === AST_NODE_TYPES36.ExportNamedDeclaration || node.type === AST_NODE_TYPES36.ExportDefaultDeclaration || node.type === AST_NODE_TYPES36.ExportAllDeclaration);
|
|
6004
6188
|
}
|
|
6005
6189
|
function hasOnlyDirectFactoryUses(variable) {
|
|
6006
6190
|
return variable.references.every((reference) => {
|
|
6007
6191
|
if (reference.isTypeReference && !reference.isValueReference) return true;
|
|
6008
6192
|
const identifier = reference.identifier;
|
|
6009
6193
|
const parent = identifier.parent;
|
|
6010
|
-
if (parent.type ===
|
|
6011
|
-
return parent.type ===
|
|
6194
|
+
if (parent.type === AST_NODE_TYPES36.CallExpression && parent.callee === identifier) return true;
|
|
6195
|
+
return parent.type === AST_NODE_TYPES36.MemberExpression && parent.object === identifier && !parent.computed && parent.parent.type === AST_NODE_TYPES36.CallExpression && parent.parent.callee === parent;
|
|
6012
6196
|
});
|
|
6013
6197
|
}
|
|
6014
6198
|
var IDENTIFIER_NAMES = /* @__PURE__ */ new WeakMap();
|
|
@@ -6022,7 +6206,7 @@ function hasIdentifierNamed(node, name) {
|
|
|
6022
6206
|
const current = pending.pop();
|
|
6023
6207
|
if (current === void 0 || seen.has(current)) continue;
|
|
6024
6208
|
seen.add(current);
|
|
6025
|
-
if (current.type ===
|
|
6209
|
+
if (current.type === AST_NODE_TYPES36.Identifier || current.type === AST_NODE_TYPES36.JSXIdentifier) collected.add(current.name);
|
|
6026
6210
|
forEachOwnAstChild(current, (child) => {
|
|
6027
6211
|
pending.push(child);
|
|
6028
6212
|
}, (key) => key !== "tokens" && key !== "comments");
|
|
@@ -6033,7 +6217,7 @@ function hasIdentifierNamed(node, name) {
|
|
|
6033
6217
|
return names.has(name);
|
|
6034
6218
|
}
|
|
6035
6219
|
function privatePredicateBooleanFix(sourceCode, node, annotation, filename) {
|
|
6036
|
-
if (!annotation.typeAnnotation || !retainsNamedTypeUses(sourceCode, annotation.typeAnnotation) || node.type !==
|
|
6220
|
+
if (!annotation.typeAnnotation || !retainsNamedTypeUses(sourceCode, annotation.typeAnnotation) || node.type !== AST_NODE_TYPES36.FunctionDeclaration || node.id === null || !isUnusedPrivateBinding(sourceCode, node, node.id, filename) || sourceCode.getCommentsInside(annotation).length > 0) return null;
|
|
6037
6221
|
return (fixer) => fixer.replaceText(annotation, `boolean${sourceCode.getText(annotation).replace(/[^\r\n]/gu, "")}`);
|
|
6038
6222
|
}
|
|
6039
6223
|
|
|
@@ -6147,7 +6331,7 @@ var no_broad_return_type_default = createRule({
|
|
|
6147
6331
|
known: false,
|
|
6148
6332
|
opaque: false
|
|
6149
6333
|
});
|
|
6150
|
-
if (node.body && node.body.type !==
|
|
6334
|
+
if (node.body && node.body.type !== AST_NODE_TYPES37.BlockStatement)
|
|
6151
6335
|
inspectReturn(node.body);
|
|
6152
6336
|
};
|
|
6153
6337
|
const leave = () => {
|
|
@@ -6155,7 +6339,7 @@ var no_broad_return_type_default = createRule({
|
|
|
6155
6339
|
if (frame?.annotation && frame.known && !frame.opaque) {
|
|
6156
6340
|
const annotation = frame.annotation;
|
|
6157
6341
|
const node = frame.node;
|
|
6158
|
-
const canFix = node.type ===
|
|
6342
|
+
const canFix = node.type === AST_NODE_TYPES37.FunctionDeclaration && node.id !== null && isUnusedPrivateBinding(context.sourceCode, node, node.id, context.filename) && context.sourceCode.getCommentsInside(annotation).length === 0 && retainsNamedTypeUses(context.sourceCode, annotation);
|
|
6159
6343
|
context.report({ node: annotation, messageId: "avoid", fix: canFix ? (fixer) => fixer.replaceText(annotation, context.sourceCode.getText(annotation).replace(/[^\r\n]/gu, "")) : null });
|
|
6160
6344
|
}
|
|
6161
6345
|
};
|
|
@@ -6175,49 +6359,49 @@ var no_broad_return_type_default = createRule({
|
|
|
6175
6359
|
|
|
6176
6360
|
// src/rules/no-reduce-accumulator-copy.ts
|
|
6177
6361
|
import {
|
|
6178
|
-
AST_NODE_TYPES as
|
|
6179
|
-
ASTUtils as
|
|
6362
|
+
AST_NODE_TYPES as AST_NODE_TYPES39,
|
|
6363
|
+
ASTUtils as ASTUtils24,
|
|
6180
6364
|
ESLintUtils as ESLintUtils9
|
|
6181
6365
|
} from "@typescript-eslint/utils";
|
|
6182
6366
|
import ts15 from "typescript";
|
|
6183
6367
|
|
|
6184
6368
|
// src/rules/_literal-identity-reduce-fix.ts
|
|
6185
6369
|
import {
|
|
6186
|
-
AST_NODE_TYPES as
|
|
6187
|
-
ASTUtils as
|
|
6370
|
+
AST_NODE_TYPES as AST_NODE_TYPES38,
|
|
6371
|
+
ASTUtils as ASTUtils23
|
|
6188
6372
|
} from "@typescript-eslint/utils";
|
|
6189
6373
|
function literalIdentityReduceFix(sourceCode, node) {
|
|
6190
|
-
if (sourceCode.ast.body.length !== 1 || sourceCode.getAllComments().length > 0 || node.optional || node.arguments.length !== 2 || node.callee.type !==
|
|
6374
|
+
if (sourceCode.ast.body.length !== 1 || sourceCode.getAllComments().length > 0 || node.optional || node.arguments.length !== 2 || node.callee.type !== AST_NODE_TYPES38.MemberExpression || node.callee.optional || ASTUtils23.getPropertyName(node.callee) !== "reduce")
|
|
6191
6375
|
return null;
|
|
6192
6376
|
const values = node.callee.object;
|
|
6193
|
-
if (values.type !==
|
|
6194
|
-
(element) => element?.type ===
|
|
6377
|
+
if (values.type !== AST_NODE_TYPES38.ArrayExpression || values.elements.length === 0 || !values.elements.every(
|
|
6378
|
+
(element) => element?.type === AST_NODE_TYPES38.Literal && typeof element.value === "string"
|
|
6195
6379
|
))
|
|
6196
6380
|
return null;
|
|
6197
6381
|
const statement = sourceCode.ast.body[0];
|
|
6198
|
-
if (statement?.type !==
|
|
6382
|
+
if (statement?.type !== AST_NODE_TYPES38.ExportNamedDeclaration || statement.declaration?.type !== AST_NODE_TYPES38.FunctionDeclaration)
|
|
6199
6383
|
return null;
|
|
6200
6384
|
const owner = statement.declaration;
|
|
6201
6385
|
if (owner.async || owner.declare || owner.generator || owner.typeParameters !== void 0 || owner.params.length !== 0 || owner.body.body.length !== 1 || !stringArray(owner.returnType?.typeAnnotation))
|
|
6202
6386
|
return null;
|
|
6203
6387
|
const returned2 = owner.body.body[0];
|
|
6204
|
-
if (returned2?.type !==
|
|
6388
|
+
if (returned2?.type !== AST_NODE_TYPES38.ReturnStatement || returned2.argument !== node || node.typeArguments?.params.length !== 1 || !stringArray(node.typeArguments.params[0]))
|
|
6205
6389
|
return null;
|
|
6206
6390
|
const [callback, seed] = node.arguments;
|
|
6207
|
-
if (seed?.type !==
|
|
6391
|
+
if (seed?.type !== AST_NODE_TYPES38.ArrayExpression || seed.elements.length !== 0 || callback?.type !== AST_NODE_TYPES38.ArrowFunctionExpression || callback.async || callback.typeParameters !== void 0 || callback.returnType !== void 0 || callback.params.length !== 2 || callback.body.type !== AST_NODE_TYPES38.ArrayExpression || callback.body.elements.length !== 2)
|
|
6208
6392
|
return null;
|
|
6209
6393
|
if (!identitySpread(sourceCode, callback)) return null;
|
|
6210
6394
|
return (fixer) => fixer.replaceText(node, sourceCode.getText(values));
|
|
6211
6395
|
}
|
|
6212
6396
|
function stringArray(node) {
|
|
6213
|
-
return node?.type ===
|
|
6397
|
+
return node?.type === AST_NODE_TYPES38.TSArrayType && node.elementType.type === AST_NODE_TYPES38.TSStringKeyword;
|
|
6214
6398
|
}
|
|
6215
6399
|
function identitySpread(sourceCode, callback) {
|
|
6216
6400
|
const [accumulator, item] = callback.params;
|
|
6217
|
-
if (accumulator?.type !==
|
|
6401
|
+
if (accumulator?.type !== AST_NODE_TYPES38.Identifier || item?.type !== AST_NODE_TYPES38.Identifier || accumulator.name === item.name || accumulator.optional || item.optional || accumulator.typeAnnotation !== void 0 || item.typeAnnotation !== void 0 || callback.body.type !== AST_NODE_TYPES38.ArrayExpression)
|
|
6218
6402
|
return false;
|
|
6219
6403
|
const [spread, appended] = callback.body.elements;
|
|
6220
|
-
if (spread?.type !==
|
|
6404
|
+
if (spread?.type !== AST_NODE_TYPES38.SpreadElement || spread.argument.type !== AST_NODE_TYPES38.Identifier || appended?.type !== AST_NODE_TYPES38.Identifier || spread.argument.name !== accumulator.name || appended.name !== item.name)
|
|
6221
6405
|
return false;
|
|
6222
6406
|
const bindings = sourceCode.getDeclaredVariables(callback);
|
|
6223
6407
|
const left = bindings.find(
|
|
@@ -6226,10 +6410,10 @@ function identitySpread(sourceCode, callback) {
|
|
|
6226
6410
|
const right = bindings.find(
|
|
6227
6411
|
(variable) => variable.identifiers.includes(item)
|
|
6228
6412
|
);
|
|
6229
|
-
return left !== void 0 && right !== void 0 &&
|
|
6413
|
+
return left !== void 0 && right !== void 0 && ASTUtils23.findVariable(
|
|
6230
6414
|
sourceCode.getScope(spread.argument),
|
|
6231
6415
|
spread.argument.name
|
|
6232
|
-
) === left &&
|
|
6416
|
+
) === left && ASTUtils23.findVariable(sourceCode.getScope(appended), appended.name) === right;
|
|
6233
6417
|
}
|
|
6234
6418
|
|
|
6235
6419
|
// src/rules/no-reduce-accumulator-copy.ts
|
|
@@ -6325,19 +6509,19 @@ var no_reduce_accumulator_copy_default = createRule({
|
|
|
6325
6509
|
const checker = program.getTypeChecker();
|
|
6326
6510
|
return {
|
|
6327
6511
|
CallExpression(node) {
|
|
6328
|
-
if (node.callee.type !==
|
|
6329
|
-
|
|
6512
|
+
if (node.callee.type !== AST_NODE_TYPES39.MemberExpression || !["reduce", "reduceRight"].includes(
|
|
6513
|
+
ASTUtils24.getPropertyName(node.callee) ?? ""
|
|
6330
6514
|
) || node.arguments.length !== 2)
|
|
6331
6515
|
return;
|
|
6332
6516
|
const seed = node.arguments[1];
|
|
6333
|
-
const arraySeed = seed?.type ===
|
|
6334
|
-
const objectSeed = seed?.type ===
|
|
6517
|
+
const arraySeed = seed?.type === AST_NODE_TYPES39.ArrayExpression && seed.elements.length === 0;
|
|
6518
|
+
const objectSeed = seed?.type === AST_NODE_TYPES39.ObjectExpression && seed.properties.length === 0;
|
|
6335
6519
|
if (!arraySeed && !objectSeed) return;
|
|
6336
6520
|
const callback = node.arguments[0];
|
|
6337
|
-
if (!callback || callback.type !==
|
|
6521
|
+
if (!callback || callback.type !== AST_NODE_TYPES39.ArrowFunctionExpression && callback.type !== AST_NODE_TYPES39.FunctionExpression)
|
|
6338
6522
|
return;
|
|
6339
6523
|
const parameter = callback.params[0];
|
|
6340
|
-
if (parameter?.type !==
|
|
6524
|
+
if (parameter?.type !== AST_NODE_TYPES39.Identifier) return;
|
|
6341
6525
|
const signature = checker.getResolvedSignature(
|
|
6342
6526
|
services.esTreeNodeToTSNodeMap.get(node)
|
|
6343
6527
|
);
|
|
@@ -6348,51 +6532,51 @@ var no_reduce_accumulator_copy_default = createRule({
|
|
|
6348
6532
|
if (!accumulator || accumulator.references.some((reference) => reference.isWrite()))
|
|
6349
6533
|
return;
|
|
6350
6534
|
const fix = literalIdentityReduceFix(context.sourceCode, node);
|
|
6351
|
-
const referencesAccumulator = (value) => value.type ===
|
|
6535
|
+
const referencesAccumulator = (value) => value.type === AST_NODE_TYPES39.Identifier && ASTUtils24.findVariable(
|
|
6352
6536
|
context.sourceCode.getScope(value),
|
|
6353
6537
|
value.name
|
|
6354
6538
|
) === accumulator;
|
|
6355
6539
|
const inspect = (current) => {
|
|
6356
6540
|
if (current !== callback.body && [
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6541
|
+
AST_NODE_TYPES39.ArrowFunctionExpression,
|
|
6542
|
+
AST_NODE_TYPES39.FunctionExpression,
|
|
6543
|
+
AST_NODE_TYPES39.FunctionDeclaration,
|
|
6544
|
+
AST_NODE_TYPES39.ClassDeclaration,
|
|
6545
|
+
AST_NODE_TYPES39.ClassExpression,
|
|
6546
|
+
AST_NODE_TYPES39.ForStatement,
|
|
6547
|
+
AST_NODE_TYPES39.ForInStatement,
|
|
6548
|
+
AST_NODE_TYPES39.ForOfStatement,
|
|
6549
|
+
AST_NODE_TYPES39.WhileStatement,
|
|
6550
|
+
AST_NODE_TYPES39.DoWhileStatement
|
|
6367
6551
|
].some((kind) => kind === current.type))
|
|
6368
6552
|
return;
|
|
6369
|
-
if (current.type ===
|
|
6553
|
+
if (current.type === AST_NODE_TYPES39.SpreadElement && (arraySeed && current.parent.type === AST_NODE_TYPES39.ArrayExpression || objectSeed && current.parent.type === AST_NODE_TYPES39.ObjectExpression) && referencesAccumulator(current.argument)) {
|
|
6370
6554
|
context.report({
|
|
6371
6555
|
node: current,
|
|
6372
6556
|
messageId: "copy",
|
|
6373
6557
|
fix
|
|
6374
6558
|
});
|
|
6375
6559
|
}
|
|
6376
|
-
if (current.type ===
|
|
6560
|
+
if (current.type === AST_NODE_TYPES39.CallExpression)
|
|
6377
6561
|
inspectCall(current);
|
|
6378
6562
|
forEachAstChild(current, context.sourceCode.visitorKeys, inspect);
|
|
6379
6563
|
};
|
|
6380
6564
|
const inspectCall = (current) => {
|
|
6381
|
-
if (current.callee.type !==
|
|
6565
|
+
if (current.callee.type !== AST_NODE_TYPES39.MemberExpression) return;
|
|
6382
6566
|
const member3 = current.callee;
|
|
6383
|
-
const name =
|
|
6567
|
+
const name = ASTUtils24.getPropertyName(member3);
|
|
6384
6568
|
const directCopy = arraySeed && name !== null && COPY_METHODS.has(name) && referencesAccumulator(member3.object);
|
|
6385
|
-
const globalArray = member3.object.type ===
|
|
6569
|
+
const globalArray = member3.object.type === AST_NODE_TYPES39.Identifier && member3.object.name === "Array" && !ASTUtils24.findVariable(
|
|
6386
6570
|
context.sourceCode.getScope(member3.object),
|
|
6387
6571
|
"Array"
|
|
6388
6572
|
)?.defs.length;
|
|
6389
6573
|
const fromCopy = arraySeed && name === "from" && globalArray && current.arguments[0] !== void 0 && referencesAccumulator(current.arguments[0]);
|
|
6390
|
-
const globalObject = member3.object.type ===
|
|
6574
|
+
const globalObject = member3.object.type === AST_NODE_TYPES39.Identifier && member3.object.name === "Object" && !ASTUtils24.findVariable(
|
|
6391
6575
|
context.sourceCode.getScope(member3.object),
|
|
6392
6576
|
"Object"
|
|
6393
6577
|
)?.defs.length;
|
|
6394
6578
|
const target = current.arguments[0];
|
|
6395
|
-
const assignCopy = objectSeed && name === "assign" && globalObject && target?.type ===
|
|
6579
|
+
const assignCopy = objectSeed && name === "assign" && globalObject && target?.type === AST_NODE_TYPES39.ObjectExpression && current.arguments.slice(1).some(referencesAccumulator);
|
|
6396
6580
|
if (directCopy || fromCopy || assignCopy)
|
|
6397
6581
|
context.report({ node: current, messageId: "copy" });
|
|
6398
6582
|
};
|
|
@@ -6403,7 +6587,7 @@ var no_reduce_accumulator_copy_default = createRule({
|
|
|
6403
6587
|
});
|
|
6404
6588
|
|
|
6405
6589
|
// src/rules/no-known-value-widening.ts
|
|
6406
|
-
import { AST_NODE_TYPES as
|
|
6590
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES40, ESLintUtils as ESLintUtils10 } from "@typescript-eslint/utils";
|
|
6407
6591
|
import ts16 from "typescript";
|
|
6408
6592
|
var NO_KNOWN_VALUE_WIDENING_DOCUMENTATION = {
|
|
6409
6593
|
summary: "Preserve a known value's contract instead of widening a local binding to unknown, object, or an unknown-valued dictionary.",
|
|
@@ -6458,7 +6642,7 @@ var no_known_value_widening_default = createRule({
|
|
|
6458
6642
|
const checker = services.program.getTypeChecker();
|
|
6459
6643
|
return {
|
|
6460
6644
|
VariableDeclarator(node) {
|
|
6461
|
-
if (node.id.type !==
|
|
6645
|
+
if (node.id.type !== AST_NODE_TYPES40.Identifier || !node.id.typeAnnotation || node.init?.type !== AST_NODE_TYPES40.Identifier || node.parent.kind !== "const" || node.parent.parent.type === AST_NODE_TYPES40.ExportNamedDeclaration) return;
|
|
6462
6646
|
const source = checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(node.init));
|
|
6463
6647
|
if (hasUnknownContract(source, checker)) return;
|
|
6464
6648
|
const target = checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(node.id.typeAnnotation.typeAnnotation));
|
|
@@ -6477,7 +6661,7 @@ var no_known_value_widening_default = createRule({
|
|
|
6477
6661
|
});
|
|
6478
6662
|
|
|
6479
6663
|
// src/rules/no-invalid-typed-mutation.ts
|
|
6480
|
-
import { ASTUtils as
|
|
6664
|
+
import { ASTUtils as ASTUtils25, AST_NODE_TYPES as AST_NODE_TYPES41, ESLintUtils as ESLintUtils11 } from "@typescript-eslint/utils";
|
|
6481
6665
|
import { isObjectType, isTypeReference } from "ts-api-utils";
|
|
6482
6666
|
import ts17 from "typescript";
|
|
6483
6667
|
var NO_INVALID_TYPED_MUTATION_DOCUMENTATION = {
|
|
@@ -6585,7 +6769,7 @@ var no_invalid_typed_mutation_default = createRule({
|
|
|
6585
6769
|
const target = node.arguments[0];
|
|
6586
6770
|
if (target === void 0) return;
|
|
6587
6771
|
invalidateNamespace(target);
|
|
6588
|
-
if (target.type !==
|
|
6772
|
+
if (target.type !== AST_NODE_TYPES41.Identifier) return;
|
|
6589
6773
|
const writes = mutationWrites(node, method.namespace, method.method);
|
|
6590
6774
|
if (writes !== void 0) candidates.push({ call: node, ...method, target, writes });
|
|
6591
6775
|
},
|
|
@@ -6596,9 +6780,9 @@ var no_invalid_typed_mutation_default = createRule({
|
|
|
6596
6780
|
}
|
|
6597
6781
|
});
|
|
6598
6782
|
function localDataTarget(target, sourceCode) {
|
|
6599
|
-
const binding3 =
|
|
6783
|
+
const binding3 = ASTUtils25.findVariable(sourceCode.getScope(target), target.name);
|
|
6600
6784
|
const definition = binding3?.defs.length === 1 ? binding3.defs[0] : void 0;
|
|
6601
|
-
if (definition?.type !== "Variable" || definition.parent.kind !== "const" || definition.node.id.type !==
|
|
6785
|
+
if (definition?.type !== "Variable" || definition.parent.kind !== "const" || definition.node.id.type !== AST_NODE_TYPES41.Identifier || definition.node.id.typeAnnotation === void 0 || definition.node.init?.type !== AST_NODE_TYPES41.ObjectExpression || definition.parent.parent.type === AST_NODE_TYPES41.ExportNamedDeclaration) return void 0;
|
|
6602
6786
|
const properties = plainProperties(definition.node.init);
|
|
6603
6787
|
if (properties === void 0) return void 0;
|
|
6604
6788
|
const scope = sourceCode.getScope(definition.node).variableScope;
|
|
@@ -6609,29 +6793,29 @@ function localDataTarget(target, sourceCode) {
|
|
|
6609
6793
|
return new Set(properties.map((property) => property.key));
|
|
6610
6794
|
}
|
|
6611
6795
|
function safeTargetUse(identifier, sourceCode) {
|
|
6612
|
-
if (identifier.type !==
|
|
6796
|
+
if (identifier.type !== AST_NODE_TYPES41.Identifier) return false;
|
|
6613
6797
|
const parent = identifier.parent;
|
|
6614
|
-
if (parent.type ===
|
|
6615
|
-
const key =
|
|
6798
|
+
if (parent.type === AST_NODE_TYPES41.MemberExpression && parent.object === identifier) {
|
|
6799
|
+
const key = ASTUtils25.getPropertyName(parent);
|
|
6616
6800
|
const use = outerExpression(parent);
|
|
6617
|
-
if (parent.optional || use.parent.type ===
|
|
6618
|
-
return key !== null && key !== "__proto__" && !(use.parent.type ===
|
|
6801
|
+
if (parent.optional || use.parent.type === AST_NODE_TYPES41.UnaryExpression && use.parent.operator === "delete") return false;
|
|
6802
|
+
return key !== null && key !== "__proto__" && !(use.parent.type === AST_NODE_TYPES41.CallExpression && use.parent.callee === use);
|
|
6619
6803
|
}
|
|
6620
|
-
if (parent.type !==
|
|
6804
|
+
if (parent.type !== AST_NODE_TYPES41.CallExpression || parent.arguments[0] !== identifier) return false;
|
|
6621
6805
|
const method = nativeMember(parent.callee, sourceCode);
|
|
6622
6806
|
if (method === void 0) return false;
|
|
6623
6807
|
const writes = mutationWrites(parent, method.namespace, method.method);
|
|
6624
|
-
return writes !== void 0 && writes.every((write) => write.key !== "__proto__") && keepsMutableDescriptor(parent, method.method) && (method.method === "set" || parent.parent.type ===
|
|
6808
|
+
return writes !== void 0 && writes.every((write) => write.key !== "__proto__") && keepsMutableDescriptor(parent, method.method) && (method.method === "set" || parent.parent.type === AST_NODE_TYPES41.ExpressionStatement);
|
|
6625
6809
|
}
|
|
6626
6810
|
function keepsMutableDescriptor(call, method) {
|
|
6627
6811
|
if (method !== "defineProperty") return true;
|
|
6628
6812
|
const descriptor = call.arguments[2];
|
|
6629
|
-
if (descriptor?.type !==
|
|
6813
|
+
if (descriptor?.type !== AST_NODE_TYPES41.ObjectExpression) return false;
|
|
6630
6814
|
const properties = plainProperties(descriptor);
|
|
6631
6815
|
return properties !== void 0 && properties.every((property) => {
|
|
6632
6816
|
if (property.key !== "writable" && property.key !== "configurable") return true;
|
|
6633
6817
|
const value = unwrapExpression(property.value);
|
|
6634
|
-
return value.type ===
|
|
6818
|
+
return value.type === AST_NODE_TYPES41.Literal && value.value === true;
|
|
6635
6819
|
});
|
|
6636
6820
|
}
|
|
6637
6821
|
function declaredTargetType(node, checker) {
|
|
@@ -6681,9 +6865,9 @@ function definiteSignatures(type, checker, seen) {
|
|
|
6681
6865
|
}
|
|
6682
6866
|
function nativeMember(node, sourceCode) {
|
|
6683
6867
|
const member3 = unwrapExpression(node);
|
|
6684
|
-
if (member3.type !==
|
|
6868
|
+
if (member3.type !== AST_NODE_TYPES41.MemberExpression || member3.optional) return void 0;
|
|
6685
6869
|
const namespace = nativeNamespace(member3.object, sourceCode);
|
|
6686
|
-
const method =
|
|
6870
|
+
const method = ASTUtils25.getPropertyName(member3);
|
|
6687
6871
|
if (namespace === void 0 || method === null) return void 0;
|
|
6688
6872
|
const supported2 = namespace === "Object" ? ["assign", "defineProperty", "defineProperties", "setPrototypeOf"] : ["set", "defineProperty", "setPrototypeOf"];
|
|
6689
6873
|
return supported2.includes(method) ? { namespace, method } : void 0;
|
|
@@ -6692,43 +6876,43 @@ function ordinaryNamespaceUse(node) {
|
|
|
6692
6876
|
const value = outerExpression(node);
|
|
6693
6877
|
const parent = value.parent;
|
|
6694
6878
|
if (parent === void 0) return false;
|
|
6695
|
-
return parent.type ===
|
|
6879
|
+
return parent.type === AST_NODE_TYPES41.MemberExpression && parent.object === value || parent.type === AST_NODE_TYPES41.UnaryExpression && parent.operator === "typeof" || parent.type === AST_NODE_TYPES41.TSTypeQuery || parent.type === AST_NODE_TYPES41.TSQualifiedName;
|
|
6696
6880
|
}
|
|
6697
6881
|
function replacementNamespace(node, sourceCode) {
|
|
6698
6882
|
const value = unwrapExpression(node);
|
|
6699
6883
|
if (nativeObjectPrototype(value, sourceCode)) return "ObjectPrototype";
|
|
6700
|
-
return nativeNamespace(value, sourceCode) ?? (value.type ===
|
|
6884
|
+
return nativeNamespace(value, sourceCode) ?? (value.type === AST_NODE_TYPES41.MemberExpression ? replacementNamespace(value.object, sourceCode) : void 0);
|
|
6701
6885
|
}
|
|
6702
6886
|
function nativeObjectPrototype(node, sourceCode) {
|
|
6703
6887
|
const value = unwrapExpression(node);
|
|
6704
|
-
return value.type ===
|
|
6888
|
+
return value.type === AST_NODE_TYPES41.MemberExpression && ASTUtils25.getPropertyName(value) === "prototype" && nativeNamespace(value.object, sourceCode) === "Object";
|
|
6705
6889
|
}
|
|
6706
6890
|
function nativeNamespace(node, sourceCode) {
|
|
6707
6891
|
const value = unwrapExpression(node);
|
|
6708
|
-
if (value.type ===
|
|
6709
|
-
const key =
|
|
6892
|
+
if (value.type === AST_NODE_TYPES41.MemberExpression && !value.optional && nativeGlobalReceiver(value.object, sourceCode)) {
|
|
6893
|
+
const key = ASTUtils25.getPropertyName(value);
|
|
6710
6894
|
if (key === "Object" || key === "Reflect") return key;
|
|
6711
6895
|
}
|
|
6712
|
-
if (value.type !==
|
|
6713
|
-
const binding3 =
|
|
6896
|
+
if (value.type !== AST_NODE_TYPES41.Identifier || value.name !== "Object" && value.name !== "Reflect") return void 0;
|
|
6897
|
+
const binding3 = ASTUtils25.findVariable(sourceCode.getScope(value), value.name);
|
|
6714
6898
|
return binding3 === null || binding3.defs.length === 0 ? value.name : void 0;
|
|
6715
6899
|
}
|
|
6716
6900
|
function nativeGlobalReceiver(node, sourceCode) {
|
|
6717
|
-
if (node.type !==
|
|
6718
|
-
const binding3 =
|
|
6901
|
+
if (node.type !== AST_NODE_TYPES41.Identifier || !["globalThis", "window", "self"].includes(node.name)) return false;
|
|
6902
|
+
const binding3 = ASTUtils25.findVariable(sourceCode.getScope(node), node.name);
|
|
6719
6903
|
return binding3 === null || binding3.defs.length === 0;
|
|
6720
6904
|
}
|
|
6721
6905
|
function mutationWrites(node, namespace, method) {
|
|
6722
6906
|
if (namespace === "Object" && method === "assign") {
|
|
6723
6907
|
const source = node.arguments[1];
|
|
6724
|
-
return node.arguments.length === 2 && source?.type ===
|
|
6908
|
+
return node.arguments.length === 2 && source?.type === AST_NODE_TYPES41.ObjectExpression ? plainProperties(source) : void 0;
|
|
6725
6909
|
}
|
|
6726
6910
|
if (node.arguments.length !== 3 || method !== "set" && method !== "defineProperty") return void 0;
|
|
6727
6911
|
const key = staticString(node.arguments[1]);
|
|
6728
6912
|
const value = node.arguments[2];
|
|
6729
|
-
if (key === null || value === void 0 || value.type ===
|
|
6913
|
+
if (key === null || value === void 0 || value.type === AST_NODE_TYPES41.SpreadElement) return void 0;
|
|
6730
6914
|
if (method === "set") return [{ key, value }];
|
|
6731
|
-
if (value.type !==
|
|
6915
|
+
if (value.type !== AST_NODE_TYPES41.ObjectExpression) return void 0;
|
|
6732
6916
|
const properties = plainProperties(value);
|
|
6733
6917
|
if (properties === void 0 || properties.some((property) => !["value", "configurable", "enumerable", "writable"].includes(property.key))) return void 0;
|
|
6734
6918
|
const payload = properties.find((property) => property.key === "value");
|
|
@@ -6738,8 +6922,8 @@ function plainProperties(node) {
|
|
|
6738
6922
|
const writes = [];
|
|
6739
6923
|
const names = /* @__PURE__ */ new Set();
|
|
6740
6924
|
for (const property of node.properties) {
|
|
6741
|
-
if (property.type !==
|
|
6742
|
-
const key =
|
|
6925
|
+
if (property.type !== AST_NODE_TYPES41.Property || property.kind !== "init" || property.method) return void 0;
|
|
6926
|
+
const key = ASTUtils25.getPropertyName(property);
|
|
6743
6927
|
if (key === null || key === "__proto__" || names.has(key)) return void 0;
|
|
6744
6928
|
names.add(key);
|
|
6745
6929
|
writes.push({ key, value: property.value });
|
|
@@ -6748,7 +6932,7 @@ function plainProperties(node) {
|
|
|
6748
6932
|
}
|
|
6749
6933
|
|
|
6750
6934
|
// src/rules/no-contradictory-type-predicate.ts
|
|
6751
|
-
import { ASTUtils as
|
|
6935
|
+
import { ASTUtils as ASTUtils27, AST_NODE_TYPES as AST_NODE_TYPES43, ESLintUtils as ESLintUtils12 } from "@typescript-eslint/utils";
|
|
6752
6936
|
import ts20 from "typescript";
|
|
6753
6937
|
|
|
6754
6938
|
// src/rules/_has-separate-predicate-contract.ts
|
|
@@ -6764,7 +6948,7 @@ function hasSeparatePredicateContract(node, checker) {
|
|
|
6764
6948
|
}
|
|
6765
6949
|
|
|
6766
6950
|
// src/rules/_contradictory-array-predicate.ts
|
|
6767
|
-
import { AST_NODE_TYPES as
|
|
6951
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES42, ASTUtils as ASTUtils26 } from "@typescript-eslint/utils";
|
|
6768
6952
|
import ts19 from "typescript";
|
|
6769
6953
|
import { isTypeReference as isTypeReference2 } from "ts-api-utils";
|
|
6770
6954
|
var HOST_GLOBALS = ["globalThis", "window", "self", "global"];
|
|
@@ -6777,12 +6961,12 @@ function contradictoryArrayPredicate(sourceCode, services) {
|
|
|
6777
6961
|
function matches(expression, parameter, input, target) {
|
|
6778
6962
|
if ((input.flags & ts19.TypeFlags.Unknown) === 0 || !plainPrimitiveArray(target, checker)) return false;
|
|
6779
6963
|
const call = unwrapExpression(expression);
|
|
6780
|
-
if (call.type !==
|
|
6964
|
+
if (call.type !== AST_NODE_TYPES42.CallExpression || call.optional || call.arguments.length !== 1) return false;
|
|
6781
6965
|
const argument = call.arguments[0];
|
|
6782
6966
|
const callee = unwrapExpression(call.callee);
|
|
6783
|
-
if (argument?.type !==
|
|
6784
|
-
const declared =
|
|
6785
|
-
if (declared === null || declared !==
|
|
6967
|
+
if (argument?.type !== AST_NODE_TYPES42.Identifier || callee.type !== AST_NODE_TYPES42.MemberExpression || callee.optional || ASTUtils26.getPropertyName(callee) !== "isArray" || callee.object.type !== AST_NODE_TYPES42.Identifier || callee.object.name !== "Array") return false;
|
|
6968
|
+
const declared = ASTUtils26.findVariable(sourceCode.getScope(parameter), parameter.name);
|
|
6969
|
+
if (declared === null || declared !== ASTUtils26.findVariable(sourceCode.getScope(argument), argument.name)) return false;
|
|
6786
6970
|
const binding3 = nativeBinding(callee.object, sourceCode);
|
|
6787
6971
|
if (binding3 === void 0 || !stableArray(binding3, sourceCode, stable2)) return false;
|
|
6788
6972
|
const signature = checker.getResolvedSignature(services.esTreeNodeToTSNodeMap.get(call));
|
|
@@ -6792,7 +6976,7 @@ function contradictoryArrayPredicate(sourceCode, services) {
|
|
|
6792
6976
|
return {
|
|
6793
6977
|
matches,
|
|
6794
6978
|
observeConstructor(member3) {
|
|
6795
|
-
const name =
|
|
6979
|
+
const name = ASTUtils26.getPropertyName(member3, sourceCode.getScope(member3));
|
|
6796
6980
|
if (name === "constructor" || name === null && member3.computed) constructorCapability = true;
|
|
6797
6981
|
},
|
|
6798
6982
|
stable() {
|
|
@@ -6806,7 +6990,7 @@ function plainPrimitiveArray(target, checker) {
|
|
|
6806
6990
|
return element !== void 0 && (element.flags & PRIMITIVE_ELEMENTS) !== 0 && (element.flags & (ts19.TypeFlags.Enum | ts19.TypeFlags.EnumLiteral | ts19.TypeFlags.Intersection)) === 0;
|
|
6807
6991
|
}
|
|
6808
6992
|
function nativeBinding(identifier, sourceCode) {
|
|
6809
|
-
const binding3 =
|
|
6993
|
+
const binding3 = ASTUtils26.findVariable(sourceCode.getScope(identifier), identifier.name);
|
|
6810
6994
|
return binding3 !== null && binding3.defs.length === 0 ? binding3 : void 0;
|
|
6811
6995
|
}
|
|
6812
6996
|
function stableArray(binding3, sourceCode, cache) {
|
|
@@ -6833,8 +7017,8 @@ function typeOnlyReference2(reference) {
|
|
|
6833
7017
|
}
|
|
6834
7018
|
function ordinaryObjectUse(node) {
|
|
6835
7019
|
const member3 = node.parent;
|
|
6836
|
-
if (member3?.type !==
|
|
6837
|
-
const name =
|
|
7020
|
+
if (member3?.type !== AST_NODE_TYPES42.MemberExpression || member3.object !== node) return false;
|
|
7021
|
+
const name = ASTUtils26.getPropertyName(member3);
|
|
6838
7022
|
return name !== null && !OBJECT_REFLECTION2.has(name);
|
|
6839
7023
|
}
|
|
6840
7024
|
function ordinaryArrayReference(reference) {
|
|
@@ -6844,17 +7028,17 @@ function ordinaryArrayReference(reference) {
|
|
|
6844
7028
|
}
|
|
6845
7029
|
function ordinaryArrayUse(node) {
|
|
6846
7030
|
const member3 = node.parent;
|
|
6847
|
-
if (member3?.type ===
|
|
6848
|
-
if (member3?.type !==
|
|
6849
|
-
return member3.parent.type ===
|
|
7031
|
+
if (member3?.type === AST_NODE_TYPES42.TSTypeQuery) return true;
|
|
7032
|
+
if (member3?.type !== AST_NODE_TYPES42.MemberExpression || member3.object !== node || member3.optional || ASTUtils26.getPropertyName(member3) !== "isArray") return false;
|
|
7033
|
+
return member3.parent.type === AST_NODE_TYPES42.CallExpression && member3.parent.callee === member3 && !member3.parent.optional;
|
|
6850
7034
|
}
|
|
6851
7035
|
function ordinaryHostReference(reference) {
|
|
6852
7036
|
if (reference.isWrite()) return false;
|
|
6853
7037
|
if (reference.isTypeReference && !reference.isValueReference) return true;
|
|
6854
7038
|
let node = reference.identifier;
|
|
6855
|
-
while (node.parent?.type ===
|
|
7039
|
+
while (node.parent?.type === AST_NODE_TYPES42.MemberExpression && node.parent.object === node) {
|
|
6856
7040
|
const member3 = node.parent;
|
|
6857
|
-
const name =
|
|
7041
|
+
const name = ASTUtils26.getPropertyName(member3);
|
|
6858
7042
|
if (name === null) return false;
|
|
6859
7043
|
if (name === "Array") return ordinaryArrayUse(member3);
|
|
6860
7044
|
if (name === "Reflect") return false;
|
|
@@ -6940,10 +7124,10 @@ var no_contradictory_type_predicate_default = createRule({
|
|
|
6940
7124
|
const pendingArrays = [];
|
|
6941
7125
|
function inspect(node) {
|
|
6942
7126
|
const annotation = node.returnType?.typeAnnotation;
|
|
6943
|
-
if (node.async || node.generator || node.typeParameters !== void 0 || annotation?.type !==
|
|
7127
|
+
if (node.async || node.generator || node.typeParameters !== void 0 || annotation?.type !== AST_NODE_TYPES43.TSTypePredicate || annotation.asserts || annotation.parameterName.type !== AST_NODE_TYPES43.Identifier || annotation.typeAnnotation === void 0) return;
|
|
6944
7128
|
const name = annotation.parameterName.name;
|
|
6945
7129
|
if (hasSeparatePredicateContract(services.esTreeNodeToTSNodeMap.get(node), checker)) return;
|
|
6946
|
-
const parameter = node.params.find((candidate2) => candidate2.type ===
|
|
7130
|
+
const parameter = node.params.find((candidate2) => candidate2.type === AST_NODE_TYPES43.Identifier && candidate2.name === name);
|
|
6947
7131
|
const expression = singleReturn(node);
|
|
6948
7132
|
if (parameter?.typeAnnotation === void 0 || expression === void 0) return;
|
|
6949
7133
|
const check = typeofCheck(expression);
|
|
@@ -6988,13 +7172,13 @@ function shallowRecordCheck(expression, parameter, input, target, sourceCode, ch
|
|
|
6988
7172
|
const value = unwrapExpression(expression);
|
|
6989
7173
|
const direct = typeofCheck(value);
|
|
6990
7174
|
if (direct !== void 0) return direct.kind === "object" && sameParameter(parameter, direct.parameter, sourceCode);
|
|
6991
|
-
if (value.type !==
|
|
7175
|
+
if (value.type !== AST_NODE_TYPES43.LogicalExpression || value.operator !== "&&") return false;
|
|
6992
7176
|
for (const [left, right] of [[value.left, value.right], [value.right, value.left]]) {
|
|
6993
7177
|
const check = typeofCheck(left);
|
|
6994
7178
|
const excluded = unwrapExpression(right);
|
|
6995
|
-
if (check?.kind !== "object" || !sameParameter(parameter, check.parameter, sourceCode) || excluded.type !==
|
|
7179
|
+
if (check?.kind !== "object" || !sameParameter(parameter, check.parameter, sourceCode) || excluded.type !== AST_NODE_TYPES43.BinaryExpression || excluded.operator !== "!==" && excluded.operator !== "!=") continue;
|
|
6996
7180
|
for (const [tested, sentinel] of [[excluded.left, excluded.right], [excluded.right, excluded.left]]) {
|
|
6997
|
-
if (tested.type ===
|
|
7181
|
+
if (tested.type === AST_NODE_TYPES43.Identifier && sentinel.type === AST_NODE_TYPES43.Literal && sentinel.value === null && sameParameter(parameter, tested, sourceCode)) return true;
|
|
6998
7182
|
}
|
|
6999
7183
|
}
|
|
7000
7184
|
return false;
|
|
@@ -7027,17 +7211,17 @@ function literalKind(type, checker) {
|
|
|
7027
7211
|
}
|
|
7028
7212
|
function singleReturn(node) {
|
|
7029
7213
|
if (node.body === void 0) return void 0;
|
|
7030
|
-
if (node.body.type !==
|
|
7214
|
+
if (node.body.type !== AST_NODE_TYPES43.BlockStatement) return node.body;
|
|
7031
7215
|
const statement = node.body.body[0];
|
|
7032
|
-
return node.body.body.length === 1 && statement?.type ===
|
|
7216
|
+
return node.body.body.length === 1 && statement?.type === AST_NODE_TYPES43.ReturnStatement && statement.argument !== null ? statement.argument : void 0;
|
|
7033
7217
|
}
|
|
7034
7218
|
function typeofCheck(expression) {
|
|
7035
7219
|
const value = unwrapExpression(expression);
|
|
7036
|
-
if (value.type !==
|
|
7220
|
+
if (value.type !== AST_NODE_TYPES43.BinaryExpression || value.operator !== "===" && value.operator !== "==") return void 0;
|
|
7037
7221
|
for (const [tested, expected] of [[value.left, value.right], [value.right, value.left]]) {
|
|
7038
7222
|
const operand = unwrapExpression(tested);
|
|
7039
7223
|
const kind = staticString(expected);
|
|
7040
|
-
if (operand.type !==
|
|
7224
|
+
if (operand.type !== AST_NODE_TYPES43.UnaryExpression || operand.operator !== "typeof" || operand.argument.type !== AST_NODE_TYPES43.Identifier || kind === null || !isRuntimeKind(kind)) continue;
|
|
7041
7225
|
return { parameter: operand.argument, kind };
|
|
7042
7226
|
}
|
|
7043
7227
|
return void 0;
|
|
@@ -7046,8 +7230,8 @@ function isRuntimeKind(value) {
|
|
|
7046
7230
|
return RUNTIME_KINDS.has(value);
|
|
7047
7231
|
}
|
|
7048
7232
|
function sameParameter(declared, tested, sourceCode) {
|
|
7049
|
-
const parameter =
|
|
7050
|
-
return parameter !== null && parameter ===
|
|
7233
|
+
const parameter = ASTUtils27.findVariable(sourceCode.getScope(declared), declared.name);
|
|
7234
|
+
return parameter !== null && parameter === ASTUtils27.findVariable(sourceCode.getScope(tested), tested.name);
|
|
7051
7235
|
}
|
|
7052
7236
|
function inputKinds(type, checker) {
|
|
7053
7237
|
if ((type.flags & ts20.TypeFlags.Unknown) !== 0) return /* @__PURE__ */ new Set(["string", "number", "bigint", "boolean", "symbol", "undefined", "object", "function"]);
|
|
@@ -7091,62 +7275,6 @@ import ts22 from "typescript";
|
|
|
7091
7275
|
// src/rules/_uuid-predicate-witness.ts
|
|
7092
7276
|
import { AST_NODE_TYPES as AST_NODE_TYPES44, ASTUtils as ASTUtils28 } from "@typescript-eslint/utils";
|
|
7093
7277
|
import ts21 from "typescript";
|
|
7094
|
-
|
|
7095
|
-
// src/rules/_native-runtime-unchanged.ts
|
|
7096
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES43, ASTUtils as ASTUtils27 } from "@typescript-eslint/utils";
|
|
7097
|
-
var INDEXES = /* @__PURE__ */ new WeakMap();
|
|
7098
|
-
var GLOBAL_OBJECTS2 = /* @__PURE__ */ new Set(["globalThis", "global", "window", "self"]);
|
|
7099
|
-
function nativeRuntimeUnchanged(sourceCode, name) {
|
|
7100
|
-
const index = runtimeIndex(sourceCode);
|
|
7101
|
-
const cached = index.results.get(name);
|
|
7102
|
-
if (cached !== void 0) return cached;
|
|
7103
|
-
const changed = index.nodes.some((node) => node.type === AST_NODE_TYPES43.MemberExpression && staticPropertyName(node, sourceCode) === "constructor" || name === "RegExp" && node.type === AST_NODE_TYPES43.Literal && "regex" in node) || index.references.some((node) => unsafeReference(node, sourceCode, name));
|
|
7104
|
-
index.results.set(name, !changed);
|
|
7105
|
-
return !changed;
|
|
7106
|
-
}
|
|
7107
|
-
function runtimeIndex(sourceCode) {
|
|
7108
|
-
const cached = INDEXES.get(sourceCode);
|
|
7109
|
-
if (cached !== void 0) return cached;
|
|
7110
|
-
const references = sourceCode.scopeManager?.scopes.flatMap((scope) => scope.references.filter((reference) => reference.isValueReference !== false).map((reference) => reference.identifier)) ?? [];
|
|
7111
|
-
const nodes = [];
|
|
7112
|
-
const pending = [sourceCode.ast];
|
|
7113
|
-
while (pending.length > 0) {
|
|
7114
|
-
const node = pending.pop();
|
|
7115
|
-
if (node === void 0) continue;
|
|
7116
|
-
nodes.push(node);
|
|
7117
|
-
forEachAstChild(node, sourceCode.visitorKeys, (child) => {
|
|
7118
|
-
pending.push(child);
|
|
7119
|
-
});
|
|
7120
|
-
}
|
|
7121
|
-
const index = { references, nodes, results: /* @__PURE__ */ new Map() };
|
|
7122
|
-
INDEXES.set(sourceCode, index);
|
|
7123
|
-
return index;
|
|
7124
|
-
}
|
|
7125
|
-
function unsafeReference(node, sourceCode, name) {
|
|
7126
|
-
if (!ambient(node, sourceCode)) return false;
|
|
7127
|
-
if (node.name === "eval" || node.name === "Function") return true;
|
|
7128
|
-
if (node.name === name) return !nativeRead(node, name);
|
|
7129
|
-
if (!GLOBAL_OBJECTS2.has(node.name)) return false;
|
|
7130
|
-
const value = outerExpression(node);
|
|
7131
|
-
const property = value.parent;
|
|
7132
|
-
if (property?.type !== AST_NODE_TYPES43.MemberExpression || property.object !== value) return true;
|
|
7133
|
-
const key = staticPropertyName(property, sourceCode);
|
|
7134
|
-
if (key === null || key === "eval" || key === "Function" || key === "constructor") return true;
|
|
7135
|
-
return key === name && !nativeRead(property, name);
|
|
7136
|
-
}
|
|
7137
|
-
function ambient(node, sourceCode) {
|
|
7138
|
-
const variable = ASTUtils27.findVariable(sourceCode.getScope(node), node.name);
|
|
7139
|
-
return variable === null || variable.defs.length === 0;
|
|
7140
|
-
}
|
|
7141
|
-
function nativeRead(node, name) {
|
|
7142
|
-
const value = outerExpression(node);
|
|
7143
|
-
const parent = value.parent;
|
|
7144
|
-
if (parent?.type === AST_NODE_TYPES43.UnaryExpression && parent.operator === "typeof") return true;
|
|
7145
|
-
if (name !== "Error") return false;
|
|
7146
|
-
return parent?.type === AST_NODE_TYPES43.NewExpression && parent.callee === value || parent?.type === AST_NODE_TYPES43.BinaryExpression && parent.operator === "instanceof" && parent.right === value;
|
|
7147
|
-
}
|
|
7148
|
-
|
|
7149
|
-
// src/rules/_uuid-predicate-witness.ts
|
|
7150
7278
|
function uuidPredicateWitness(expression, parameter, sourceCode, services) {
|
|
7151
7279
|
const success = unwrapExpression(expression);
|
|
7152
7280
|
if (!member(success, "success")) return void 0;
|
|
@@ -11379,14 +11507,21 @@ function canAutofixNextConfigLiteral(sourceCode) {
|
|
|
11379
11507
|
// src/rules/no-dangerously-allow-svg.ts
|
|
11380
11508
|
var NEXT_CONFIG_RE = /(?:^|\/)next\.config\.[cm]?[jt]s$/;
|
|
11381
11509
|
var NO_DANGEROUSLY_ALLOW_SVG_DOCUMENTATION = {
|
|
11382
|
-
summary: "
|
|
11383
|
-
rationale: "SVG
|
|
11384
|
-
remediation: "
|
|
11510
|
+
summary: "Require an explicit hardening policy for Next Image SVG delivery",
|
|
11511
|
+
rationale: "SVG can contain scripts and other active content. This organizational rule requires a recognized explicit script-blocking sandbox CSP when SVG delivery is enabled, with attachment disposition. It does not establish that framework defaults are missing or that a reported configuration is exploitable.",
|
|
11512
|
+
remediation: "Disable dangerouslyAllowSVG, or configure an explicit literal image contentSecurityPolicy such as `script-src 'none'; sandbox;` and keep attachment disposition. Verify effective headers and defaults against the application's pinned Next version.",
|
|
11385
11513
|
category: "security",
|
|
11386
11514
|
autofix: "safe",
|
|
11515
|
+
references: [
|
|
11516
|
+
"https://www.w3.org/TR/2026/WD-CSP3-20261027/#parse-serialized-policy",
|
|
11517
|
+
"https://github.com/vercel/next.js/blob/v16.4.3/packages/next/src/shared/lib/image-config.ts#L255"
|
|
11518
|
+
],
|
|
11387
11519
|
limitations: [
|
|
11388
11520
|
"Automatic boolean changes are withheld when the module contains explicit TypeScript or JSDoc contracts; those contracts can constrain an aliased property to literal true. Plain objects and as const inference remain fixable.",
|
|
11389
|
-
"
|
|
11521
|
+
"This rule does not resolve the installed Next version or evaluate effective response headers. The inspected Next 16.4.3 defaults already block scripts, apply sandbox, and use attachment disposition. A report for omitted explicit CSP is a policy finding, not proof of XSS.",
|
|
11522
|
+
"Omitted contentDispositionType is treated as attachment. Older or customized runtime defaults are not established by this source-only check.",
|
|
11523
|
+
"Only a bounded literal CSP subset is recognized: the first script-src must contain only 'none', and the first sandbox must have no tokens. Directive names and separators use CSP ASCII syntax. Valid policy lists, default-src fallbacks and other equivalent policies are not proved; omitted, dynamic or unrecognized explicit policies can still report. This is not a general CSP validator or proof of runtime security.",
|
|
11524
|
+
"Automatic fixes disable SVG opt-in to satisfy this policy; recognized hardened configurations are preserved. Only literal effective properties of a directly exported object, unescaped const alias, or isolated module.exports object are analyzed. Wrappers, factories, spreads, dynamic computed keys and mutations are not inferred."
|
|
11390
11525
|
],
|
|
11391
11526
|
examples: [
|
|
11392
11527
|
{
|
|
@@ -11400,7 +11535,7 @@ var NO_DANGEROUSLY_ALLOW_SVG_DOCUMENTATION = {
|
|
|
11400
11535
|
},
|
|
11401
11536
|
{
|
|
11402
11537
|
id: "svg-enabled",
|
|
11403
|
-
title: "
|
|
11538
|
+
title: "SVG opt-in requires explicit hardening under this policy",
|
|
11404
11539
|
outcome: "match",
|
|
11405
11540
|
files: [{ path: "next.config.mjs", source: "export default { images: { dangerouslyAllowSVG: true } };\n" }],
|
|
11406
11541
|
focusPath: "next.config.mjs",
|
|
@@ -11409,12 +11544,34 @@ var NO_DANGEROUSLY_ALLOW_SVG_DOCUMENTATION = {
|
|
|
11409
11544
|
},
|
|
11410
11545
|
{
|
|
11411
11546
|
id: "safe-autofix",
|
|
11412
|
-
title: "
|
|
11547
|
+
title: "Disable SVG delivery to satisfy this policy",
|
|
11413
11548
|
outcome: "match",
|
|
11414
11549
|
files: [{ path: "next.config.ts", source: "export default { images: { dangerouslyAllowSVG: true } };" }],
|
|
11415
11550
|
fixedFiles: [{ path: "next.config.ts", source: "export default { images: { dangerouslyAllowSVG: false } };" }],
|
|
11416
11551
|
focusPath: "next.config.ts",
|
|
11417
11552
|
expectedCount: 1
|
|
11553
|
+
},
|
|
11554
|
+
{
|
|
11555
|
+
id: "svg-explicit-hardening",
|
|
11556
|
+
scenarioId: "explicit-hardening",
|
|
11557
|
+
title: "Allow SVG delivery with explicit hardening",
|
|
11558
|
+
outcome: "no-match",
|
|
11559
|
+
files: [{ path: "next.config.mjs", source: `export default { images: { dangerouslyAllowSVG: true, contentDispositionType: "attachment", contentSecurityPolicy: "script-src 'none'; sandbox;" } };
|
|
11560
|
+
` }],
|
|
11561
|
+
focusPath: "next.config.mjs",
|
|
11562
|
+
expectedCount: 0,
|
|
11563
|
+
public: true
|
|
11564
|
+
},
|
|
11565
|
+
{
|
|
11566
|
+
id: "svg-unsafe-first-directive",
|
|
11567
|
+
scenarioId: "explicit-hardening",
|
|
11568
|
+
title: "A later duplicate cannot replace the effective policy",
|
|
11569
|
+
outcome: "match",
|
|
11570
|
+
files: [{ path: "next.config.mjs", source: `export default { images: { dangerouslyAllowSVG: true, contentDispositionType: "attachment", contentSecurityPolicy: "script-src 'unsafe-inline'; script-src 'none'; sandbox;" } };
|
|
11571
|
+
` }],
|
|
11572
|
+
focusPath: "next.config.mjs",
|
|
11573
|
+
expectedCount: 1,
|
|
11574
|
+
public: true
|
|
11418
11575
|
}
|
|
11419
11576
|
]
|
|
11420
11577
|
};
|
|
@@ -11424,12 +11581,16 @@ function literalString2(node) {
|
|
|
11424
11581
|
return null;
|
|
11425
11582
|
}
|
|
11426
11583
|
function hasHardenedSvgPolicy(policy) {
|
|
11427
|
-
const directives =
|
|
11428
|
-
const
|
|
11429
|
-
|
|
11430
|
-
|
|
11431
|
-
|
|
11432
|
-
|
|
11584
|
+
const directives = /* @__PURE__ */ new Map();
|
|
11585
|
+
for (const part of policy.split(";")) {
|
|
11586
|
+
const [name, ...values] = part.split(/[\t\n\f\r ]+/u).filter(Boolean);
|
|
11587
|
+
if (name === void 0 || !/^[A-Za-z0-9-]+$/u.test(name)) continue;
|
|
11588
|
+
const key = name.toLowerCase();
|
|
11589
|
+
if (!directives.has(key)) directives.set(key, values);
|
|
11590
|
+
}
|
|
11591
|
+
const scriptSource = directives.get("script-src");
|
|
11592
|
+
const sandbox = directives.get("sandbox");
|
|
11593
|
+
return scriptSource?.length === 1 && scriptSource[0]?.toLowerCase() === "'none'" && sandbox?.length === 0;
|
|
11433
11594
|
}
|
|
11434
11595
|
var no_dangerously_allow_svg_default = createRule({
|
|
11435
11596
|
name: "no-dangerously-allow-svg",
|
|
@@ -11440,7 +11601,7 @@ var no_dangerously_allow_svg_default = createRule({
|
|
|
11440
11601
|
docs: { description: NO_DANGEROUSLY_ALLOW_SVG_DOCUMENTATION.summary },
|
|
11441
11602
|
schema: [],
|
|
11442
11603
|
messages: {
|
|
11443
|
-
noDangerouslyAllowSvg: "
|
|
11604
|
+
noDangerouslyAllowSvg: "SVG opt-in requires a recognized explicit script-blocking sandbox CSP and attachment disposition under this policy."
|
|
11444
11605
|
}
|
|
11445
11606
|
},
|
|
11446
11607
|
defaultOptions: [],
|
|
@@ -17777,7 +17938,7 @@ var NO_RAW_FETCH_OUTSIDE_CLIENTS_DOCUMENTATION = {
|
|
|
17777
17938
|
rationale: "Scattered fetch calls bypass shared transport policy and are harder to stub and observe consistently.",
|
|
17778
17939
|
remediation: "Move the request into a client module and call that abstraction from application code.",
|
|
17779
17940
|
category: "architecture",
|
|
17780
|
-
limitations: ["Tests, client-layer paths, constructed handoffs, and pre-signed URL transfers are excluded. Configure the same literal Next.js basePath here and on prefer-server-actions so one rule owns each internal mutation.", "Effect and pre-signed-transfer exemptions use recognized syntax and naming conventions, not complete React or URL provenance. Those conservative exclusions are recall limitations, not evidence that every excluded request satisfies transport policy."],
|
|
17941
|
+
limitations: ["Tests, client-layer paths, constructed handoffs, and pre-signed URL transfers are excluded. Configure the same literal Next.js basePath here and on prefer-server-actions so one rule owns each internal mutation.", "Effect and pre-signed-transfer exemptions use recognized syntax and naming conventions, not complete React or URL provenance. Those conservative exclusions are recall limitations, not evidence that every excluded request satisfies transport policy.", "Unshadowed native members and bounded stable const aliases or single-property destructuring are recognized. Visible writes, callable escapes, whole-global escapes and mutation capabilities anywhere in the file invalidate that proof, including earlier captures. Known unrelated global member writes and typeof global checks do not. Static constructor members and destructuring projections invalidate the proof; indirect reflection, external monkeypatches and arbitrary forwarding functions are not inferred."],
|
|
17781
17942
|
examples: [
|
|
17782
17943
|
{ id: "client-call", title: "Use a client abstraction", outcome: "no-match", files: [{ path: "src/routes/handler.ts", source: "const response = await billingClient.getInvoice(id);" }], focusPath: "src/routes/handler.ts", expectedCount: 0, public: true },
|
|
17783
17944
|
{ id: "raw-fetch", title: "Do not call global fetch here", outcome: "match", files: [{ path: "src/routes/handler.ts", source: "const response = await fetch('/api/invoices');" }], focusPath: "src/routes/handler.ts", expectedCount: 1, public: true }
|
|
@@ -17798,11 +17959,6 @@ var DEFAULT_ALLOW = [
|
|
|
17798
17959
|
"[\\\\/][^\\\\/]*(?:Client|client)\\.[cm]?[jt]sx?$"
|
|
17799
17960
|
];
|
|
17800
17961
|
var NON_PRODUCTION_TREE_RE = /[\\/](playwright|cypress|__testfixtures__)[\\/]/;
|
|
17801
|
-
var GLOBAL_RECEIVERS3 = /* @__PURE__ */ new Set([
|
|
17802
|
-
"globalThis",
|
|
17803
|
-
"window",
|
|
17804
|
-
"self"
|
|
17805
|
-
]);
|
|
17806
17962
|
var PRESIGNED_URL_NAME_RE = /(?:pre-?signed|signed|upload|download)Url$/i;
|
|
17807
17963
|
var INTERNAL_MUTATION_METHODS = /* @__PURE__ */ new Set([
|
|
17808
17964
|
"POST",
|
|
@@ -17826,23 +17982,13 @@ var BASE_PATH_RE = /^\/(?!$)(?!.*[?#])(?:[^/]+\/)*[^/]+$/u;
|
|
|
17826
17982
|
function isValidBasePath(basePath) {
|
|
17827
17983
|
return BASE_PATH_RE.test(basePath) && !basePath.split("/").some((segment) => segment === "." || segment === "..");
|
|
17828
17984
|
}
|
|
17829
|
-
function isGlobalFetchCall(node, resolvesToGlobal) {
|
|
17830
|
-
const callee = unwrapExpression(node.callee);
|
|
17831
|
-
if (callee.type === "Identifier") {
|
|
17832
|
-
return callee.name === "fetch" && resolvesToGlobal(callee);
|
|
17833
|
-
}
|
|
17834
|
-
if (callee.type === "MemberExpression" && !callee.computed && callee.property.type === "Identifier" && callee.property.name === "fetch" && callee.object.type === "Identifier") {
|
|
17835
|
-
return GLOBAL_RECEIVERS3.has(callee.object.name) && resolvesToGlobal(callee.object);
|
|
17836
|
-
}
|
|
17837
|
-
return false;
|
|
17838
|
-
}
|
|
17839
17985
|
function isConstructedArgumentHandoff(node, resolvesToGlobal) {
|
|
17840
17986
|
const [first] = node.arguments;
|
|
17841
17987
|
return node.arguments.length === 1 && first !== void 0 && first.type === AST_NODE_TYPES98.NewExpression && first.callee.type === AST_NODE_TYPES98.Identifier && (first.callee.name === "URL" || first.callee.name === "Request") && resolvesToGlobal(first.callee);
|
|
17842
17988
|
}
|
|
17843
17989
|
function effectOwns(node) {
|
|
17844
17990
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
17845
|
-
if (unwrappedNodeCallee.type !== AST_NODE_TYPES98.Identifier) return false;
|
|
17991
|
+
if (unwrappedNodeCallee.type !== AST_NODE_TYPES98.Identifier || unwrappedNodeCallee.name !== "fetch") return false;
|
|
17846
17992
|
const method = readDirectMethod(node);
|
|
17847
17993
|
if (method !== null && method !== "GET") return false;
|
|
17848
17994
|
const first = node.arguments[0];
|
|
@@ -17979,7 +18125,7 @@ var no_raw_fetch_outside_clients_default = createRule({
|
|
|
17979
18125
|
}
|
|
17980
18126
|
function serverActionOwns(node) {
|
|
17981
18127
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
17982
|
-
if (unwrappedNodeCallee.type !== AST_NODE_TYPES98.Identifier || !hasUseClientDirective || hasUseServerDirective2 || importsServerOnly || SERVER_ACTION_SKIP_FILE_RE.test(filename) || nonReactFramework) {
|
|
18128
|
+
if (unwrappedNodeCallee.type !== AST_NODE_TYPES98.Identifier || unwrappedNodeCallee.name !== "fetch" || !resolvesToGlobal(unwrappedNodeCallee) || !hasUseClientDirective || hasUseServerDirective2 || importsServerOnly || SERVER_ACTION_SKIP_FILE_RE.test(filename) || nonReactFramework) {
|
|
17983
18129
|
return false;
|
|
17984
18130
|
}
|
|
17985
18131
|
const url = node.arguments[0];
|
|
@@ -18036,7 +18182,7 @@ var no_raw_fetch_outside_clients_default = createRule({
|
|
|
18036
18182
|
}
|
|
18037
18183
|
return {
|
|
18038
18184
|
CallExpression(node) {
|
|
18039
|
-
if (!
|
|
18185
|
+
if (!nativeFetchReference(unwrapExpression(node.callee), context.sourceCode)) {
|
|
18040
18186
|
return;
|
|
18041
18187
|
}
|
|
18042
18188
|
if (isPresignedUrlTransfer(node) || isConstructedArgumentHandoff(node, resolvesToGlobal) || effectOwns(node) || serverActionOwns(node)) {
|
|
@@ -32726,6 +32872,7 @@ var REQUIRE_FETCH_TIMEOUT_DOCUMENTATION = {
|
|
|
32726
32872
|
limitations: [
|
|
32727
32873
|
"Signal presence establishes an explicit cancellation path, not a guaranteed timeout. Literal null, global undefined, and void 0 do not provide a signal. Erased TypeScript wrappers preserve the same analysis. Unknown spreads and dynamic values are not inferred. Forwarded Request objects retain their signal unless an init explicitly resets it to null.",
|
|
32728
32874
|
"Unshadowed native fetch members and bounded stable const aliases or destructuring are recognized. Reassigned, defaulted and unknown aliases and arbitrary forwarding functions are excluded.",
|
|
32875
|
+
"Visible writes, callable escapes, whole-global escapes and mutation capabilities anywhere in the file invalidate native fetch identity, including earlier captures. Known unrelated global member writes and typeof global checks do not. Static constructor members and destructuring projections invalidate the proof; indirect reflection and external monkeypatches are not inferred.",
|
|
32729
32876
|
"Accessors and unproved prototypes are excluded because native option conversion can attach or replace a signal before it is read."
|
|
32730
32877
|
],
|
|
32731
32878
|
examples: [
|
|
@@ -32772,7 +32919,7 @@ function emptySignal(expression, resolvesToGlobal) {
|
|
|
32772
32919
|
}
|
|
32773
32920
|
return null;
|
|
32774
32921
|
}
|
|
32775
|
-
function initSignalState(init, resolvesToGlobal) {
|
|
32922
|
+
function initSignalState(init, resolvesToGlobal, sourceCode) {
|
|
32776
32923
|
init = unwrapExpression(init);
|
|
32777
32924
|
if (init.type !== AST_NODE_TYPES159.ObjectExpression) return "unknown";
|
|
32778
32925
|
let state = "absent";
|
|
@@ -32782,12 +32929,12 @@ function initSignalState(init, resolvesToGlobal) {
|
|
|
32782
32929
|
continue;
|
|
32783
32930
|
}
|
|
32784
32931
|
if (prop.kind !== "init" || hasUnprovedPrototype(prop)) return "unknown";
|
|
32785
|
-
const
|
|
32786
|
-
if (
|
|
32932
|
+
const name = staticPropertyName(prop, sourceCode);
|
|
32933
|
+
if (name === "signal") {
|
|
32787
32934
|
state = !prop.method ? emptySignal(prop.value, resolvesToGlobal) ?? "unknown" : "unknown";
|
|
32788
|
-
} else if (!prop.computed &&
|
|
32935
|
+
} else if (!prop.computed && name === "__proto__" && state === "absent") {
|
|
32789
32936
|
state = "unknown";
|
|
32790
|
-
} else if (prop.computed &&
|
|
32937
|
+
} else if (prop.computed && name === null) {
|
|
32791
32938
|
state = "unknown";
|
|
32792
32939
|
}
|
|
32793
32940
|
}
|
|
@@ -32865,7 +33012,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
32865
33012
|
return "unknown";
|
|
32866
33013
|
}
|
|
32867
33014
|
}
|
|
32868
|
-
return initSignalState(definition.node.init, resolvesToGlobal);
|
|
33015
|
+
return initSignalState(definition.node.init, resolvesToGlobal, context.sourceCode);
|
|
32869
33016
|
}
|
|
32870
33017
|
function isForwardedRequest(argument) {
|
|
32871
33018
|
let value = unwrapExpression(argument);
|
|
@@ -32893,7 +33040,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
32893
33040
|
}
|
|
32894
33041
|
const [first, rawInit] = node.arguments;
|
|
32895
33042
|
const init = rawInit === void 0 ? void 0 : unwrapExpression(rawInit);
|
|
32896
|
-
const state = init === void 0 ? "unknown" : init.type === AST_NODE_TYPES159.Identifier ? localConstInitSignalState(init) : initSignalState(init, resolvesToGlobal);
|
|
33043
|
+
const state = init === void 0 ? "unknown" : init.type === AST_NODE_TYPES159.Identifier ? localConstInitSignalState(init) : initSignalState(init, resolvesToGlobal, context.sourceCode);
|
|
32897
33044
|
if (first !== void 0 && (node.arguments.length === 1 && !isInlineUrl(first, resolvesToGlobal) || isForwardedRequest(first) && state !== "null")) {
|
|
32898
33045
|
return;
|
|
32899
33046
|
}
|