@sarj/eslint-plugin 15.8.1 → 15.9.0
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 +1214 -1045
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +282 -112
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4679,11 +4679,11 @@ var no_offset_pagination_default = createRule({
|
|
|
4679
4679
|
// src/rules/no-positional-tuple-return.ts
|
|
4680
4680
|
import { AST_NODE_TYPES as AST_NODE_TYPES18 } from "@typescript-eslint/utils";
|
|
4681
4681
|
var noPositionalTupleReturnDocumentation = {
|
|
4682
|
-
summary: "Disallow returning a multi-field tuple from
|
|
4683
|
-
rationale: "
|
|
4682
|
+
summary: "Disallow returning a multi-field tuple from a named function; return a named object so call sites cannot mismatch slots.",
|
|
4683
|
+
rationale: "Tuple fields are identified only by position, so reordering can preserve types while changing meaning.",
|
|
4684
4684
|
remediation: "Return an object whose property names describe each value.",
|
|
4685
4685
|
category: "maintainability",
|
|
4686
|
-
limitations: ["
|
|
4686
|
+
limitations: ["Declared or syntax-proven multi-field tuple returns on named functions and public type surfaces are inspected; anonymous inline callbacks and syntax-proven TanStack Query key factories are excluded."],
|
|
4687
4687
|
examples: [
|
|
4688
4688
|
{ id: "named-object-return", title: "Return named fields", outcome: "no-match", files: [{ path: "src/download.ts", source: "export function download(): { body: string; status: number } { return impl(); }" }], focusPath: "src/download.ts", expectedCount: 0, public: true },
|
|
4689
4689
|
{ id: "tuple-return", title: "Do not expose positional fields", outcome: "match", files: [{ path: "src/download.ts", source: "export function download(): [string, number] { return impl(); }" }], focusPath: "src/download.ts", expectedCount: 1, public: true }
|
|
@@ -4721,6 +4721,16 @@ function tupleReturnType(node, aliases, resolving = /* @__PURE__ */ new Set()) {
|
|
|
4721
4721
|
}
|
|
4722
4722
|
return null;
|
|
4723
4723
|
}
|
|
4724
|
+
function tupleExpression(node, aliases) {
|
|
4725
|
+
if (node.type !== AST_NODE_TYPES18.TSAsExpression && node.type !== AST_NODE_TYPES18.TSSatisfiesExpression) {
|
|
4726
|
+
return null;
|
|
4727
|
+
}
|
|
4728
|
+
if (node.expression.type !== AST_NODE_TYPES18.ArrayExpression || node.expression.elements.length < MIN_ELEMENTS) {
|
|
4729
|
+
return null;
|
|
4730
|
+
}
|
|
4731
|
+
if (node.type === AST_NODE_TYPES18.TSAsExpression && node.typeAnnotation.type === AST_NODE_TYPES18.TSTypeReference && node.typeAnnotation.typeName.type === AST_NODE_TYPES18.Identifier && node.typeAnnotation.typeName.name === "const") return node.expression;
|
|
4732
|
+
return tupleReturnType(node.typeAnnotation, aliases) === null ? null : node.expression;
|
|
4733
|
+
}
|
|
4724
4734
|
function functionName(node) {
|
|
4725
4735
|
if (node.type === AST_NODE_TYPES18.FunctionDeclaration) {
|
|
4726
4736
|
if (node.id !== null) return node.id.name;
|
|
@@ -4736,60 +4746,25 @@ function functionName(node) {
|
|
|
4736
4746
|
return parent.id.name;
|
|
4737
4747
|
}
|
|
4738
4748
|
if ((parent?.type === AST_NODE_TYPES18.MethodDefinition || parent?.type === AST_NODE_TYPES18.TSAbstractMethodDefinition || parent?.type === AST_NODE_TYPES18.PropertyDefinition || parent?.type === AST_NODE_TYPES18.Property) && parent.key.type === AST_NODE_TYPES18.Identifier) {
|
|
4739
|
-
if ((parent.type === AST_NODE_TYPES18.MethodDefinition || parent.type === AST_NODE_TYPES18.TSAbstractMethodDefinition || parent.type === AST_NODE_TYPES18.PropertyDefinition) && (parent.accessibility === "private" || parent.accessibility === "protected")) return null;
|
|
4740
4749
|
return parent.key.name;
|
|
4741
4750
|
}
|
|
4742
4751
|
return null;
|
|
4743
4752
|
}
|
|
4744
|
-
function
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
return false;
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
}
|
|
4759
|
-
if (current.parent?.type !== AST_NODE_TYPES18.Program) {
|
|
4760
|
-
return null;
|
|
4761
|
-
}
|
|
4762
|
-
let topLevel = current;
|
|
4763
|
-
if (current.type === AST_NODE_TYPES18.ExportNamedDeclaration || current.type === AST_NODE_TYPES18.ExportDefaultDeclaration) {
|
|
4764
|
-
topLevel = current.declaration;
|
|
4765
|
-
}
|
|
4766
|
-
if (topLevel === null) return null;
|
|
4767
|
-
if (topLevel.type === AST_NODE_TYPES18.FunctionDeclaration) {
|
|
4768
|
-
if (topLevel !== node) return null;
|
|
4769
|
-
return topLevel.id?.name ?? (current.type === AST_NODE_TYPES18.ExportDefaultDeclaration ? "default" : null);
|
|
4770
|
-
}
|
|
4771
|
-
if ((topLevel.type === AST_NODE_TYPES18.ArrowFunctionExpression || topLevel.type === AST_NODE_TYPES18.FunctionExpression) && topLevel === node && current.type === AST_NODE_TYPES18.ExportDefaultDeclaration) {
|
|
4772
|
-
return "default";
|
|
4773
|
-
}
|
|
4774
|
-
if (topLevel.type === AST_NODE_TYPES18.ClassDeclaration) {
|
|
4775
|
-
let owner = node.parent;
|
|
4776
|
-
while (owner != null && owner.parent !== topLevel.body) owner = owner.parent;
|
|
4777
|
-
return (owner?.type === AST_NODE_TYPES18.MethodDefinition || owner?.type === AST_NODE_TYPES18.TSAbstractMethodDefinition || owner?.type === AST_NODE_TYPES18.PropertyDefinition) && owner.value === node ? topLevel.id?.name ?? (current.type === AST_NODE_TYPES18.ExportDefaultDeclaration ? "default" : null) : null;
|
|
4778
|
-
}
|
|
4779
|
-
if (topLevel.type === AST_NODE_TYPES18.VariableDeclaration) {
|
|
4780
|
-
for (const declarator of topLevel.declarations) {
|
|
4781
|
-
let initializer = declarator.init;
|
|
4782
|
-
while (initializer?.type === AST_NODE_TYPES18.TSAsExpression || initializer?.type === AST_NODE_TYPES18.TSSatisfiesExpression || initializer?.type === AST_NODE_TYPES18.TSNonNullExpression) initializer = initializer.expression;
|
|
4783
|
-
if (declarator.id.type === AST_NODE_TYPES18.Identifier && initializer === node) return declarator.id.name;
|
|
4784
|
-
if (declarator.id.type === AST_NODE_TYPES18.Identifier && (initializer?.type === AST_NODE_TYPES18.ClassExpression || initializer?.type === AST_NODE_TYPES18.ObjectExpression)) {
|
|
4785
|
-
let owner = node.parent;
|
|
4786
|
-
const container = initializer.type === AST_NODE_TYPES18.ClassExpression ? initializer.body : initializer;
|
|
4787
|
-
while (owner != null && owner.parent !== container) owner = owner.parent;
|
|
4788
|
-
if ((owner?.type === AST_NODE_TYPES18.MethodDefinition || owner?.type === AST_NODE_TYPES18.PropertyDefinition || owner?.type === AST_NODE_TYPES18.Property) && owner.value === node) return declarator.id.name;
|
|
4789
|
-
}
|
|
4790
|
-
}
|
|
4791
|
-
}
|
|
4792
|
-
return null;
|
|
4753
|
+
function isQueryKeyFactory(node) {
|
|
4754
|
+
let wrapped = node;
|
|
4755
|
+
while ((wrapped.parent?.type === AST_NODE_TYPES18.TSAsExpression || wrapped.parent?.type === AST_NODE_TYPES18.TSSatisfiesExpression || wrapped.parent?.type === AST_NODE_TYPES18.TSNonNullExpression) && wrapped.parent.expression === wrapped) wrapped = wrapped.parent;
|
|
4756
|
+
const property = wrapped.parent;
|
|
4757
|
+
if (property?.type !== AST_NODE_TYPES18.Property || property.value !== wrapped) return false;
|
|
4758
|
+
const object = property.parent;
|
|
4759
|
+
if (object.type !== AST_NODE_TYPES18.ObjectExpression) return false;
|
|
4760
|
+
const assertion = object.parent;
|
|
4761
|
+
if (assertion.type !== AST_NODE_TYPES18.TSAsExpression || assertion.expression !== object || assertion.typeAnnotation.type !== AST_NODE_TYPES18.TSTypeReference || assertion.typeAnnotation.typeName.type !== AST_NODE_TYPES18.Identifier || assertion.typeAnnotation.typeName.name !== "const") return false;
|
|
4762
|
+
const declarator = assertion.parent;
|
|
4763
|
+
if (declarator.type !== AST_NODE_TYPES18.VariableDeclarator || declarator.id.type !== AST_NODE_TYPES18.Identifier || !/Keys$/i.test(declarator.id.name) || declarator.parent.type !== AST_NODE_TYPES18.VariableDeclaration || declarator.parent.kind !== "const") return false;
|
|
4764
|
+
return object.properties.some((candidate) => {
|
|
4765
|
+
if (candidate.type !== AST_NODE_TYPES18.Property || staticMemberName3(candidate.key) !== "all") return false;
|
|
4766
|
+
return candidate.value.type === AST_NODE_TYPES18.TSAsExpression && candidate.value.expression.type === AST_NODE_TYPES18.ArrayExpression && candidate.value.typeAnnotation.type === AST_NODE_TYPES18.TSTypeReference && candidate.value.typeAnnotation.typeName.type === AST_NODE_TYPES18.Identifier && candidate.value.typeAnnotation.typeName.name === "const";
|
|
4767
|
+
});
|
|
4793
4768
|
}
|
|
4794
4769
|
function specifierExportedNames(program) {
|
|
4795
4770
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -4898,18 +4873,52 @@ function isExportedClass(node, specifierExports) {
|
|
|
4898
4873
|
if (node.parent.type === AST_NODE_TYPES18.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES18.Identifier) return specifierExports.has(node.parent.id.name) || isInlineExported(node);
|
|
4899
4874
|
return false;
|
|
4900
4875
|
}
|
|
4901
|
-
function
|
|
4902
|
-
|
|
4876
|
+
function isInlineExported(node) {
|
|
4877
|
+
if (moduleScopeBindingName(node) === null) return false;
|
|
4878
|
+
for (let current = node; current != null; current = current.parent) {
|
|
4879
|
+
const parent = current.parent;
|
|
4880
|
+
if (parent?.type === AST_NODE_TYPES18.ExportNamedDeclaration || parent?.type === AST_NODE_TYPES18.ExportDefaultDeclaration) {
|
|
4881
|
+
return true;
|
|
4882
|
+
}
|
|
4883
|
+
}
|
|
4884
|
+
return false;
|
|
4903
4885
|
}
|
|
4904
|
-
function
|
|
4905
|
-
|
|
4906
|
-
|
|
4886
|
+
function moduleScopeBindingName(node) {
|
|
4887
|
+
let current = node;
|
|
4888
|
+
while (current.parent != null && current.parent.type !== AST_NODE_TYPES18.Program) {
|
|
4889
|
+
current = current.parent;
|
|
4907
4890
|
}
|
|
4908
|
-
if (
|
|
4909
|
-
|
|
4891
|
+
if (current.parent?.type !== AST_NODE_TYPES18.Program) return null;
|
|
4892
|
+
let topLevel = current;
|
|
4893
|
+
if (current.type === AST_NODE_TYPES18.ExportNamedDeclaration || current.type === AST_NODE_TYPES18.ExportDefaultDeclaration) topLevel = current.declaration;
|
|
4894
|
+
if (topLevel === null) return null;
|
|
4895
|
+
if (topLevel.type === AST_NODE_TYPES18.FunctionDeclaration) {
|
|
4896
|
+
if (topLevel !== node) return null;
|
|
4897
|
+
return topLevel.id?.name ?? (current.type === AST_NODE_TYPES18.ExportDefaultDeclaration ? "default" : null);
|
|
4910
4898
|
}
|
|
4911
|
-
|
|
4912
|
-
|
|
4899
|
+
if ((topLevel.type === AST_NODE_TYPES18.ArrowFunctionExpression || topLevel.type === AST_NODE_TYPES18.FunctionExpression) && topLevel === node && current.type === AST_NODE_TYPES18.ExportDefaultDeclaration) return "default";
|
|
4900
|
+
if (topLevel.type === AST_NODE_TYPES18.ClassDeclaration) {
|
|
4901
|
+
let owner = node.parent;
|
|
4902
|
+
while (owner != null && owner.parent !== topLevel.body) owner = owner.parent;
|
|
4903
|
+
return (owner?.type === AST_NODE_TYPES18.MethodDefinition || owner?.type === AST_NODE_TYPES18.TSAbstractMethodDefinition || owner?.type === AST_NODE_TYPES18.PropertyDefinition) && owner.value === node ? topLevel.id?.name ?? (current.type === AST_NODE_TYPES18.ExportDefaultDeclaration ? "default" : null) : null;
|
|
4904
|
+
}
|
|
4905
|
+
if (topLevel.type === AST_NODE_TYPES18.VariableDeclaration) {
|
|
4906
|
+
for (const declarator of topLevel.declarations) {
|
|
4907
|
+
let initializer = declarator.init;
|
|
4908
|
+
while (initializer?.type === AST_NODE_TYPES18.TSAsExpression || initializer?.type === AST_NODE_TYPES18.TSSatisfiesExpression || initializer?.type === AST_NODE_TYPES18.TSNonNullExpression) initializer = initializer.expression;
|
|
4909
|
+
if (declarator.id.type === AST_NODE_TYPES18.Identifier && initializer === node) return declarator.id.name;
|
|
4910
|
+
if (declarator.id.type === AST_NODE_TYPES18.Identifier && (initializer?.type === AST_NODE_TYPES18.ClassExpression || initializer?.type === AST_NODE_TYPES18.ObjectExpression)) {
|
|
4911
|
+
let owner = node.parent;
|
|
4912
|
+
const container = initializer.type === AST_NODE_TYPES18.ClassExpression ? initializer.body : initializer;
|
|
4913
|
+
while (owner != null && owner.parent !== container) owner = owner.parent;
|
|
4914
|
+
if ((owner?.type === AST_NODE_TYPES18.MethodDefinition || owner?.type === AST_NODE_TYPES18.PropertyDefinition || owner?.type === AST_NODE_TYPES18.Property) && owner.value === node) return declarator.id.name;
|
|
4915
|
+
}
|
|
4916
|
+
}
|
|
4917
|
+
}
|
|
4918
|
+
return null;
|
|
4919
|
+
}
|
|
4920
|
+
function isExportedInterface(node, exports) {
|
|
4921
|
+
return node.parent.type === AST_NODE_TYPES18.ExportNamedDeclaration || node.parent.type === AST_NODE_TYPES18.ExportDefaultDeclaration || node.parent.type === AST_NODE_TYPES18.Program && exports.has(node.id.name);
|
|
4913
4922
|
}
|
|
4914
4923
|
var no_positional_tuple_return_default = createRule({
|
|
4915
4924
|
name: "no-positional-tuple-return",
|
|
@@ -4917,11 +4926,11 @@ var no_positional_tuple_return_default = createRule({
|
|
|
4917
4926
|
meta: {
|
|
4918
4927
|
type: "suggestion",
|
|
4919
4928
|
docs: {
|
|
4920
|
-
description: "Disallow returning a multi-field tuple from
|
|
4929
|
+
description: "Disallow returning a multi-field tuple from a named function; return a named object so call sites cannot mismatch slots."
|
|
4921
4930
|
},
|
|
4922
4931
|
schema: [],
|
|
4923
4932
|
messages: {
|
|
4924
|
-
noPositionalTupleReturn: "
|
|
4933
|
+
noPositionalTupleReturn: "`{{name}}` returns a {{count}}-field tuple, so callers depend on positional slots that can be reordered silently. Return a named object instead."
|
|
4925
4934
|
}
|
|
4926
4935
|
},
|
|
4927
4936
|
defaultOptions: [],
|
|
@@ -4933,6 +4942,8 @@ var no_positional_tuple_return_default = createRule({
|
|
|
4933
4942
|
exportedTypeNames(context.sourceCode.ast)
|
|
4934
4943
|
);
|
|
4935
4944
|
const aliases = typeAliases(context.sourceCode.ast);
|
|
4945
|
+
const reportedFunctions = /* @__PURE__ */ new WeakSet();
|
|
4946
|
+
const functionStack = [];
|
|
4936
4947
|
const report = (annotation, name) => {
|
|
4937
4948
|
const tuple = tupleReturnType(annotation, aliases);
|
|
4938
4949
|
if (tuple === null || tuple.elementTypes.length < MIN_ELEMENTS) return;
|
|
@@ -4942,25 +4953,54 @@ var no_positional_tuple_return_default = createRule({
|
|
|
4942
4953
|
data: { name, count: String(tuple.elementTypes.length) }
|
|
4943
4954
|
});
|
|
4944
4955
|
};
|
|
4956
|
+
const reportExpression = (node, expression) => {
|
|
4957
|
+
if (reportedFunctions.has(node)) return;
|
|
4958
|
+
const tuple = tupleExpression(expression, aliases);
|
|
4959
|
+
const name = functionName(node);
|
|
4960
|
+
if (tuple === null || name === null) return;
|
|
4961
|
+
reportedFunctions.add(node);
|
|
4962
|
+
context.report({
|
|
4963
|
+
node: tuple,
|
|
4964
|
+
messageId: "noPositionalTupleReturn",
|
|
4965
|
+
data: { name, count: String(tuple.elements.length) }
|
|
4966
|
+
});
|
|
4967
|
+
};
|
|
4945
4968
|
const check = (node) => {
|
|
4969
|
+
if (isQueryKeyFactory(node)) return;
|
|
4946
4970
|
const annotation = node.returnType?.typeAnnotation;
|
|
4947
4971
|
if (annotation === void 0) {
|
|
4972
|
+
if (node.type === AST_NODE_TYPES18.ArrowFunctionExpression && node.expression) {
|
|
4973
|
+
reportExpression(node, node.body);
|
|
4974
|
+
}
|
|
4948
4975
|
return;
|
|
4949
4976
|
}
|
|
4950
4977
|
const name = functionName(node);
|
|
4951
4978
|
if (name === null) {
|
|
4952
4979
|
return;
|
|
4953
4980
|
}
|
|
4954
|
-
if (!isExported(node, specifierExports)) {
|
|
4955
|
-
return;
|
|
4956
|
-
}
|
|
4957
4981
|
report(annotation, name);
|
|
4958
4982
|
};
|
|
4983
|
+
const enterFunction = (node) => {
|
|
4984
|
+
functionStack.push(node);
|
|
4985
|
+
check(node);
|
|
4986
|
+
};
|
|
4987
|
+
const exitFunction = () => {
|
|
4988
|
+
functionStack.pop();
|
|
4989
|
+
};
|
|
4959
4990
|
return {
|
|
4960
|
-
FunctionDeclaration:
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4991
|
+
FunctionDeclaration: enterFunction,
|
|
4992
|
+
"FunctionDeclaration:exit": exitFunction,
|
|
4993
|
+
FunctionExpression: enterFunction,
|
|
4994
|
+
"FunctionExpression:exit": exitFunction,
|
|
4995
|
+
ArrowFunctionExpression: enterFunction,
|
|
4996
|
+
"ArrowFunctionExpression:exit": exitFunction,
|
|
4997
|
+
TSEmptyBodyFunctionExpression: enterFunction,
|
|
4998
|
+
"TSEmptyBodyFunctionExpression:exit": exitFunction,
|
|
4999
|
+
ReturnStatement(node) {
|
|
5000
|
+
const owner = functionStack.at(-1);
|
|
5001
|
+
if (owner === void 0 || owner.returnType !== void 0 || node.argument === null) return;
|
|
5002
|
+
reportExpression(owner, node.argument);
|
|
5003
|
+
},
|
|
4964
5004
|
TSDeclareFunction(node) {
|
|
4965
5005
|
if (node.id === null || node.returnType === void 0 || node.parent.type !== AST_NODE_TYPES18.ExportNamedDeclaration && node.parent.type !== AST_NODE_TYPES18.ExportDefaultDeclaration && !specifierExports.has(node.id.name)) return;
|
|
4966
5006
|
report(node.returnType.typeAnnotation, node.id.name);
|
|
@@ -5586,6 +5626,38 @@ var no_repeated_string_literal_default = createRule({
|
|
|
5586
5626
|
|
|
5587
5627
|
// src/rules/no-restated-comment.ts
|
|
5588
5628
|
import { AST_NODE_TYPES as AST_NODE_TYPES22 } from "@typescript-eslint/utils";
|
|
5629
|
+
|
|
5630
|
+
// src/rules/_comment-edits.ts
|
|
5631
|
+
import "@typescript-eslint/utils";
|
|
5632
|
+
function physicalLineEnd(text, offset) {
|
|
5633
|
+
const newline = text.indexOf("\n", offset);
|
|
5634
|
+
return newline < 0 ? text.length : newline;
|
|
5635
|
+
}
|
|
5636
|
+
function contentLineEnd(text, offset) {
|
|
5637
|
+
const end = physicalLineEnd(text, offset);
|
|
5638
|
+
return end > offset && text[end - 1] === "\r" ? end - 1 : end;
|
|
5639
|
+
}
|
|
5640
|
+
function wholeLineRemovalRange(text, comment) {
|
|
5641
|
+
if (comment.loc.start.line !== comment.loc.end.line) return null;
|
|
5642
|
+
const lineStart = text.lastIndexOf("\n", Math.max(0, comment.range[0] - 1)) + 1;
|
|
5643
|
+
if (!/^[\t ]*$/u.test(text.slice(lineStart, comment.range[0]))) return null;
|
|
5644
|
+
const contentEnd = contentLineEnd(text, comment.range[1]);
|
|
5645
|
+
if (!/^[\t ]*$/u.test(text.slice(comment.range[1], contentEnd))) return null;
|
|
5646
|
+
const physicalEnd = physicalLineEnd(text, comment.range[1]);
|
|
5647
|
+
return { range: [lineStart, physicalEnd < text.length ? physicalEnd + 1 : physicalEnd] };
|
|
5648
|
+
}
|
|
5649
|
+
function trailingCommentRemovalRange(text, comment) {
|
|
5650
|
+
if (comment.loc.start.line !== comment.loc.end.line) return null;
|
|
5651
|
+
const contentEnd = contentLineEnd(text, comment.range[1]);
|
|
5652
|
+
if (!/^[\t ]*$/u.test(text.slice(comment.range[1], contentEnd))) return null;
|
|
5653
|
+
let start = comment.range[0];
|
|
5654
|
+
while (start > 0 && (text[start - 1] === " " || text[start - 1] === " ")) {
|
|
5655
|
+
start -= 1;
|
|
5656
|
+
}
|
|
5657
|
+
return { range: [start, contentEnd] };
|
|
5658
|
+
}
|
|
5659
|
+
|
|
5660
|
+
// src/rules/no-restated-comment.ts
|
|
5589
5661
|
var MAX_WORDS = 8;
|
|
5590
5662
|
var MIN_CONTENT_TOKENS = 2;
|
|
5591
5663
|
var DIRECTIVE_RE3 = /^(eslint\b|eslint-|sarj-noqa\b|@ts-|prettier-ignore|prettier\b|biome-|c8\b|v8\b|istanbul\b|@type\b|@vite|webpack|<reference|<amd|global\b|noinspection|todo\b|fixme\b|hack\b|xxx\b)/i;
|
|
@@ -5605,6 +5677,7 @@ var noRestatedCommentDocumentation = {
|
|
|
5605
5677
|
rationale: "A comment that only repeats code adds no context and can become stale independently.",
|
|
5606
5678
|
remediation: "Delete the comment or replace it with the reason, constraint, or consequence absent from the code.",
|
|
5607
5679
|
category: "maintainability",
|
|
5680
|
+
autofix: "suggestion",
|
|
5608
5681
|
limitations: ["Directives, protected references, questions, multi-line prose, comments with novel content, and generated files are excluded."],
|
|
5609
5682
|
examples: [
|
|
5610
5683
|
{ id: "reason-comment", title: "Keep the reason the code cannot express", outcome: "no-match", files: [{ path: "src/cache.ts", source: "// Serialize because the cache key is stable across deploys.\nconst key = serialize(input);" }], focusPath: "src/cache.ts", expectedCount: 0, public: true },
|
|
@@ -5628,11 +5701,13 @@ var no_restated_comment_default = createRule({
|
|
|
5628
5701
|
documentation: noRestatedCommentDocumentation,
|
|
5629
5702
|
meta: {
|
|
5630
5703
|
type: "suggestion",
|
|
5704
|
+
hasSuggestions: true,
|
|
5631
5705
|
docs: {
|
|
5632
5706
|
description: "Flag a single-line comment whose every word already appears on the statement below it."
|
|
5633
5707
|
},
|
|
5634
5708
|
schema: [],
|
|
5635
5709
|
messages: {
|
|
5710
|
+
deleteComment: "Delete the redundant comment.",
|
|
5636
5711
|
restatesLineBelow: "Comment restates the statement below it \u2014 delete it, or replace it with the *why*; the code already carries the *what*."
|
|
5637
5712
|
}
|
|
5638
5713
|
},
|
|
@@ -5701,7 +5776,17 @@ var no_restated_comment_default = createRule({
|
|
|
5701
5776
|
if (!ACTION_STMT_RE.test(line)) continue;
|
|
5702
5777
|
if (labelsASiblingRun(comment)) continue;
|
|
5703
5778
|
if (restates(tokens, codeTokens(line))) {
|
|
5704
|
-
|
|
5779
|
+
const removal = wholeLineRemovalRange(sourceCode.text, comment);
|
|
5780
|
+
context.report({
|
|
5781
|
+
node: comment,
|
|
5782
|
+
messageId: "restatesLineBelow",
|
|
5783
|
+
suggest: removal === null ? null : [
|
|
5784
|
+
{
|
|
5785
|
+
messageId: "deleteComment",
|
|
5786
|
+
fix: (fixer) => fixer.removeRange(removal.range)
|
|
5787
|
+
}
|
|
5788
|
+
]
|
|
5789
|
+
});
|
|
5705
5790
|
}
|
|
5706
5791
|
}
|
|
5707
5792
|
}
|
|
@@ -7729,6 +7814,7 @@ var noTrailingValueNarrationDocumentation = {
|
|
|
7729
7814
|
rationale: "A repeated value can disagree with the expression after either the code or comment changes.",
|
|
7730
7815
|
remediation: "Put the unit in the identifier and keep comments only when they explain a constraint or non-obvious conversion.",
|
|
7731
7816
|
category: "maintainability",
|
|
7817
|
+
autofix: "suggestion",
|
|
7732
7818
|
aliases: ["trailing-value-narration"],
|
|
7733
7819
|
limitations: ["Only trailing comments with numeric values and recognized unit words are inspected."],
|
|
7734
7820
|
examples: [
|
|
@@ -7845,13 +7931,15 @@ var no_trailing_value_narration_default = createRule({
|
|
|
7845
7931
|
documentation: noTrailingValueNarrationDocumentation,
|
|
7846
7932
|
meta: {
|
|
7847
7933
|
type: "suggestion",
|
|
7934
|
+
hasSuggestions: true,
|
|
7848
7935
|
docs: {
|
|
7849
7936
|
description: "Flag a trailing comment that repeats the line's numeric value only to name its unit."
|
|
7850
7937
|
},
|
|
7851
7938
|
schema: [],
|
|
7852
7939
|
messages: {
|
|
7853
7940
|
deleteNarration: "Trailing comment restates the literal and the identifier already names its unit \u2014 delete the comment so it cannot drift.",
|
|
7854
|
-
narratesValue: "Trailing comment restates the literal on this line \u2014 put the unit in the name (STALE_TIME_MS) so it cannot drift."
|
|
7941
|
+
narratesValue: "Trailing comment restates the literal on this line \u2014 put the unit in the name (STALE_TIME_MS) so it cannot drift.",
|
|
7942
|
+
removeNarration: "Delete the redundant trailing narration."
|
|
7855
7943
|
}
|
|
7856
7944
|
},
|
|
7857
7945
|
defaultOptions: [],
|
|
@@ -7883,9 +7971,17 @@ var no_trailing_value_narration_default = createRule({
|
|
|
7883
7971
|
const code = line.slice(0, comment.loc.start.column);
|
|
7884
7972
|
const body2 = comment.value.replace(/^\*+/, "").replace(/\*+$/, "").trim();
|
|
7885
7973
|
if (narratesValue(body2, code)) {
|
|
7974
|
+
const canDelete = nameAlreadyCarriesUnit(code);
|
|
7975
|
+
const removal = canDelete ? trailingCommentRemovalRange(sourceCode.text, comment) : null;
|
|
7886
7976
|
context.report({
|
|
7887
7977
|
node: comment,
|
|
7888
|
-
messageId:
|
|
7978
|
+
messageId: canDelete ? "deleteNarration" : "narratesValue",
|
|
7979
|
+
suggest: removal === null ? null : [
|
|
7980
|
+
{
|
|
7981
|
+
messageId: "removeNarration",
|
|
7982
|
+
fix: (fixer) => fixer.removeRange(removal.range)
|
|
7983
|
+
}
|
|
7984
|
+
]
|
|
7889
7985
|
});
|
|
7890
7986
|
}
|
|
7891
7987
|
}
|
|
@@ -11083,6 +11179,7 @@ var prefer_non_nullable_collection_default = createRule({
|
|
|
11083
11179
|
|
|
11084
11180
|
// src/rules/prefer-await-in-async-return.ts
|
|
11085
11181
|
import {
|
|
11182
|
+
ASTUtils as ASTUtils14,
|
|
11086
11183
|
ESLintUtils as ESLintUtils3,
|
|
11087
11184
|
AST_NODE_TYPES as AST_NODE_TYPES46
|
|
11088
11185
|
} from "@typescript-eslint/utils";
|
|
@@ -11095,7 +11192,8 @@ var preferAwaitInAsyncReturnDocumentation = {
|
|
|
11095
11192
|
since: "15.6.3",
|
|
11096
11193
|
limitations: [
|
|
11097
11194
|
"Only a single directly returned `.then` call with an inline callback is checked.",
|
|
11098
|
-
"The receiver must be proven Promise-like by TypeScript; untyped files and larger chains are intentionally ignored."
|
|
11195
|
+
"The receiver must be proven Promise-like by TypeScript; untyped files and larger chains are intentionally ignored.",
|
|
11196
|
+
"Direct loader callbacks passed to resolved `React.lazy` and `next/dynamic` imports are excluded because returning the module Promise is their framework contract."
|
|
11099
11197
|
],
|
|
11100
11198
|
examples: [
|
|
11101
11199
|
{
|
|
@@ -11124,19 +11222,19 @@ var preferAwaitInAsyncReturnDocumentation = {
|
|
|
11124
11222
|
}
|
|
11125
11223
|
]
|
|
11126
11224
|
};
|
|
11127
|
-
function
|
|
11225
|
+
function directAsyncReturnOwner(node) {
|
|
11128
11226
|
const parent = node.parent;
|
|
11129
11227
|
if (parent.type === AST_NODE_TYPES46.ArrowFunctionExpression && parent.body === node) {
|
|
11130
|
-
return parent.async && !parent.generator;
|
|
11228
|
+
return parent.async && !parent.generator ? parent : null;
|
|
11131
11229
|
}
|
|
11132
11230
|
if (parent.type !== AST_NODE_TYPES46.ReturnStatement || parent.argument !== node) {
|
|
11133
|
-
return
|
|
11231
|
+
return null;
|
|
11134
11232
|
}
|
|
11135
11233
|
let owner = parent.parent;
|
|
11136
11234
|
while (owner !== void 0 && !isRuntimeFunction(owner)) {
|
|
11137
11235
|
owner = owner.parent;
|
|
11138
11236
|
}
|
|
11139
|
-
return owner !== void 0 && owner.async && !owner.generator;
|
|
11237
|
+
return owner !== void 0 && owner.async && !owner.generator ? owner : null;
|
|
11140
11238
|
}
|
|
11141
11239
|
function isRuntimeFunction(node) {
|
|
11142
11240
|
return node.type === AST_NODE_TYPES46.ArrowFunctionExpression || node.type === AST_NODE_TYPES46.FunctionDeclaration || node.type === AST_NODE_TYPES46.FunctionExpression;
|
|
@@ -11193,9 +11291,33 @@ var prefer_await_in_async_return_default = createRule({
|
|
|
11193
11291
|
services = null;
|
|
11194
11292
|
}
|
|
11195
11293
|
if (services === null) return {};
|
|
11294
|
+
const frameworkLoaders = /* @__PURE__ */ new Set();
|
|
11295
|
+
const rememberFrameworkLoader = (identifier) => {
|
|
11296
|
+
const variable = ASTUtils14.findVariable(context.sourceCode.getScope(identifier), identifier.name);
|
|
11297
|
+
if (variable !== null) frameworkLoaders.add(variable);
|
|
11298
|
+
};
|
|
11299
|
+
const isFrameworkLoaderCallback = (owner) => {
|
|
11300
|
+
const parent = owner.parent;
|
|
11301
|
+
if (parent.type !== AST_NODE_TYPES46.CallExpression || parent.arguments[0] !== owner || parent.callee.type !== AST_NODE_TYPES46.Identifier) return false;
|
|
11302
|
+
const variable = ASTUtils14.findVariable(context.sourceCode.getScope(parent.callee), parent.callee.name);
|
|
11303
|
+
return variable !== null && frameworkLoaders.has(variable);
|
|
11304
|
+
};
|
|
11196
11305
|
return {
|
|
11306
|
+
ImportDeclaration(node) {
|
|
11307
|
+
if (node.source.value === "react") {
|
|
11308
|
+
for (const specifier of node.specifiers) {
|
|
11309
|
+
if (specifier.type === AST_NODE_TYPES46.ImportSpecifier && (specifier.imported.type === AST_NODE_TYPES46.Identifier ? specifier.imported.name : specifier.imported.value) === "lazy") rememberFrameworkLoader(specifier.local);
|
|
11310
|
+
}
|
|
11311
|
+
}
|
|
11312
|
+
if (node.source.value === "next/dynamic") {
|
|
11313
|
+
for (const specifier of node.specifiers) {
|
|
11314
|
+
if (specifier.type === AST_NODE_TYPES46.ImportDefaultSpecifier) rememberFrameworkLoader(specifier.local);
|
|
11315
|
+
}
|
|
11316
|
+
}
|
|
11317
|
+
},
|
|
11197
11318
|
CallExpression(node) {
|
|
11198
|
-
|
|
11319
|
+
const owner = directAsyncReturnOwner(node);
|
|
11320
|
+
if (owner === null || isFrameworkLoaderCallback(owner)) return;
|
|
11199
11321
|
const receiver = promiseThenReceiver(node);
|
|
11200
11322
|
if (receiver === null || !isProvenPromiseLike(receiver, services)) {
|
|
11201
11323
|
return;
|
|
@@ -12404,6 +12526,16 @@ function literalIndex(node) {
|
|
|
12404
12526
|
}
|
|
12405
12527
|
return Number.isInteger(node.value) && node.value >= 0 ? node.value : null;
|
|
12406
12528
|
}
|
|
12529
|
+
function propertyAccess(node) {
|
|
12530
|
+
const path = [];
|
|
12531
|
+
let current = node;
|
|
12532
|
+
while (current.type === AST_NODE_TYPES49.MemberExpression && !current.computed && !current.optional) {
|
|
12533
|
+
if (current.property.type !== AST_NODE_TYPES49.Identifier || COLLECTION_PROPERTIES.has(current.property.name) || LITERAL_KEY_HAZARDS.has(current.property.name)) return null;
|
|
12534
|
+
path.unshift(current.property.name);
|
|
12535
|
+
current = current.object;
|
|
12536
|
+
}
|
|
12537
|
+
return path.length > 0 && isPureReceiver(current) ? { receiver: current, path } : null;
|
|
12538
|
+
}
|
|
12407
12539
|
var prefer_whole_object_assertion_default = createRule({
|
|
12408
12540
|
name: "prefer-whole-object-assertion",
|
|
12409
12541
|
documentation: preferWholeObjectAssertionDocumentation,
|
|
@@ -12450,21 +12582,23 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
12450
12582
|
return null;
|
|
12451
12583
|
}
|
|
12452
12584
|
let key;
|
|
12585
|
+
let receiver;
|
|
12453
12586
|
if (actual.computed) {
|
|
12454
12587
|
const index = literalIndex(actual.property);
|
|
12455
12588
|
if (index === null) {
|
|
12456
12589
|
return null;
|
|
12457
12590
|
}
|
|
12458
12591
|
key = { kind: "index", index };
|
|
12592
|
+
receiver = actual.object;
|
|
12459
12593
|
} else {
|
|
12460
|
-
|
|
12461
|
-
|
|
12462
|
-
}
|
|
12463
|
-
|
|
12594
|
+
const access = propertyAccess(actual);
|
|
12595
|
+
if (access === null) return null;
|
|
12596
|
+
key = { kind: "property", path: access.path };
|
|
12597
|
+
receiver = access.receiver;
|
|
12464
12598
|
}
|
|
12465
12599
|
const synthetic = SYNTHETIC_LITERAL_MATCHERS.get(matcher);
|
|
12466
12600
|
if (synthetic !== void 0 && call.arguments.length === 0) {
|
|
12467
|
-
return { statement, receiver
|
|
12601
|
+
return { statement, receiver, key, matcher, expectedText: synthetic, expectedIsLiteral: true };
|
|
12468
12602
|
}
|
|
12469
12603
|
if (!MERGEABLE_MATCHERS.has(matcher)) {
|
|
12470
12604
|
return null;
|
|
@@ -12476,7 +12610,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
12476
12610
|
const literal = literalText(expected, (node) => sourceCode.getText(node));
|
|
12477
12611
|
return {
|
|
12478
12612
|
statement,
|
|
12479
|
-
receiver
|
|
12613
|
+
receiver,
|
|
12480
12614
|
key,
|
|
12481
12615
|
matcher,
|
|
12482
12616
|
expectedText: literal ?? sourceCode.getText(expected),
|
|
@@ -12489,7 +12623,8 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
12489
12623
|
);
|
|
12490
12624
|
}
|
|
12491
12625
|
function reportPropertyRun(run) {
|
|
12492
|
-
const
|
|
12626
|
+
const tree = /* @__PURE__ */ new Map();
|
|
12627
|
+
const paths = [];
|
|
12493
12628
|
for (const assertion of run) {
|
|
12494
12629
|
if (assertion.key.kind !== "property" || !assertion.expectedIsLiteral) {
|
|
12495
12630
|
return;
|
|
@@ -12497,19 +12632,44 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
12497
12632
|
if (!MERGEABLE_MATCHERS.has(assertion.matcher) && !SYNTHETIC_LITERAL_MATCHERS.has(assertion.matcher)) {
|
|
12498
12633
|
return;
|
|
12499
12634
|
}
|
|
12500
|
-
|
|
12501
|
-
|
|
12635
|
+
paths.push([...assertion.key.path]);
|
|
12636
|
+
}
|
|
12637
|
+
const commonPrefix = [];
|
|
12638
|
+
for (let index = 0; ; index += 1) {
|
|
12639
|
+
const candidate = paths[0]?.[index];
|
|
12640
|
+
if (candidate === void 0 || paths.some((path) => path[index] !== candidate || path.length === index + 1)) {
|
|
12641
|
+
break;
|
|
12642
|
+
}
|
|
12643
|
+
commonPrefix.push(candidate);
|
|
12644
|
+
}
|
|
12645
|
+
for (const [assertionIndex, assertion] of run.entries()) {
|
|
12646
|
+
if (assertion.key.kind !== "property") return;
|
|
12647
|
+
let branch = tree;
|
|
12648
|
+
const relativePath = paths[assertionIndex]?.slice(commonPrefix.length) ?? [];
|
|
12649
|
+
for (const [index, name] of relativePath.entries()) {
|
|
12650
|
+
const leaf = index === relativePath.length - 1;
|
|
12651
|
+
const existing = branch.get(name);
|
|
12652
|
+
if (leaf) {
|
|
12653
|
+
if (existing !== void 0) return;
|
|
12654
|
+
branch.set(name, assertion.expectedText);
|
|
12655
|
+
} else if (existing === void 0) {
|
|
12656
|
+
const nested = /* @__PURE__ */ new Map();
|
|
12657
|
+
branch.set(name, nested);
|
|
12658
|
+
branch = nested;
|
|
12659
|
+
} else if (existing instanceof Map) {
|
|
12660
|
+
branch = existing;
|
|
12661
|
+
} else {
|
|
12662
|
+
return;
|
|
12663
|
+
}
|
|
12502
12664
|
}
|
|
12503
|
-
names.add(assertion.key.name);
|
|
12504
12665
|
}
|
|
12505
12666
|
const first = run[0];
|
|
12506
12667
|
if (first === void 0) {
|
|
12507
12668
|
return;
|
|
12508
12669
|
}
|
|
12509
|
-
const receiverText = sourceCode.getText(first.receiver)
|
|
12510
|
-
const
|
|
12511
|
-
|
|
12512
|
-
).join(", ");
|
|
12670
|
+
const receiverText = `${sourceCode.getText(first.receiver)}${commonPrefix.map((name) => `.${name}`).join("")}`;
|
|
12671
|
+
const renderTree = (value) => [...value.entries()].map(([name, child]) => `${name}: ${child instanceof Map ? `{ ${renderTree(child)} }` : child}`).join(", ");
|
|
12672
|
+
const properties = renderTree(tree);
|
|
12513
12673
|
context.report({
|
|
12514
12674
|
node: first.statement,
|
|
12515
12675
|
messageId: "combineAssertions",
|
|
@@ -12585,7 +12745,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
12585
12745
|
});
|
|
12586
12746
|
|
|
12587
12747
|
// src/rules/repeated-static-call-cases.ts
|
|
12588
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES50, ASTUtils as
|
|
12748
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES50, ASTUtils as ASTUtils15 } from "@typescript-eslint/utils";
|
|
12589
12749
|
var repeatedStaticCallCasesDocumentation = {
|
|
12590
12750
|
summary: "Report three or more consecutive literal call assertions that should be independently named test cases.",
|
|
12591
12751
|
rationale: "Copy-pasted cases obscure the input table and stop later cases from being reported after the first failure.",
|
|
@@ -12611,7 +12771,7 @@ function staticMemberName5(node) {
|
|
|
12611
12771
|
return null;
|
|
12612
12772
|
}
|
|
12613
12773
|
function importedName3(identifier, context, modules) {
|
|
12614
|
-
const variable =
|
|
12774
|
+
const variable = ASTUtils15.findVariable(context.sourceCode.getScope(identifier), identifier.name);
|
|
12615
12775
|
if (variable === null || variable.defs.length === 0) return identifier.name;
|
|
12616
12776
|
for (const definition of variable.defs) {
|
|
12617
12777
|
if (definition.node.type !== AST_NODE_TYPES50.ImportSpecifier) continue;
|
|
@@ -13612,7 +13772,7 @@ var require_assert_never_default = createRule({
|
|
|
13612
13772
|
});
|
|
13613
13773
|
|
|
13614
13774
|
// src/rules/require-fetch-timeout.ts
|
|
13615
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES53, ASTUtils as
|
|
13775
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES53, ASTUtils as ASTUtils16 } from "@typescript-eslint/utils";
|
|
13616
13776
|
var requireFetchTimeoutDocumentation = {
|
|
13617
13777
|
summary: "Require an abort `signal` (e.g. `AbortSignal.timeout(ms)`) on global `fetch()` calls so stalled upstreams cannot hang the caller forever.",
|
|
13618
13778
|
rationale: "An unbounded request can occupy work indefinitely when an upstream stalls.",
|
|
@@ -13693,7 +13853,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
13693
13853
|
}
|
|
13694
13854
|
function resolvesToGlobal(identifier) {
|
|
13695
13855
|
const scope = context.sourceCode.getScope(identifier);
|
|
13696
|
-
const variable =
|
|
13856
|
+
const variable = ASTUtils16.findVariable(scope, identifier.name);
|
|
13697
13857
|
return variable === null || variable.defs.length === 0;
|
|
13698
13858
|
}
|
|
13699
13859
|
function isGlobalFetchCall2(callee) {
|
|
@@ -13703,7 +13863,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
13703
13863
|
return callee.type === AST_NODE_TYPES53.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES53.Identifier && callee.property.name === "fetch" && callee.object.type === AST_NODE_TYPES53.Identifier && GLOBAL_OBJECTS2.has(callee.object.name) && resolvesToGlobal(callee.object);
|
|
13704
13864
|
}
|
|
13705
13865
|
function localConstInitProvablyLacksSignal(identifier) {
|
|
13706
|
-
const variable =
|
|
13866
|
+
const variable = ASTUtils16.findVariable(
|
|
13707
13867
|
context.sourceCode.getScope(identifier),
|
|
13708
13868
|
identifier.name
|
|
13709
13869
|
);
|
|
@@ -14347,7 +14507,7 @@ var require_static_next_matcher_default = createRule({
|
|
|
14347
14507
|
// src/rules/require-zod-form-validation.ts
|
|
14348
14508
|
import {
|
|
14349
14509
|
AST_NODE_TYPES as AST_NODE_TYPES56,
|
|
14350
|
-
ASTUtils as
|
|
14510
|
+
ASTUtils as ASTUtils17
|
|
14351
14511
|
} from "@typescript-eslint/utils";
|
|
14352
14512
|
var requireZodFormValidationDocumentation = {
|
|
14353
14513
|
summary: "Require Zod validation (`Schema.parse(...)` / `Schema.safeParse(...)`) when reading values out of a `FormData` object.",
|
|
@@ -14415,7 +14575,7 @@ var require_zod_form_validation_default = createRule({
|
|
|
14415
14575
|
return {};
|
|
14416
14576
|
}
|
|
14417
14577
|
const zodBindings = /* @__PURE__ */ new Set();
|
|
14418
|
-
const resolvedBinding = (identifier) =>
|
|
14578
|
+
const resolvedBinding = (identifier) => ASTUtils17.findVariable(
|
|
14419
14579
|
context.sourceCode.getScope(identifier),
|
|
14420
14580
|
identifier.name
|
|
14421
14581
|
);
|
|
@@ -14712,7 +14872,7 @@ var store_insert_requires_on_conflict_default = createRule({
|
|
|
14712
14872
|
});
|
|
14713
14873
|
|
|
14714
14874
|
// src/rules/stepdown.ts
|
|
14715
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES57, ASTUtils as
|
|
14875
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES57, ASTUtils as ASTUtils18 } from "@typescript-eslint/utils";
|
|
14716
14876
|
var stepdownDocumentation = {
|
|
14717
14877
|
summary: "Place a private helper below its sole direct same-scope caller.",
|
|
14718
14878
|
rationale: "Caller-first ordering lets a reader follow the main flow before descending into implementation details.",
|
|
@@ -14912,7 +15072,7 @@ function methodName(node) {
|
|
|
14912
15072
|
return !node.computed && node.key.type === AST_NODE_TYPES57.Identifier ? node.key.name : null;
|
|
14913
15073
|
}
|
|
14914
15074
|
function referencedMethod(context, node, classVariables) {
|
|
14915
|
-
const objectVariable = node.object.type === AST_NODE_TYPES57.Identifier ?
|
|
15075
|
+
const objectVariable = node.object.type === AST_NODE_TYPES57.Identifier ? ASTUtils18.findVariable(context.sourceCode.getScope(node.object), node.object.name) : null;
|
|
14916
15076
|
const isClassReference = objectVariable !== null && classVariables.has(objectVariable);
|
|
14917
15077
|
if (node.object.type !== AST_NODE_TYPES57.ThisExpression && !isClassReference) return null;
|
|
14918
15078
|
if (node.property.type === AST_NODE_TYPES57.PrivateIdentifier) return `#${node.property.name}`;
|
|
@@ -14965,11 +15125,11 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
14965
15125
|
const pinned = /* @__PURE__ */ new Set();
|
|
14966
15126
|
const classVariables = /* @__PURE__ */ new Set();
|
|
14967
15127
|
if (node.id !== null) {
|
|
14968
|
-
const internal =
|
|
15128
|
+
const internal = ASTUtils18.findVariable(context.sourceCode.getScope(node), node.id.name);
|
|
14969
15129
|
if (internal !== null) classVariables.add(internal);
|
|
14970
15130
|
}
|
|
14971
15131
|
if (node.type === AST_NODE_TYPES57.ClassExpression && node.parent.type === AST_NODE_TYPES57.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES57.Identifier) {
|
|
14972
|
-
const outer =
|
|
15132
|
+
const outer = ASTUtils18.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
|
|
14973
15133
|
if (outer !== null) classVariables.add(outer);
|
|
14974
15134
|
}
|
|
14975
15135
|
for (const method of methods) {
|
|
@@ -15005,7 +15165,7 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
15005
15165
|
return;
|
|
15006
15166
|
}
|
|
15007
15167
|
if (binding.type !== AST_NODE_TYPES57.Identifier) return;
|
|
15008
|
-
const variable =
|
|
15168
|
+
const variable = ASTUtils18.findVariable(context.sourceCode.getScope(binding), binding.name);
|
|
15009
15169
|
if (variable !== null) {
|
|
15010
15170
|
methodClassVariables.add(variable);
|
|
15011
15171
|
methodAliases.add(variable);
|
|
@@ -15035,7 +15195,7 @@ function classScope(context, node, computedReferenceNames) {
|
|
|
15035
15195
|
return;
|
|
15036
15196
|
}
|
|
15037
15197
|
if (!privateNames.has(target)) return;
|
|
15038
|
-
const objectVariable = current.object.type === AST_NODE_TYPES57.Identifier ?
|
|
15198
|
+
const objectVariable = current.object.type === AST_NODE_TYPES57.Identifier ? ASTUtils18.findVariable(context.sourceCode.getScope(current.object), current.object.name) : null;
|
|
15039
15199
|
if (objectVariable !== null && methodAliases.has(objectVariable)) {
|
|
15040
15200
|
pinned.add(target);
|
|
15041
15201
|
return;
|
|
@@ -15143,7 +15303,7 @@ var stepdown_default = createRule({
|
|
|
15143
15303
|
|
|
15144
15304
|
// src/rules/source-coupled-test.ts
|
|
15145
15305
|
import { AST_NODE_TYPES as AST_NODE_TYPES58 } from "@typescript-eslint/utils";
|
|
15146
|
-
var GENERAL_SOURCE_SUFFIX_RE = /\.(?:bash|sh|ya?ml|py|[cm]?[jt]s)$/iu;
|
|
15306
|
+
var GENERAL_SOURCE_SUFFIX_RE = /\.(?:bash|sh|ya?ml|jsonc|py|[cm]?[jt]s)$/iu;
|
|
15147
15307
|
var FS_MODULES = /* @__PURE__ */ new Set(["fs", "node:fs", "fs/promises", "node:fs/promises"]);
|
|
15148
15308
|
var FS_READERS = /* @__PURE__ */ new Set(["readFile", "readFileSync"]);
|
|
15149
15309
|
var TEXT_TRANSFORMS = /* @__PURE__ */ new Set([
|
|
@@ -15338,6 +15498,13 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
15338
15498
|
if (receiver.type !== AST_NODE_TYPES58.Identifier || receiver.name !== "assert" || !ASSERT_MATCHERS.has(matcher)) return /* @__PURE__ */ new Set();
|
|
15339
15499
|
return new Set(node.arguments.flatMap((argument) => argument.type === AST_NODE_TYPES58.SpreadElement ? [] : [...evidenceOrigins(argument)]));
|
|
15340
15500
|
};
|
|
15501
|
+
const rawRegexExtractionOrigins = (node) => {
|
|
15502
|
+
const callee = unwrap5(node.callee);
|
|
15503
|
+
if (callee.type !== AST_NODE_TYPES58.MemberExpression || staticMemberName7(callee) !== "matchAll" || node.arguments.length !== 1) return /* @__PURE__ */ new Set();
|
|
15504
|
+
const argument = node.arguments[0];
|
|
15505
|
+
if (argument?.type !== AST_NODE_TYPES58.Literal || !(argument.value instanceof RegExp)) return /* @__PURE__ */ new Set();
|
|
15506
|
+
return rawOrigins(callee.object);
|
|
15507
|
+
};
|
|
15341
15508
|
const declare = (name2, state) => {
|
|
15342
15509
|
const scope = currentScope();
|
|
15343
15510
|
scope.declared.add(name2);
|
|
@@ -15417,7 +15584,10 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
15417
15584
|
if (collection && left?.type === AST_NODE_TYPES58.Identifier) declare(left.name, { path: true });
|
|
15418
15585
|
},
|
|
15419
15586
|
CallExpression(node) {
|
|
15420
|
-
const origins =
|
|
15587
|
+
const origins = /* @__PURE__ */ new Set([
|
|
15588
|
+
...rawAssertionOrigins(node),
|
|
15589
|
+
...rawRegexExtractionOrigins(node)
|
|
15590
|
+
]);
|
|
15421
15591
|
if (origins.size === 0 || [...origins].every((origin) => reportedOrigins.has(origin))) return;
|
|
15422
15592
|
for (const origin of origins) reportedOrigins.add(origin);
|
|
15423
15593
|
context.report({ node, messageId: "rawSourceOracle" });
|
|
@@ -15473,7 +15643,7 @@ var iac_source_coupled_test_default = createSourceCoupledRule(
|
|
|
15473
15643
|
// src/rules/zod-naming-convention.ts
|
|
15474
15644
|
import {
|
|
15475
15645
|
AST_NODE_TYPES as AST_NODE_TYPES59,
|
|
15476
|
-
ASTUtils as
|
|
15646
|
+
ASTUtils as ASTUtils19
|
|
15477
15647
|
} from "@typescript-eslint/utils";
|
|
15478
15648
|
var zodNamingConventionDocumentation = {
|
|
15479
15649
|
summary: "Enforce a consistent Zod schema naming convention \u2014 a `Z` prefix (`ZUser`) or a `Schema` suffix (`userSchema`); both are accepted by default.",
|
|
@@ -15566,7 +15736,7 @@ var zod_naming_convention_default = createRule({
|
|
|
15566
15736
|
const acceptsSchemaWord = convention !== "prefix";
|
|
15567
15737
|
const zodBindings = /* @__PURE__ */ new Set();
|
|
15568
15738
|
function resolvedBinding(identifier) {
|
|
15569
|
-
return
|
|
15739
|
+
return ASTUtils19.findVariable(
|
|
15570
15740
|
context.sourceCode.getScope(identifier),
|
|
15571
15741
|
identifier.name
|
|
15572
15742
|
);
|
|
@@ -15768,7 +15938,7 @@ var rules = {
|
|
|
15768
15938
|
};
|
|
15769
15939
|
var meta = {
|
|
15770
15940
|
name: "@sarj/eslint-plugin",
|
|
15771
|
-
version: "15.
|
|
15941
|
+
version: "15.9.0"
|
|
15772
15942
|
};
|
|
15773
15943
|
var applicationOnlyRules = [
|
|
15774
15944
|
"no-restricted-library-load",
|