@sarj/eslint-plugin 18.0.3 → 18.0.5
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 +988 -913
- package/dist/index.js +978 -903
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -809,14 +809,14 @@ function sameShape(checker, input, output, location) {
|
|
|
809
809
|
|
|
810
810
|
// src/rules/prefer-server-data-preparation.ts
|
|
811
811
|
import {
|
|
812
|
-
AST_NODE_TYPES as
|
|
812
|
+
AST_NODE_TYPES as AST_NODE_TYPES9,
|
|
813
813
|
ASTUtils as ASTUtils4
|
|
814
814
|
} from "@typescript-eslint/utils";
|
|
815
|
-
import
|
|
815
|
+
import ts7 from "typescript";
|
|
816
816
|
|
|
817
817
|
// src/rules/_react-prop-bindings.ts
|
|
818
818
|
import {
|
|
819
|
-
AST_NODE_TYPES as
|
|
819
|
+
AST_NODE_TYPES as AST_NODE_TYPES8,
|
|
820
820
|
ASTUtils as ASTUtils3
|
|
821
821
|
} from "@typescript-eslint/utils";
|
|
822
822
|
|
|
@@ -826,6 +826,206 @@ function importSpecifierName(node) {
|
|
|
826
826
|
return node.imported.type === AST_NODE_TYPES5.Identifier ? node.imported.name : node.imported.value;
|
|
827
827
|
}
|
|
828
828
|
|
|
829
|
+
// src/rules/_private-scalar-consumer.ts
|
|
830
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES7 } from "@typescript-eslint/utils";
|
|
831
|
+
import ts6 from "typescript";
|
|
832
|
+
|
|
833
|
+
// src/rules/_scalar-parameter-view.ts
|
|
834
|
+
import ts5 from "typescript";
|
|
835
|
+
|
|
836
|
+
// src/rules/_checked-native-source.ts
|
|
837
|
+
import ts3 from "typescript";
|
|
838
|
+
var CHECKED = /* @__PURE__ */ new WeakMap();
|
|
839
|
+
var SINGLE_LINE_DIRECTIVE = /^\/\/\/?\s*@(?:ts-expect-error|ts-ignore)/u;
|
|
840
|
+
var MULTI_LINE_DIRECTIVE = /^[/*]*\s*@(?:ts-expect-error|ts-ignore)/u;
|
|
841
|
+
var SINGLE_LINE_PRAGMA = /^\/\/\/?\s*@([^\s:]+)(?:(?:[^\S\r\n]|:).*)?$/mu;
|
|
842
|
+
function currentNativeSource(sourceCode, services) {
|
|
843
|
+
const source = services.esTreeNodeToTSNodeMap.get(sourceCode.ast);
|
|
844
|
+
return ts3.isSourceFile(source) && services.program.getSourceFile(source.fileName) === source && source.text === sourceCode.text ? source : null;
|
|
845
|
+
}
|
|
846
|
+
function checkedNativeSource(program, source) {
|
|
847
|
+
let files = CHECKED.get(program);
|
|
848
|
+
if (!files) {
|
|
849
|
+
files = /* @__PURE__ */ new WeakMap();
|
|
850
|
+
CHECKED.set(program, files);
|
|
851
|
+
}
|
|
852
|
+
const known2 = files.get(source);
|
|
853
|
+
if (known2 !== void 0) return known2;
|
|
854
|
+
const available = !program.getCompilerOptions().noCheck && !source.isDeclarationFile && (source.flags & (ts3.NodeFlags.JavaScriptFile | ts3.NodeFlags.JsonFile)) === 0 && !program.getProjectReferences()?.length && !program.getResolvedProjectReferences()?.length && program.getSourceFile(source.fileName) === source && !program.isSourceFileFromExternalLibrary(source) && !program.isSourceFileDefaultLibrary(source) && !program.getSyntacticDiagnostics(source).some((diagnostic) => diagnostic.category === ts3.DiagnosticCategory.Error && diagnostic.file === source) && !checkingSuppressed(source) && !program.getSemanticDiagnostics(source).some((diagnostic) => diagnostic.category === ts3.DiagnosticCategory.Error && diagnostic.file === source);
|
|
855
|
+
files.set(source, available);
|
|
856
|
+
return available;
|
|
857
|
+
}
|
|
858
|
+
function checkingSuppressed(source) {
|
|
859
|
+
if (!/@ts-/iu.test(source.text)) return false;
|
|
860
|
+
if (ts3.getLeadingCommentRanges(source.text, 0)?.some((comment) => comment.kind === ts3.SyntaxKind.SingleLineCommentTrivia && SINGLE_LINE_PRAGMA.exec(source.text.slice(comment.pos, comment.end))?.[1]?.toLowerCase() === "ts-nocheck")) return true;
|
|
861
|
+
const pending = [source];
|
|
862
|
+
while (pending.length) {
|
|
863
|
+
const node = pending.pop();
|
|
864
|
+
if (!node || ts3.isJsxText(node) || ts3.isJSDoc(node) || (node.flags & ts3.NodeFlags.JSDoc) !== 0) continue;
|
|
865
|
+
if (!ts3.isToken(node)) {
|
|
866
|
+
for (const child of node.getChildren(source)) pending.push(child);
|
|
867
|
+
continue;
|
|
868
|
+
}
|
|
869
|
+
if (tokenTriviaSuppressesChecking(node, source)) return true;
|
|
870
|
+
}
|
|
871
|
+
return false;
|
|
872
|
+
}
|
|
873
|
+
function tokenTriviaSuppressesChecking(node, source) {
|
|
874
|
+
const start = node.getStart(source);
|
|
875
|
+
for (const comment of [...ts3.getLeadingCommentRanges(source.text, node.pos) ?? [], ...ts3.getTrailingCommentRanges(source.text, node.pos) ?? []]) {
|
|
876
|
+
if (comment.pos < node.pos || comment.end > start) continue;
|
|
877
|
+
if (commentSuppressesChecking(source.text.slice(comment.pos, comment.end), comment.kind)) return true;
|
|
878
|
+
}
|
|
879
|
+
return false;
|
|
880
|
+
}
|
|
881
|
+
function commentSuppressesChecking(text, kind) {
|
|
882
|
+
if (kind === ts3.SyntaxKind.SingleLineCommentTrivia) return SINGLE_LINE_DIRECTIVE.test(text);
|
|
883
|
+
let lastLine = text.length;
|
|
884
|
+
while (lastLine > 0 && !ts3.isLineBreak(text.charCodeAt(lastLine - 1))) lastLine--;
|
|
885
|
+
return MULTI_LINE_DIRECTIVE.test(text.slice(lastLine).trimStart());
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
// src/rules/_native-const-value.ts
|
|
889
|
+
import ts4 from "typescript";
|
|
890
|
+
function constInitializer(declaration) {
|
|
891
|
+
if (!declaration || !ts4.isVariableDeclaration(declaration) || !ts4.isVariableDeclarationList(declaration.parent) || (declaration.parent.flags & ts4.NodeFlags.BlockScoped) !== ts4.NodeFlags.Const) return void 0;
|
|
892
|
+
let initializer = declaration.initializer;
|
|
893
|
+
while (initializer && ts4.isParenthesizedExpression(initializer)) initializer = initializer.expression;
|
|
894
|
+
return initializer;
|
|
895
|
+
}
|
|
896
|
+
function unassertedValue(node) {
|
|
897
|
+
let value = node;
|
|
898
|
+
while (ts4.isParenthesizedExpression(value) || ts4.isAsExpression(value) || ts4.isTypeAssertionExpression(value) || ts4.isNonNullExpression(value) || ts4.isSatisfiesExpression(value)) value = value.expression;
|
|
899
|
+
return value;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
// src/rules/_scalar-parameter-view.ts
|
|
903
|
+
var SCALAR_OPERATORS = /* @__PURE__ */ new Set([
|
|
904
|
+
ts5.SyntaxKind.PlusToken,
|
|
905
|
+
ts5.SyntaxKind.MinusToken,
|
|
906
|
+
ts5.SyntaxKind.AsteriskToken,
|
|
907
|
+
ts5.SyntaxKind.SlashToken,
|
|
908
|
+
ts5.SyntaxKind.PercentToken,
|
|
909
|
+
ts5.SyntaxKind.AsteriskAsteriskToken,
|
|
910
|
+
ts5.SyntaxKind.LessThanToken,
|
|
911
|
+
ts5.SyntaxKind.LessThanEqualsToken,
|
|
912
|
+
ts5.SyntaxKind.GreaterThanToken,
|
|
913
|
+
ts5.SyntaxKind.GreaterThanEqualsToken,
|
|
914
|
+
ts5.SyntaxKind.EqualsEqualsEqualsToken,
|
|
915
|
+
ts5.SyntaxKind.ExclamationEqualsEqualsToken,
|
|
916
|
+
ts5.SyntaxKind.EqualsEqualsToken,
|
|
917
|
+
ts5.SyntaxKind.ExclamationEqualsToken,
|
|
918
|
+
ts5.SyntaxKind.AmpersandAmpersandToken,
|
|
919
|
+
ts5.SyntaxKind.BarBarToken,
|
|
920
|
+
ts5.SyntaxKind.QuestionQuestionToken
|
|
921
|
+
]);
|
|
922
|
+
var SCALAR_PREFIXES = /* @__PURE__ */ new Set([ts5.SyntaxKind.PlusToken, ts5.SyntaxKind.MinusToken, ts5.SyntaxKind.ExclamationToken, ts5.SyntaxKind.TildeToken]);
|
|
923
|
+
var RETURNED_OPERANDS = /* @__PURE__ */ new Set([ts5.SyntaxKind.AmpersandAmpersandToken, ts5.SyntaxKind.BarBarToken, ts5.SyntaxKind.QuestionQuestionToken]);
|
|
924
|
+
function scalarParameterView(parameter, body3, checker) {
|
|
925
|
+
return parameterReads(parameter, body3, checker, true);
|
|
926
|
+
}
|
|
927
|
+
function scalarParameterReads(parameter, body3, checker, callProgram, auxiliaries) {
|
|
928
|
+
return parameterReads(parameter, body3, checker, false, callProgram, auxiliaries);
|
|
929
|
+
}
|
|
930
|
+
function parameterReads(parameter, body3, checker, jsx, callProgram, auxiliaries) {
|
|
931
|
+
if (parameter.dotDotDotToken || parameter.initializer || ts5.isArrayBindingPattern(parameter.name)) return null;
|
|
932
|
+
const root = ts5.isIdentifier(parameter.name) ? checker.getSymbolAtLocation(parameter.name) : void 0;
|
|
933
|
+
if (ts5.isIdentifier(parameter.name) && !root) return null;
|
|
934
|
+
const reads = /* @__PURE__ */ new Set();
|
|
935
|
+
const aliases = parameterAliases(parameter.name, checker, reads);
|
|
936
|
+
if (!aliases) return null;
|
|
937
|
+
const expression = returnedExpression(body3);
|
|
938
|
+
const view = { checker, props: checker.getTypeAtLocation(parameter), root, aliases, reads, callProgram, auxiliaries };
|
|
939
|
+
return expression && scalarView(expression, view, jsx) ? reads : null;
|
|
940
|
+
}
|
|
941
|
+
function scalarType(type, allowUndefined = true) {
|
|
942
|
+
if (type.isUnion()) return type.types.every((part) => scalarType(part, allowUndefined));
|
|
943
|
+
const flags = ts5.TypeFlags.StringLike | ts5.TypeFlags.NumberLike | ts5.TypeFlags.BooleanLike | ts5.TypeFlags.BigIntLike | ts5.TypeFlags.Null;
|
|
944
|
+
return (type.flags & (allowUndefined ? flags | ts5.TypeFlags.Undefined : flags)) !== 0;
|
|
945
|
+
}
|
|
946
|
+
function parameterAliases(name, checker, reads) {
|
|
947
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
948
|
+
if (ts5.isIdentifier(name)) return aliases;
|
|
949
|
+
for (const element of name.elements) {
|
|
950
|
+
const key = element.propertyName ?? element.name;
|
|
951
|
+
if (element.dotDotDotToken || element.initializer || !ts5.isIdentifier(element.name) || !ts5.isIdentifier(key) && !ts5.isStringLiteralLike(key) && !ts5.isNumericLiteral(key)) return null;
|
|
952
|
+
const binding3 = checker.getSymbolAtLocation(element.name);
|
|
953
|
+
if (!binding3) return null;
|
|
954
|
+
reads.add(key.text);
|
|
955
|
+
aliases.set(binding3, key.text);
|
|
956
|
+
}
|
|
957
|
+
return aliases;
|
|
958
|
+
}
|
|
959
|
+
function returnedExpression(body3) {
|
|
960
|
+
if (!ts5.isBlock(body3)) return body3;
|
|
961
|
+
const statement = body3.statements.length === 1 ? body3.statements[0] : void 0;
|
|
962
|
+
return statement && ts5.isReturnStatement(statement) ? statement.expression : void 0;
|
|
963
|
+
}
|
|
964
|
+
function scalarView(node, view, jsx = false) {
|
|
965
|
+
if (scalarLiteral(node)) return true;
|
|
966
|
+
if (ts5.isCallExpression(node)) return !jsx && scalarCall(node, view);
|
|
967
|
+
if (ts5.isJsxExpression(node)) return !node.dotDotDotToken && (!node.expression || scalarView(node.expression, view, jsx));
|
|
968
|
+
if (ts5.isIdentifier(node)) {
|
|
969
|
+
const binding3 = view.checker.getSymbolAtLocation(node);
|
|
970
|
+
if (binding3 && view.auxiliaries?.has(binding3)) return scalarType(view.checker.getTypeAtLocation(node));
|
|
971
|
+
const key = binding3 && view.aliases.get(binding3);
|
|
972
|
+
return key !== void 0 && readField(node, key, view);
|
|
973
|
+
}
|
|
974
|
+
if (ts5.isPropertyAccessExpression(node) || ts5.isElementAccessExpression(node)) return memberRead(node, view);
|
|
975
|
+
return scalarOperation(node, view, jsx);
|
|
976
|
+
}
|
|
977
|
+
function scalarOperation(node, view, jsx) {
|
|
978
|
+
if (ts5.isParenthesizedExpression(node) || ts5.isNonNullExpression(node)) return scalarView(node.expression, view, jsx);
|
|
979
|
+
if (ts5.isTypeOfExpression(node)) return scalarView(node.expression, view);
|
|
980
|
+
if (ts5.isConditionalExpression(node)) return scalarView(node.condition, view) && scalarView(node.whenTrue, view, jsx) && scalarView(node.whenFalse, view, jsx);
|
|
981
|
+
if (ts5.isBinaryExpression(node)) return binaryView(node, view, jsx);
|
|
982
|
+
if (ts5.isPrefixUnaryExpression(node)) return SCALAR_PREFIXES.has(node.operator) && scalarView(node.operand, view);
|
|
983
|
+
if (ts5.isTemplateExpression(node)) return node.templateSpans.every((span) => scalarView(span.expression, view));
|
|
984
|
+
return jsx && jsxView(node, view);
|
|
985
|
+
}
|
|
986
|
+
function scalarCall(node, view) {
|
|
987
|
+
if (!view.callProgram || node.questionDotToken || node.typeArguments?.length || !ts5.isIdentifier(node.expression) || !node.arguments.length || node.arguments.some(ts5.isSpreadElement)) return false;
|
|
988
|
+
const declarations = view.checker.getSymbolAtLocation(node.expression)?.declarations;
|
|
989
|
+
const declaration = declarations?.length === 1 ? declarations[0] : void 0;
|
|
990
|
+
const helper = declaration && localHelper(declaration);
|
|
991
|
+
if (!helper || helper.getSourceFile() !== node.getSourceFile() || helper.typeParameters?.length || !helper.type || !node.arguments.every((argument) => scalarView(argument, view))) return false;
|
|
992
|
+
if (!checkedNativeSource(view.callProgram, node.getSourceFile())) return false;
|
|
993
|
+
const signature = view.checker.getResolvedSignature(node);
|
|
994
|
+
return signature?.declaration === helper && !view.checker.getTypePredicateOfSignature(signature) && scalarType(view.checker.getTypeAtLocation(node));
|
|
995
|
+
}
|
|
996
|
+
function localHelper(node) {
|
|
997
|
+
if (ts5.isFunctionDeclaration(node)) return node.body && ts5.isSourceFile(node.parent) ? node : void 0;
|
|
998
|
+
if (!ts5.isVariableDeclaration(node) || node.type || !node.initializer || constInitializer(node) !== node.initializer || !ts5.isArrowFunction(node.initializer) || !ts5.isVariableStatement(node.parent.parent) || !ts5.isSourceFile(node.parent.parent.parent)) return void 0;
|
|
999
|
+
return node.initializer;
|
|
1000
|
+
}
|
|
1001
|
+
function binaryView(node, view, jsx) {
|
|
1002
|
+
const returned2 = jsx && RETURNED_OPERANDS.has(node.operatorToken.kind);
|
|
1003
|
+
return SCALAR_OPERATORS.has(node.operatorToken.kind) && scalarView(node.left, view, returned2) && scalarView(node.right, view, returned2);
|
|
1004
|
+
}
|
|
1005
|
+
function scalarLiteral(node) {
|
|
1006
|
+
return ts5.isStringLiteralLike(node) || ts5.isNumericLiteral(node) || ts5.isBigIntLiteral(node) || ts5.isJsxText(node) || node.kind === ts5.SyntaxKind.TrueKeyword || node.kind === ts5.SyntaxKind.FalseKeyword || node.kind === ts5.SyntaxKind.NullKeyword;
|
|
1007
|
+
}
|
|
1008
|
+
function memberRead(node, view) {
|
|
1009
|
+
if (!view.root || !ts5.isIdentifier(node.expression) || view.checker.getSymbolAtLocation(node.expression) !== view.root) return false;
|
|
1010
|
+
const key = ts5.isPropertyAccessExpression(node) ? node.name.text : node.argumentExpression && (ts5.isStringLiteralLike(node.argumentExpression) || ts5.isNumericLiteral(node.argumentExpression)) ? node.argumentExpression.text : void 0;
|
|
1011
|
+
return key !== void 0 && readField(node, key, view);
|
|
1012
|
+
}
|
|
1013
|
+
function readField(node, key, view) {
|
|
1014
|
+
if (!view.checker.getPropertyOfType(view.props, key) || !scalarType(view.checker.getTypeAtLocation(node))) return false;
|
|
1015
|
+
view.reads.add(key);
|
|
1016
|
+
return true;
|
|
1017
|
+
}
|
|
1018
|
+
function jsxView(node, view) {
|
|
1019
|
+
if (ts5.isJsxFragment(node)) return node.children.every((child) => scalarView(child, view, true));
|
|
1020
|
+
if (ts5.isJsxElement(node)) return jsxView(node.openingElement, view) && node.children.every((child) => scalarView(child, view, true));
|
|
1021
|
+
if (!ts5.isJsxOpeningElement(node) && !ts5.isJsxSelfClosingElement(node)) return false;
|
|
1022
|
+
if (!ts5.isIdentifier(node.tagName) || !/^[a-z][A-Za-z0-9]*$/u.test(node.tagName.text)) return false;
|
|
1023
|
+
return node.attributes.properties.every((attribute) => intrinsicAttribute(attribute, view));
|
|
1024
|
+
}
|
|
1025
|
+
function intrinsicAttribute(attribute, view) {
|
|
1026
|
+
return ts5.isJsxAttribute(attribute) && ts5.isIdentifier(attribute.name) && attribute.name.text !== "is" && (!attribute.initializer || scalarView(attribute.initializer, view));
|
|
1027
|
+
}
|
|
1028
|
+
|
|
829
1029
|
// src/rules/_stable-value-binding.ts
|
|
830
1030
|
import { AST_NODE_TYPES as AST_NODE_TYPES6 } from "@typescript-eslint/utils";
|
|
831
1031
|
function typeOnlyReference(reference) {
|
|
@@ -846,8 +1046,107 @@ function stableValueBinding(variable, acceptRead) {
|
|
|
846
1046
|
});
|
|
847
1047
|
}
|
|
848
1048
|
|
|
1049
|
+
// src/rules/_private-scalar-consumer.ts
|
|
1050
|
+
function directEval(node) {
|
|
1051
|
+
let callee = unwrapExpression(node.callee);
|
|
1052
|
+
while (callee.type === AST_NODE_TYPES7.TSInstantiationExpression) callee = unwrapExpression(callee.expression);
|
|
1053
|
+
return callee.type === AST_NODE_TYPES7.Identifier && callee.name === "eval";
|
|
1054
|
+
}
|
|
1055
|
+
function primitiveKeyword(node) {
|
|
1056
|
+
return node !== void 0 && (node.kind === ts6.SyntaxKind.StringKeyword || node.kind === ts6.SyntaxKind.NumberKeyword || node.kind === ts6.SyntaxKind.BooleanKeyword || node.kind === ts6.SyntaxKind.BigIntKeyword);
|
|
1057
|
+
}
|
|
1058
|
+
function nullishPrimitiveUnion(node) {
|
|
1059
|
+
return node !== void 0 && ts6.isUnionTypeNode(node) && node.types.length === 2 && node.types.some(primitiveKeyword) && node.types.some((part) => part.kind === ts6.SyntaxKind.UndefinedKeyword || ts6.isLiteralTypeNode(part) && part.literal.kind === ts6.SyntaxKind.NullKeyword);
|
|
1060
|
+
}
|
|
1061
|
+
function consumerAnnotation(node, auxiliaryScalars = false) {
|
|
1062
|
+
if (node.params.length !== 1) {
|
|
1063
|
+
if (!auxiliaryScalars) return void 0;
|
|
1064
|
+
let annotation;
|
|
1065
|
+
for (const parameter2 of node.params) {
|
|
1066
|
+
if (parameter2.type !== AST_NODE_TYPES7.Identifier && parameter2.type !== AST_NODE_TYPES7.ObjectPattern) continue;
|
|
1067
|
+
const current = parameter2.typeAnnotation?.typeAnnotation;
|
|
1068
|
+
if (current?.type !== AST_NODE_TYPES7.TSTypeLiteral) continue;
|
|
1069
|
+
if (annotation) return void 0;
|
|
1070
|
+
annotation = current;
|
|
1071
|
+
}
|
|
1072
|
+
return annotation;
|
|
1073
|
+
}
|
|
1074
|
+
const parameter = node.params[0];
|
|
1075
|
+
return parameter?.type === AST_NODE_TYPES7.Identifier || parameter?.type === AST_NODE_TYPES7.ObjectPattern ? parameter.typeAnnotation?.typeAnnotation : void 0;
|
|
1076
|
+
}
|
|
1077
|
+
function exportedSymbols(source, checker) {
|
|
1078
|
+
const symbol = checker.getSymbolAtLocation(source);
|
|
1079
|
+
return new Set(symbol ? checker.getExportsOfModule(symbol).map((entry) => (entry.flags & ts6.SymbolFlags.Alias) !== 0 ? checker.getAliasedSymbol(entry) : entry) : []);
|
|
1080
|
+
}
|
|
1081
|
+
function privateScalarConsumer(node, sourceCode, services, exports, options = {}) {
|
|
1082
|
+
const native = services.esTreeNodeToTSNodeMap.get(node);
|
|
1083
|
+
if (!ts6.isFunctionDeclaration(native) && !ts6.isArrowFunction(native) || !native.body) return null;
|
|
1084
|
+
let parameter = native.parameters[0];
|
|
1085
|
+
if (native.parameters.length !== 1) {
|
|
1086
|
+
const annotation = consumerAnnotation(node, options.auxiliaryScalars);
|
|
1087
|
+
const selected = annotation && services.esTreeNodeToTSNodeMap.get(annotation);
|
|
1088
|
+
parameter = native.parameters.find((entry) => entry.type === selected);
|
|
1089
|
+
}
|
|
1090
|
+
if (!parameter || !independentSignature(native, parameter, options.auxiliaryScalars === true)) return null;
|
|
1091
|
+
const checker = services.program.getTypeChecker();
|
|
1092
|
+
if (!ts6.isExternalModule(native.getSourceFile()) || !services.program.getCompilerOptions().strict) return null;
|
|
1093
|
+
if (!privateDirectCallable(node, native, sourceCode, checker, exports)) return null;
|
|
1094
|
+
const signature = checker.getSignatureFromDeclaration(native);
|
|
1095
|
+
if (!signature || signature.typeParameters?.length || checker.getTypePredicateOfSignature(signature)) return null;
|
|
1096
|
+
const expression = returnedExpression(native.body);
|
|
1097
|
+
if (!expression || !checker.isTypeAssignableTo(checker.getTypeAtLocation(expression), checker.getReturnTypeOfSignature(signature))) return null;
|
|
1098
|
+
const auxiliaries = native.parameters.length > 1 ? auxiliaryBindings(native, parameter, checker) : void 0;
|
|
1099
|
+
if (auxiliaries === null) return null;
|
|
1100
|
+
const reads = scalarParameterReads(parameter, native.body, checker, options.scalarCalls ? services.program : void 0, auxiliaries);
|
|
1101
|
+
return reads?.size ? { parameter, reads } : null;
|
|
1102
|
+
}
|
|
1103
|
+
function privateDirectCallable(node, native, sourceCode, checker, exports) {
|
|
1104
|
+
const binding3 = callableBinding(node, sourceCode);
|
|
1105
|
+
if (!binding3 || binding3.defs.length !== 1) return false;
|
|
1106
|
+
const name = ts6.isFunctionDeclaration(native) ? native.name : ts6.isVariableDeclaration(native.parent) ? native.parent.name : void 0;
|
|
1107
|
+
const symbol = name && checker.getSymbolAtLocation(name);
|
|
1108
|
+
return symbol !== void 0 && symbol.declarations?.length === 1 && !exports.has(symbol) && directCalls(binding3, native.parameters.length);
|
|
1109
|
+
}
|
|
1110
|
+
function independentSignature(native, selected, auxiliaryScalars) {
|
|
1111
|
+
if (!auxiliaryScalars && native.parameters.length !== 1 || native.typeParameters?.length || native.asteriskToken || native.modifiers?.length || !primitiveKeyword(native.type)) return false;
|
|
1112
|
+
return native.parameters.every((parameter) => parameter.type !== void 0 && !parameter.modifiers?.length && !parameter.questionToken && !parameter.initializer && !parameter.dotDotDotToken && (!ts6.isIdentifier(parameter.name) || parameter.name.text !== "this") && (parameter === selected || ts6.isIdentifier(parameter.name) && primitiveKeyword(parameter.type)));
|
|
1113
|
+
}
|
|
1114
|
+
function auxiliaryBindings(native, selected, checker) {
|
|
1115
|
+
const bindings = /* @__PURE__ */ new Set();
|
|
1116
|
+
for (const parameter of native.parameters) {
|
|
1117
|
+
if (parameter === selected) continue;
|
|
1118
|
+
const symbol = ts6.isIdentifier(parameter.name) ? checker.getSymbolAtLocation(parameter.name) : void 0;
|
|
1119
|
+
if (!symbol || symbol.declarations?.length !== 1 || symbol.declarations[0] !== parameter || bindings.has(symbol)) return null;
|
|
1120
|
+
bindings.add(symbol);
|
|
1121
|
+
}
|
|
1122
|
+
return bindings;
|
|
1123
|
+
}
|
|
1124
|
+
function callableBinding(node, sourceCode) {
|
|
1125
|
+
if (node.type === AST_NODE_TYPES7.FunctionDeclaration) {
|
|
1126
|
+
if (node.parent.type !== AST_NODE_TYPES7.Program) return void 0;
|
|
1127
|
+
return sourceCode.getDeclaredVariables(node).find((variable) => variable.defs.some((definition) => definition.type === "FunctionName" && definition.node === node));
|
|
1128
|
+
}
|
|
1129
|
+
const declaration = node.parent;
|
|
1130
|
+
if (declaration.type !== AST_NODE_TYPES7.VariableDeclarator || declaration.init !== node || declaration.id.type !== AST_NODE_TYPES7.Identifier || declaration.id.typeAnnotation || declaration.parent.kind !== "const" || declaration.parent.parent.type !== AST_NODE_TYPES7.Program) return void 0;
|
|
1131
|
+
return sourceCode.getDeclaredVariables(declaration).find((variable) => variable.defs.some((definition) => definition.type === "Variable" && definition.node === declaration));
|
|
1132
|
+
}
|
|
1133
|
+
function directCalls(binding3, arity) {
|
|
1134
|
+
let calls = 0;
|
|
1135
|
+
const stable2 = stableValueBinding(binding3, (reference) => {
|
|
1136
|
+
const identifier = reference.identifier;
|
|
1137
|
+
const call = identifier.parent;
|
|
1138
|
+
if (reference.isTypeReference || !reference.isReadOnly() || call.type !== AST_NODE_TYPES7.CallExpression || call.callee !== identifier || call.optional || call.typeArguments || call.arguments.length !== arity || !call.arguments.every((argument) => argument.type === AST_NODE_TYPES7.Identifier)) return false;
|
|
1139
|
+
calls += 1;
|
|
1140
|
+
return true;
|
|
1141
|
+
});
|
|
1142
|
+
return stable2 && calls > 0;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
849
1145
|
// src/rules/_react-prop-bindings.ts
|
|
850
1146
|
var VIEWS = /* @__PURE__ */ new WeakMap();
|
|
1147
|
+
var DIRECT_EVAL = /* @__PURE__ */ new WeakMap();
|
|
1148
|
+
var REACT_IMPORTS = /* @__PURE__ */ new WeakMap();
|
|
1149
|
+
var PARAMETER_BINDINGS = /* @__PURE__ */ new WeakMap();
|
|
851
1150
|
function renderFunction(node) {
|
|
852
1151
|
let parent = node.parent;
|
|
853
1152
|
while (parent !== void 0 && parent !== null) {
|
|
@@ -864,13 +1163,27 @@ function renderFunction(node) {
|
|
|
864
1163
|
return null;
|
|
865
1164
|
}
|
|
866
1165
|
function firstParameterBindings(source, node) {
|
|
1166
|
+
let functions = PARAMETER_BINDINGS.get(source);
|
|
1167
|
+
if (functions === void 0) {
|
|
1168
|
+
functions = /* @__PURE__ */ new WeakMap();
|
|
1169
|
+
PARAMETER_BINDINGS.set(source, functions);
|
|
1170
|
+
}
|
|
1171
|
+
let bindings = functions.get(node);
|
|
1172
|
+
if (bindings === void 0) {
|
|
1173
|
+
bindings = collectParameterBindings(source, node);
|
|
1174
|
+
functions.set(node, bindings);
|
|
1175
|
+
}
|
|
1176
|
+
return bindings;
|
|
1177
|
+
}
|
|
1178
|
+
function collectParameterBindings(source, node) {
|
|
1179
|
+
if (hasDirectEval(source)) return /* @__PURE__ */ new Set();
|
|
867
1180
|
const parameter = node.params[0];
|
|
868
1181
|
const identifiers = [];
|
|
869
|
-
if (parameter?.type ===
|
|
1182
|
+
if (parameter?.type === AST_NODE_TYPES8.Identifier)
|
|
870
1183
|
identifiers.push(parameter);
|
|
871
|
-
if (parameter?.type ===
|
|
1184
|
+
if (parameter?.type === AST_NODE_TYPES8.ObjectPattern) {
|
|
872
1185
|
for (const property of parameter.properties) {
|
|
873
|
-
if (property.type ===
|
|
1186
|
+
if (property.type === AST_NODE_TYPES8.Property && !property.computed && property.value.type === AST_NODE_TYPES8.Identifier)
|
|
874
1187
|
identifiers.push(property.value);
|
|
875
1188
|
}
|
|
876
1189
|
}
|
|
@@ -882,17 +1195,34 @@ function firstParameterBindings(source, node) {
|
|
|
882
1195
|
)
|
|
883
1196
|
);
|
|
884
1197
|
}
|
|
1198
|
+
function hasDirectEval(source) {
|
|
1199
|
+
let found = DIRECT_EVAL.get(source);
|
|
1200
|
+
if (found !== void 0) return found;
|
|
1201
|
+
found = source.scopeManager?.scopes.some(
|
|
1202
|
+
(scope) => scope.references.some(({ identifier }) => {
|
|
1203
|
+
if (identifier.type !== AST_NODE_TYPES8.Identifier || identifier.name !== "eval")
|
|
1204
|
+
return false;
|
|
1205
|
+
let callee = outerExpression(identifier);
|
|
1206
|
+
while (callee.parent?.type === AST_NODE_TYPES8.TSInstantiationExpression && callee.parent.expression === callee)
|
|
1207
|
+
callee = outerExpression(callee.parent);
|
|
1208
|
+
const call = callee.parent;
|
|
1209
|
+
return call?.type === AST_NODE_TYPES8.CallExpression && call.callee === callee && !call.optional && directEval(call);
|
|
1210
|
+
})
|
|
1211
|
+
) ?? true;
|
|
1212
|
+
DIRECT_EVAL.set(source, found);
|
|
1213
|
+
return found;
|
|
1214
|
+
}
|
|
885
1215
|
function parameterPath(source, node, bindings) {
|
|
886
1216
|
let current = unwrapExpression(node);
|
|
887
1217
|
for (let depth = 0; depth < 64; depth += 1) {
|
|
888
|
-
if (current.type ===
|
|
1218
|
+
if (current.type === AST_NODE_TYPES8.Identifier) {
|
|
889
1219
|
const variable = ASTUtils3.findVariable(
|
|
890
1220
|
source.getScope(current),
|
|
891
1221
|
current.name
|
|
892
1222
|
);
|
|
893
1223
|
return variable !== null && bindings.has(variable);
|
|
894
1224
|
}
|
|
895
|
-
if (current.type !==
|
|
1225
|
+
if (current.type !== AST_NODE_TYPES8.MemberExpression || current.optional || current.computed && (current.property.type !== AST_NODE_TYPES8.Literal || typeof current.property.value !== "string"))
|
|
896
1226
|
return false;
|
|
897
1227
|
current = unwrapExpression(current.object);
|
|
898
1228
|
}
|
|
@@ -902,8 +1232,8 @@ function reactHook(source, callee, hook) {
|
|
|
902
1232
|
callee = unwrapExpression(callee);
|
|
903
1233
|
let identifier;
|
|
904
1234
|
let namespace = false;
|
|
905
|
-
if (callee.type ===
|
|
906
|
-
else if (callee.type ===
|
|
1235
|
+
if (callee.type === AST_NODE_TYPES8.Identifier) identifier = callee;
|
|
1236
|
+
else if (callee.type === AST_NODE_TYPES8.MemberExpression && !callee.optional && ASTUtils3.getPropertyName(callee) === hook && callee.object.type === AST_NODE_TYPES8.Identifier) {
|
|
907
1237
|
identifier = callee.object;
|
|
908
1238
|
namespace = true;
|
|
909
1239
|
} else return false;
|
|
@@ -911,16 +1241,21 @@ function reactHook(source, callee, hook) {
|
|
|
911
1241
|
source.getScope(identifier),
|
|
912
1242
|
identifier.name
|
|
913
1243
|
);
|
|
914
|
-
if (variable === null
|
|
915
|
-
|
|
1244
|
+
if (variable === null) return false;
|
|
1245
|
+
const specifier = reactImportSpecifier(variable);
|
|
1246
|
+
if (specifier === null) return false;
|
|
1247
|
+
return namespace ? specifier.type === AST_NODE_TYPES8.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES8.ImportNamespaceSpecifier : specifier.type === AST_NODE_TYPES8.ImportSpecifier && specifier.importKind !== "type" && importSpecifierName(specifier) === hook;
|
|
1248
|
+
}
|
|
1249
|
+
function reactImportSpecifier(variable) {
|
|
1250
|
+
let specifier = REACT_IMPORTS.get(variable);
|
|
1251
|
+
if (specifier !== void 0) return specifier;
|
|
916
1252
|
const definition = variable.defs[0];
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
return namespace ? specifier.type === AST_NODE_TYPES7.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES7.ImportNamespaceSpecifier : specifier.type === AST_NODE_TYPES7.ImportSpecifier && specifier.importKind !== "type" && importSpecifierName(specifier) === hook;
|
|
1253
|
+
specifier = variable.defs.length === 1 && definition?.type === "ImportBinding" && definition.parent.type === AST_NODE_TYPES8.ImportDeclaration && definition.parent.source.value === "react" && definition.parent.importKind !== "type" && stableValueBinding(variable) ? definition.node : null;
|
|
1254
|
+
REACT_IMPORTS.set(variable, specifier);
|
|
1255
|
+
return specifier;
|
|
921
1256
|
}
|
|
922
1257
|
function containsView(node) {
|
|
923
|
-
if (node.type ===
|
|
1258
|
+
if (node.type === AST_NODE_TYPES8.JSXElement || node.type === AST_NODE_TYPES8.JSXFragment)
|
|
924
1259
|
return true;
|
|
925
1260
|
if (isFunction(node)) return false;
|
|
926
1261
|
return forEachOwnAstChild(
|
|
@@ -930,7 +1265,7 @@ function containsView(node) {
|
|
|
930
1265
|
);
|
|
931
1266
|
}
|
|
932
1267
|
function isFunction(node) {
|
|
933
|
-
return node.type ===
|
|
1268
|
+
return node.type === AST_NODE_TYPES8.ArrowFunctionExpression || node.type === AST_NODE_TYPES8.FunctionDeclaration || node.type === AST_NODE_TYPES8.FunctionExpression;
|
|
934
1269
|
}
|
|
935
1270
|
|
|
936
1271
|
// src/rules/prefer-server-data-preparation.ts
|
|
@@ -970,8 +1305,8 @@ var PREFER_SERVER_DATA_PREPARATION_DOCUMENTATION = {
|
|
|
970
1305
|
category: "architecture",
|
|
971
1306
|
limitations: [
|
|
972
1307
|
"Advisory only. Local syntax cannot establish whether a caller is a Server Component, whether props change interactively or whether server preparation reduces the total cost. This rule is a review lead, never proof that code can be moved to the server. No automatic fix is provided.",
|
|
973
|
-
"Requires an explicit use client directive and parser-owned TypeScript services resolving map/filter/flatMap to the standard Array or ReadonlyArray library signature. The containing view must have an independent React useState/useReducer call or an intrinsic DOM onClick/onChange/onInput/onSubmit handler. Noninteractive boundaries remain owned by no-unnecessary-use-client; custom hooks and
|
|
974
|
-
"Every runtime reference to the source parameter binding must be a supported native data projection or a field-only JSX display loop. Inputs also needed for editing, whole-record forwarding, lookup, mutation, other fields or opaque helpers are excluded. Only direct first-parameter paths and synchronous single-expression callbacks are supported. Whole-row identity maps and constant maps are excluded; supported projections must read a fixed input field.",
|
|
1308
|
+
"Requires an explicit use client directive and parser-owned TypeScript services resolving map/filter/flatMap to the standard Array or ReadonlyArray library signature. The receiver beneath erased wrappers must itself have an Array, ReadonlyArray or tuple type after nullish narrowing; casts from opaque or custom collections do not establish this. Subclass and structural collection types outside those native array types are excluded. The containing view must have an independent React useState/useReducer call or a native callable type on an intrinsic DOM onClick/onChange/onInput/onSubmit handler. Nullish, noncallable and opaque handler types do not establish interaction. Noninteractive boundaries remain owned by no-unnecessary-use-client; custom hooks and indirect client requirements are unsupported.",
|
|
1309
|
+
"Every runtime reference to the source parameter binding must be a supported native data projection or a field-only JSX display loop. Inputs also needed for editing, whole-record forwarding, lookup, mutation, other fields or opaque helpers are excluded. Files containing direct eval are excluded because it can observe or change lexical bindings; indirect eval and properties named eval do not establish lexical access. Only direct first-parameter paths and synchronous single-expression callbacks are supported. Whole-row identity maps and constant maps are excluded; supported projections must read a fixed input field.",
|
|
975
1310
|
"JSX-rendering callbacks are never reported as preparation findings. Callback calls, captured values, destructuring defaults/rest/nesting, async callbacks, event handlers, effects, memo callbacks, opaque helpers, dynamic/optional paths, custom collection signatures, missing type services, generated source and tests are excluded. First-parameter provenance is syntactic; annotations cannot prove absence of runtime getters or patched array methods. Analysis does not claim callback purity or preserve semantics of a hypothetical move.",
|
|
976
1311
|
"Reports the direct source projection once; chained operations with a call receiver are not independently reported. A static subprojection may still be prepared by its producer while a union with pending local edits remains in the client."
|
|
977
1312
|
],
|
|
@@ -1018,306 +1353,190 @@ var prefer_server_data_preparation_default = createRule({
|
|
|
1018
1353
|
const services = getTypeServices(context);
|
|
1019
1354
|
const checker = services.program.getTypeChecker();
|
|
1020
1355
|
const interactions = /* @__PURE__ */ new WeakMap();
|
|
1356
|
+
const projectedInputs = /* @__PURE__ */ new WeakMap();
|
|
1357
|
+
const callable = (node) => {
|
|
1358
|
+
const type = checker.getTypeAtLocation(
|
|
1359
|
+
services.esTreeNodeToTSNodeMap.get(unwrapExpression(node))
|
|
1360
|
+
);
|
|
1361
|
+
const members = type.isUnion() ? type.types : [type];
|
|
1362
|
+
return members.some((member3) => member3.getCallSignatures().length > 0);
|
|
1363
|
+
};
|
|
1021
1364
|
const nativeArray = (node) => {
|
|
1365
|
+
const callee = unwrapExpression(node.callee);
|
|
1366
|
+
if (callee.type !== AST_NODE_TYPES9.MemberExpression) return false;
|
|
1367
|
+
const receiver = checker.getNonNullableType(
|
|
1368
|
+
checker.getTypeAtLocation(
|
|
1369
|
+
services.esTreeNodeToTSNodeMap.get(unwrapExpression(callee.object))
|
|
1370
|
+
)
|
|
1371
|
+
);
|
|
1372
|
+
const members = receiver.isUnion() ? receiver.types : [receiver];
|
|
1373
|
+
if (!members.every(
|
|
1374
|
+
(type) => checker.isArrayType(type) || checker.isTupleType(type)
|
|
1375
|
+
))
|
|
1376
|
+
return false;
|
|
1022
1377
|
const declaration = checker.getResolvedSignature(
|
|
1023
1378
|
services.esTreeNodeToTSNodeMap.get(node)
|
|
1024
1379
|
)?.declaration;
|
|
1025
1380
|
return declaration !== void 0 && services.program.isSourceFileDefaultLibrary(
|
|
1026
1381
|
declaration.getSourceFile()
|
|
1027
|
-
) &&
|
|
1382
|
+
) && ts7.isInterfaceDeclaration(declaration.parent) && ["Array", "ReadonlyArray"].includes(declaration.parent.name.text);
|
|
1028
1383
|
};
|
|
1029
1384
|
return {
|
|
1030
1385
|
CallExpression(node) {
|
|
1031
1386
|
const callee = unwrapExpression(node.callee);
|
|
1032
|
-
if (node.optional || callee.type !==
|
|
1387
|
+
if (node.optional || callee.type !== AST_NODE_TYPES9.MemberExpression || callee.optional || node.arguments.length !== 1 || !METHODS.has(ASTUtils4.getPropertyName(callee) ?? ""))
|
|
1033
1388
|
return;
|
|
1034
1389
|
const callback = node.arguments[0];
|
|
1035
|
-
if (callback?.type !==
|
|
1390
|
+
if (callback?.type !== AST_NODE_TYPES9.ArrowFunctionExpression && callback?.type !== AST_NODE_TYPES9.FunctionExpression)
|
|
1036
1391
|
return;
|
|
1037
1392
|
const component = renderFunction(node);
|
|
1038
1393
|
if (component === null || !parameterPath(
|
|
1039
1394
|
context.sourceCode,
|
|
1040
1395
|
callee.object,
|
|
1041
1396
|
firstParameterBindings(context.sourceCode, component)
|
|
1042
|
-
) || !projection(context.sourceCode, callback)
|
|
1397
|
+
) || !projection(context.sourceCode, callback))
|
|
1043
1398
|
return;
|
|
1044
1399
|
let interactive = interactions.get(component);
|
|
1045
1400
|
if (interactive === void 0) {
|
|
1046
|
-
interactive = clientInteraction(
|
|
1401
|
+
interactive = clientInteraction(
|
|
1402
|
+
context.sourceCode,
|
|
1403
|
+
component.body,
|
|
1404
|
+
callable
|
|
1405
|
+
);
|
|
1047
1406
|
interactions.set(component, interactive);
|
|
1048
|
-
}
|
|
1049
|
-
if (!interactive
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
return
|
|
1066
|
-
const parameter = callback.params[0];
|
|
1067
|
-
if (parameter?.type === AST_NODE_TYPES8.ObjectPattern && parameter.properties.some(
|
|
1068
|
-
(property) => property.type !== AST_NODE_TYPES8.Property || property.computed || property.value.type !== AST_NODE_TYPES8.Identifier
|
|
1069
|
-
))
|
|
1070
|
-
return false;
|
|
1071
|
-
const parameters = firstParameterBindings(source, callback);
|
|
1072
|
-
if (parameters.size === 0) return false;
|
|
1073
|
-
let body3 = callback.body;
|
|
1074
|
-
if (body3.type === AST_NODE_TYPES8.BlockStatement) {
|
|
1075
|
-
const [statement] = body3.body;
|
|
1076
|
-
if (body3.body.length !== 1 || statement?.type !== AST_NODE_TYPES8.ReturnStatement || statement.argument === null)
|
|
1077
|
-
return false;
|
|
1078
|
-
body3 = statement.argument;
|
|
1079
|
-
}
|
|
1080
|
-
let fieldRead = false;
|
|
1081
|
-
const inspect = (node, depth) => {
|
|
1082
|
-
if (depth > 64) return false;
|
|
1083
|
-
node = unwrapExpression(node);
|
|
1084
|
-
if (parameterPath(source, node, parameters)) {
|
|
1085
|
-
if (node.type !== AST_NODE_TYPES8.MemberExpression && callback.params[0]?.type !== AST_NODE_TYPES8.ObjectPattern)
|
|
1086
|
-
return false;
|
|
1087
|
-
fieldRead = true;
|
|
1088
|
-
return true;
|
|
1089
|
-
}
|
|
1090
|
-
if (node.type === AST_NODE_TYPES8.Literal) return !("regex" in node);
|
|
1091
|
-
if (node.type === AST_NODE_TYPES8.UnaryExpression)
|
|
1092
|
-
return ["!", "+", "-", "~", "typeof"].includes(node.operator) && inspect(node.argument, depth + 1);
|
|
1093
|
-
if (node.type === AST_NODE_TYPES8.BinaryExpression)
|
|
1094
|
-
return BINARY.has(node.operator) && inspect(node.left, depth + 1) && inspect(node.right, depth + 1);
|
|
1095
|
-
if (node.type === AST_NODE_TYPES8.LogicalExpression)
|
|
1096
|
-
return inspect(node.left, depth + 1) && inspect(node.right, depth + 1);
|
|
1097
|
-
if (node.type === AST_NODE_TYPES8.ConditionalExpression)
|
|
1098
|
-
return inspect(node.test, depth + 1) && inspect(node.consequent, depth + 1) && inspect(node.alternate, depth + 1);
|
|
1099
|
-
if (node.type === AST_NODE_TYPES8.ObjectExpression)
|
|
1100
|
-
return node.properties.every(
|
|
1101
|
-
(property) => property.type === AST_NODE_TYPES8.Property && property.kind === "init" && !property.method && !property.computed && inspect(property.value, depth + 1)
|
|
1102
|
-
);
|
|
1103
|
-
return mode === "view" && displayProjection(node, (child) => inspect(child, depth + 1));
|
|
1104
|
-
};
|
|
1105
|
-
return inspect(body3, 0) && fieldRead;
|
|
1106
|
-
}
|
|
1107
|
-
function displayProjection(node, inspectChild) {
|
|
1108
|
-
if (node.type === AST_NODE_TYPES8.JSXElement)
|
|
1109
|
-
return node.openingElement.attributes.every(
|
|
1110
|
-
(attribute) => attribute.type === AST_NODE_TYPES8.JSXAttribute && (attribute.value === null || inspectChild(attribute.value))
|
|
1111
|
-
) && node.children.every(inspectChild);
|
|
1112
|
-
if (node.type === AST_NODE_TYPES8.JSXFragment)
|
|
1113
|
-
return node.children.every(inspectChild);
|
|
1114
|
-
if (node.type === AST_NODE_TYPES8.JSXText) return true;
|
|
1115
|
-
if (node.type === AST_NODE_TYPES8.JSXExpressionContainer)
|
|
1116
|
-
return node.expression.type === AST_NODE_TYPES8.JSXEmptyExpression || inspectChild(node.expression);
|
|
1117
|
-
return false;
|
|
1118
|
-
}
|
|
1119
|
-
function onlyProjectedInput(source, receiver, nativeArray) {
|
|
1120
|
-
let root = unwrapExpression(receiver);
|
|
1121
|
-
while (root.type === AST_NODE_TYPES8.MemberExpression)
|
|
1122
|
-
root = unwrapExpression(root.object);
|
|
1123
|
-
if (root.type !== AST_NODE_TYPES8.Identifier) return false;
|
|
1124
|
-
const variable = ASTUtils4.findVariable(source.getScope(root), root.name);
|
|
1125
|
-
return variable !== null && variable.references.every((reference) => {
|
|
1126
|
-
if (typeOnlyReference(reference)) return true;
|
|
1127
|
-
if (!reference.isRead()) return false;
|
|
1128
|
-
let access = outerExpression(reference.identifier);
|
|
1129
|
-
let parent = access.parent;
|
|
1130
|
-
while (parent?.type === AST_NODE_TYPES8.MemberExpression && parent.object === access) {
|
|
1131
|
-
access = outerExpression(parent);
|
|
1132
|
-
parent = access.parent;
|
|
1133
|
-
}
|
|
1134
|
-
const member3 = unwrapExpression(access);
|
|
1135
|
-
const call = parent;
|
|
1136
|
-
if (call?.type !== AST_NODE_TYPES8.CallExpression) return false;
|
|
1137
|
-
if (member3.type !== AST_NODE_TYPES8.MemberExpression || member3.optional || !METHODS.has(ASTUtils4.getPropertyName(member3) ?? "") || call.optional || call.arguments.length !== 1 || !nativeArray(call))
|
|
1138
|
-
return false;
|
|
1139
|
-
const callback = call.arguments[0];
|
|
1140
|
-
return (callback?.type === AST_NODE_TYPES8.ArrowFunctionExpression || callback?.type === AST_NODE_TYPES8.FunctionExpression) && (projection(source, callback) || projection(source, callback, "view")) && call.callee === access;
|
|
1141
|
-
});
|
|
1142
|
-
}
|
|
1143
|
-
function clientInteraction(source, node) {
|
|
1144
|
-
if (node.type === AST_NODE_TYPES8.ArrowFunctionExpression || node.type === AST_NODE_TYPES8.FunctionExpression || node.type === AST_NODE_TYPES8.FunctionDeclaration)
|
|
1145
|
-
return false;
|
|
1146
|
-
if (node.type === AST_NODE_TYPES8.CallExpression && (reactHook(source, node.callee, "useState") || reactHook(source, node.callee, "useReducer")))
|
|
1147
|
-
return true;
|
|
1148
|
-
if (node.type === AST_NODE_TYPES8.JSXOpeningElement && node.name.type === AST_NODE_TYPES8.JSXIdentifier && /^[a-z]/u.test(node.name.name) && node.attributes.some(
|
|
1149
|
-
(attribute) => attribute.type === AST_NODE_TYPES8.JSXAttribute && attribute.name.type === AST_NODE_TYPES8.JSXIdentifier && DOM_EVENTS.has(attribute.name.name) && attribute.value !== null
|
|
1150
|
-
))
|
|
1151
|
-
return true;
|
|
1152
|
-
return forEachOwnAstChild(
|
|
1153
|
-
node,
|
|
1154
|
-
(child) => clientInteraction(source, child),
|
|
1155
|
-
(key) => key !== "tokens" && key !== "comments"
|
|
1156
|
-
);
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1159
|
-
// src/rules/no-readonly-prop-state.ts
|
|
1160
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES11 } from "@typescript-eslint/utils";
|
|
1161
|
-
import ts4 from "typescript";
|
|
1162
|
-
|
|
1163
|
-
// src/rules/_unused-private-binding.ts
|
|
1164
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES10 } from "@typescript-eslint/utils";
|
|
1165
|
-
|
|
1166
|
-
// src/rules/_type-binding.ts
|
|
1167
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES9 } from "@typescript-eslint/utils";
|
|
1168
|
-
function typeBinding(source, identifier) {
|
|
1169
|
-
let scope = source.getScope(identifier);
|
|
1170
|
-
while (scope !== null) {
|
|
1171
|
-
const variable = scope.set.get(identifier.name);
|
|
1172
|
-
if (variable !== void 0 && (variable.isTypeVariable || variable.defs.some((definition) => definition.isTypeDefinition))) {
|
|
1173
|
-
return variable;
|
|
1174
|
-
}
|
|
1175
|
-
scope = scope.upper;
|
|
1176
|
-
}
|
|
1177
|
-
return null;
|
|
1178
|
-
}
|
|
1179
|
-
var REFERENCE_INDEXES = /* @__PURE__ */ new WeakMap();
|
|
1180
|
-
function retainsNamedTypeUses(source, removed) {
|
|
1181
|
-
const manager = source.scopeManager;
|
|
1182
|
-
if (manager === null) return false;
|
|
1183
|
-
const index = referenceIndex(source, manager);
|
|
1184
|
-
for (const reference of referencesWithin(index.references, removed)) {
|
|
1185
|
-
if (!reference.isRead()) continue;
|
|
1186
|
-
const binding3 = reference.resolved;
|
|
1187
|
-
if (!binding3 || !reference.isTypeReference && !reference.isValueReference) return false;
|
|
1188
|
-
if (binding3.defs.length === 0) continue;
|
|
1189
|
-
const reads = publicReadExtents(index, binding3);
|
|
1190
|
-
const extent = reference.isTypeReference ? reference.isValueReference ? reads.both : reads.type : reads.value;
|
|
1191
|
-
if (extent === null || extent.minStart >= removed.range[0] && extent.maxEnd <= removed.range[1]) return false;
|
|
1192
|
-
}
|
|
1193
|
-
return true;
|
|
1194
|
-
}
|
|
1195
|
-
function referenceIndex(source, manager) {
|
|
1196
|
-
const cached = REFERENCE_INDEXES.get(source);
|
|
1197
|
-
if (cached?.manager === manager) return cached;
|
|
1198
|
-
const references = manager.scopes.flatMap((scope) => scope.references);
|
|
1199
|
-
references.sort((left, right) => left.identifier.range[0] - right.identifier.range[0]);
|
|
1200
|
-
const index = { manager, references, publicReads: /* @__PURE__ */ new Map() };
|
|
1201
|
-
REFERENCE_INDEXES.set(source, index);
|
|
1202
|
-
return index;
|
|
1203
|
-
}
|
|
1204
|
-
function* referencesWithin(references, removed) {
|
|
1205
|
-
let low = 0;
|
|
1206
|
-
let high = references.length;
|
|
1207
|
-
while (low < high) {
|
|
1208
|
-
const middle = low + Math.floor((high - low) / 2);
|
|
1209
|
-
const reference = references[middle];
|
|
1210
|
-
if (reference === void 0 || reference.identifier.range[0] >= removed.range[0]) high = middle;
|
|
1211
|
-
else low = middle + 1;
|
|
1212
|
-
}
|
|
1213
|
-
for (let index = low; index < references.length; index++) {
|
|
1214
|
-
const reference = references[index];
|
|
1215
|
-
if (reference === void 0) continue;
|
|
1216
|
-
if (reference.identifier.range[0] > removed.range[1]) break;
|
|
1217
|
-
if (insideTypeRange(reference.identifier, removed)) yield reference;
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1220
|
-
function publicReadExtents(index, binding3) {
|
|
1221
|
-
const cached = index.publicReads.get(binding3);
|
|
1222
|
-
if (cached !== void 0) return cached;
|
|
1223
|
-
let type = null;
|
|
1224
|
-
let value = null;
|
|
1225
|
-
let both = null;
|
|
1226
|
-
for (const retained of binding3.references) {
|
|
1227
|
-
if (!retained.isRead() || !retained.isTypeReference && !retained.isValueReference || binding3.defs.some((definition) => insideTypeRange(retained.identifier, definition.node)) || !publicTypeUse(retained.identifier)) continue;
|
|
1228
|
-
if (retained.isTypeReference) type = extendExtent(type, retained.identifier);
|
|
1229
|
-
if (retained.isValueReference) value = extendExtent(value, retained.identifier);
|
|
1230
|
-
if (retained.isTypeReference && retained.isValueReference) both = extendExtent(both, retained.identifier);
|
|
1231
|
-
}
|
|
1232
|
-
const result = { type, value, both };
|
|
1233
|
-
index.publicReads.set(binding3, result);
|
|
1234
|
-
return result;
|
|
1235
|
-
}
|
|
1236
|
-
function extendExtent(extent, identifier) {
|
|
1237
|
-
return {
|
|
1238
|
-
minStart: Math.min(extent?.minStart ?? identifier.range[0], identifier.range[0]),
|
|
1239
|
-
maxEnd: Math.max(extent?.maxEnd ?? identifier.range[1], identifier.range[1])
|
|
1240
|
-
};
|
|
1241
|
-
}
|
|
1242
|
-
function publicTypeUse(identifier) {
|
|
1243
|
-
let node = identifier;
|
|
1244
|
-
while (node.parent) {
|
|
1245
|
-
if (node.type === AST_NODE_TYPES9.TSTypeAnnotation || node.type === AST_NODE_TYPES9.TSTypePredicate || node.type === AST_NODE_TYPES9.TSAsExpression || node.type === AST_NODE_TYPES9.TSTypeAssertion) return false;
|
|
1246
|
-
if (node.type === AST_NODE_TYPES9.TSTypeAliasDeclaration) {
|
|
1247
|
-
return node.parent.type === AST_NODE_TYPES9.ExportNamedDeclaration && node.parent.declaration === node && node.parent.parent.type === AST_NODE_TYPES9.Program;
|
|
1248
|
-
}
|
|
1249
|
-
if (node.type === AST_NODE_TYPES9.ExportSpecifier) {
|
|
1250
|
-
return node.parent.type === AST_NODE_TYPES9.ExportNamedDeclaration && node.parent.source === null && node.parent.parent.type === AST_NODE_TYPES9.Program;
|
|
1251
|
-
}
|
|
1252
|
-
node = node.parent;
|
|
1407
|
+
}
|
|
1408
|
+
if (!interactive || !onlyProjectedInput(
|
|
1409
|
+
context.sourceCode,
|
|
1410
|
+
callee.object,
|
|
1411
|
+
nativeArray,
|
|
1412
|
+
projectedInputs
|
|
1413
|
+
))
|
|
1414
|
+
return;
|
|
1415
|
+
context.report({ node, messageId: "prepareData" });
|
|
1416
|
+
}
|
|
1417
|
+
};
|
|
1418
|
+
}
|
|
1419
|
+
});
|
|
1420
|
+
function clientDirective(program) {
|
|
1421
|
+
for (const statement of program.body) {
|
|
1422
|
+
if (statement.type !== AST_NODE_TYPES9.ExpressionStatement || statement.directive === void 0)
|
|
1423
|
+
return false;
|
|
1424
|
+
if (statement.directive === "use client") return true;
|
|
1253
1425
|
}
|
|
1254
1426
|
return false;
|
|
1255
1427
|
}
|
|
1256
|
-
function
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
if (
|
|
1266
|
-
|
|
1267
|
-
if (
|
|
1268
|
-
|
|
1269
|
-
|
|
1428
|
+
function projection(source, callback, mode = "data") {
|
|
1429
|
+
if (callback.async || callback.generator || callback.params.length !== 1)
|
|
1430
|
+
return false;
|
|
1431
|
+
const parameter = callback.params[0];
|
|
1432
|
+
if (parameter?.type === AST_NODE_TYPES9.ObjectPattern && parameter.properties.some(
|
|
1433
|
+
(property) => property.type !== AST_NODE_TYPES9.Property || property.computed || property.value.type !== AST_NODE_TYPES9.Identifier
|
|
1434
|
+
))
|
|
1435
|
+
return false;
|
|
1436
|
+
const parameters = firstParameterBindings(source, callback);
|
|
1437
|
+
if (parameters.size === 0) return false;
|
|
1438
|
+
let body3 = callback.body;
|
|
1439
|
+
if (body3.type === AST_NODE_TYPES9.BlockStatement) {
|
|
1440
|
+
const [statement] = body3.body;
|
|
1441
|
+
if (body3.body.length !== 1 || statement?.type !== AST_NODE_TYPES9.ReturnStatement || statement.argument === null)
|
|
1442
|
+
return false;
|
|
1443
|
+
body3 = statement.argument;
|
|
1444
|
+
}
|
|
1445
|
+
let fieldRead = false;
|
|
1446
|
+
const inspect = (node, depth) => {
|
|
1447
|
+
if (depth > 64) return false;
|
|
1448
|
+
node = unwrapExpression(node);
|
|
1449
|
+
if (parameterPath(source, node, parameters)) {
|
|
1450
|
+
if (node.type !== AST_NODE_TYPES9.MemberExpression && callback.params[0]?.type !== AST_NODE_TYPES9.ObjectPattern)
|
|
1451
|
+
return false;
|
|
1452
|
+
fieldRead = true;
|
|
1453
|
+
return true;
|
|
1454
|
+
}
|
|
1455
|
+
if (node.type === AST_NODE_TYPES9.Literal) return !("regex" in node);
|
|
1456
|
+
if (node.type === AST_NODE_TYPES9.UnaryExpression)
|
|
1457
|
+
return ["!", "+", "-", "~", "typeof"].includes(node.operator) && inspect(node.argument, depth + 1);
|
|
1458
|
+
if (node.type === AST_NODE_TYPES9.BinaryExpression)
|
|
1459
|
+
return BINARY.has(node.operator) && inspect(node.left, depth + 1) && inspect(node.right, depth + 1);
|
|
1460
|
+
if (node.type === AST_NODE_TYPES9.LogicalExpression)
|
|
1461
|
+
return inspect(node.left, depth + 1) && inspect(node.right, depth + 1);
|
|
1462
|
+
if (node.type === AST_NODE_TYPES9.ConditionalExpression)
|
|
1463
|
+
return inspect(node.test, depth + 1) && inspect(node.consequent, depth + 1) && inspect(node.alternate, depth + 1);
|
|
1464
|
+
if (node.type === AST_NODE_TYPES9.ObjectExpression)
|
|
1465
|
+
return node.properties.every(
|
|
1466
|
+
(property) => property.type === AST_NODE_TYPES9.Property && property.kind === "init" && !property.method && !property.computed && inspect(property.value, depth + 1)
|
|
1467
|
+
);
|
|
1468
|
+
return mode === "view" && displayProjection(node, (child) => inspect(child, depth + 1));
|
|
1469
|
+
};
|
|
1470
|
+
return inspect(body3, 0) && fieldRead;
|
|
1270
1471
|
}
|
|
1271
|
-
function
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
return
|
|
1278
|
-
|
|
1472
|
+
function displayProjection(node, inspectChild) {
|
|
1473
|
+
if (node.type === AST_NODE_TYPES9.JSXElement)
|
|
1474
|
+
return node.openingElement.attributes.every(
|
|
1475
|
+
(attribute) => attribute.type === AST_NODE_TYPES9.JSXAttribute && (attribute.value === null || inspectChild(attribute.value))
|
|
1476
|
+
) && node.children.every(inspectChild);
|
|
1477
|
+
if (node.type === AST_NODE_TYPES9.JSXFragment)
|
|
1478
|
+
return node.children.every(inspectChild);
|
|
1479
|
+
if (node.type === AST_NODE_TYPES9.JSXText) return true;
|
|
1480
|
+
if (node.type === AST_NODE_TYPES9.JSXExpressionContainer)
|
|
1481
|
+
return node.expression.type === AST_NODE_TYPES9.JSXEmptyExpression || inspectChild(node.expression);
|
|
1482
|
+
return false;
|
|
1279
1483
|
}
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1484
|
+
function onlyProjectedInput(source, receiver, nativeArray, cache) {
|
|
1485
|
+
let root = unwrapExpression(receiver);
|
|
1486
|
+
while (root.type === AST_NODE_TYPES9.MemberExpression)
|
|
1487
|
+
root = unwrapExpression(root.object);
|
|
1488
|
+
if (root.type !== AST_NODE_TYPES9.Identifier) return false;
|
|
1489
|
+
const variable = ASTUtils4.findVariable(source.getScope(root), root.name);
|
|
1490
|
+
if (variable === null) return false;
|
|
1491
|
+
const cached = cache.get(variable);
|
|
1492
|
+
if (cached !== void 0) return cached;
|
|
1493
|
+
const projected = variable.references.every((reference) => {
|
|
1494
|
+
if (typeOnlyReference(reference)) return true;
|
|
1495
|
+
if (!reference.isRead()) return false;
|
|
1496
|
+
let access = outerExpression(reference.identifier);
|
|
1497
|
+
let parent = access.parent;
|
|
1498
|
+
while (parent?.type === AST_NODE_TYPES9.MemberExpression && parent.object === access) {
|
|
1499
|
+
access = outerExpression(parent);
|
|
1500
|
+
parent = access.parent;
|
|
1295
1501
|
}
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1502
|
+
const member3 = unwrapExpression(access);
|
|
1503
|
+
const call = parent;
|
|
1504
|
+
if (call?.type !== AST_NODE_TYPES9.CallExpression) return false;
|
|
1505
|
+
if (member3.type !== AST_NODE_TYPES9.MemberExpression || member3.optional || !METHODS.has(ASTUtils4.getPropertyName(member3) ?? "") || call.optional || call.arguments.length !== 1 || !nativeArray(call))
|
|
1506
|
+
return false;
|
|
1507
|
+
const callback = call.arguments[0];
|
|
1508
|
+
return (callback?.type === AST_NODE_TYPES9.ArrowFunctionExpression || callback?.type === AST_NODE_TYPES9.FunctionExpression) && (projection(source, callback) || projection(source, callback, "view")) && call.callee === access;
|
|
1509
|
+
});
|
|
1510
|
+
cache.set(variable, projected);
|
|
1511
|
+
return projected;
|
|
1300
1512
|
}
|
|
1301
|
-
function
|
|
1302
|
-
if (
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1513
|
+
function clientInteraction(source, node, callable) {
|
|
1514
|
+
if (node.type === AST_NODE_TYPES9.ArrowFunctionExpression || node.type === AST_NODE_TYPES9.FunctionExpression || node.type === AST_NODE_TYPES9.FunctionDeclaration)
|
|
1515
|
+
return false;
|
|
1516
|
+
if (node.type === AST_NODE_TYPES9.CallExpression && (reactHook(source, node.callee, "useState") || reactHook(source, node.callee, "useReducer")))
|
|
1517
|
+
return true;
|
|
1518
|
+
if (node.type === AST_NODE_TYPES9.JSXOpeningElement && node.name.type === AST_NODE_TYPES9.JSXIdentifier && /^[a-z]/u.test(node.name.name) && node.attributes.some(
|
|
1519
|
+
(attribute) => attribute.type === AST_NODE_TYPES9.JSXAttribute && attribute.name.type === AST_NODE_TYPES9.JSXIdentifier && DOM_EVENTS.has(attribute.name.name) && attribute.value?.type === AST_NODE_TYPES9.JSXExpressionContainer && attribute.value.expression.type !== AST_NODE_TYPES9.JSXEmptyExpression && callable(attribute.value.expression)
|
|
1520
|
+
))
|
|
1521
|
+
return true;
|
|
1522
|
+
return forEachOwnAstChild(
|
|
1523
|
+
node,
|
|
1524
|
+
(child) => clientInteraction(source, child, callable),
|
|
1525
|
+
(key) => key !== "tokens" && key !== "comments"
|
|
1526
|
+
);
|
|
1309
1527
|
}
|
|
1310
1528
|
|
|
1311
1529
|
// src/rules/no-readonly-prop-state.ts
|
|
1530
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES10 } from "@typescript-eslint/utils";
|
|
1531
|
+
import ts8 from "typescript";
|
|
1312
1532
|
var BEFORE2 = "import { useState } from 'react'; export function Status({ status }: { status: string }) { const [savedStatus] = useState(status); return <p>{savedStatus}</p>; }";
|
|
1313
1533
|
var AFTER2 = "export function Status({ status }: { status: string }) { return <p>{status}</p>; }";
|
|
1314
1534
|
var CONFIG2 = {
|
|
1315
1535
|
path: "tsconfig.json",
|
|
1316
1536
|
source: '{"compilerOptions":{"strict":true,"target":"ESNext","module":"ESNext","moduleResolution":"Bundler","jsx":"preserve"},"include":["src/**/*"]}'
|
|
1317
1537
|
};
|
|
1318
|
-
var
|
|
1538
|
+
var PRIMITIVE_TYPES = ts8.TypeFlags.StringLike | ts8.TypeFlags.NumberLike | ts8.TypeFlags.BigIntLike | ts8.TypeFlags.BooleanLike | ts8.TypeFlags.ESSymbolLike | ts8.TypeFlags.Null | ts8.TypeFlags.Undefined;
|
|
1319
1539
|
var MAX_TYPE_DEPTH = 16;
|
|
1320
|
-
var FUNCTION_MEMBERS = ["apply", "bind", "call"];
|
|
1321
1540
|
var NO_READONLY_PROP_STATE_DOCUMENTATION = {
|
|
1322
1541
|
defaultLevel: "warning",
|
|
1323
1542
|
summary: "Review props copied into state without a usable updater.",
|
|
@@ -1327,11 +1546,12 @@ var NO_READONLY_PROP_STATE_DOCUMENTATION = {
|
|
|
1327
1546
|
limitations: [
|
|
1328
1547
|
"Advisory only: initial snapshots can be intentional. There is no automatic fix because replacing state with current props changes how later updates behave.",
|
|
1329
1548
|
"Recognizes direct React useState imports and default/namespace member calls, including renamed imports, through lexical binding identity. Checks a direct array destructure in a function containing its own JSX and a direct first-parameter property path, or a zero-argument synchronous lazy initializer returning that path.",
|
|
1330
|
-
"Eager initializers require parser-owned TypeScript services and
|
|
1331
|
-
"An updater read, escape, reassignment or nontrivial destructuring excludes the finding. Unused state values remain owned by unused-variable checks. Opaque initialization, property aliases, optional/dynamic paths, rest/default bindings,
|
|
1549
|
+
"Eager initializers require parser-owned TypeScript services and primitive types, including unions composed entirely of primitives. Object and void types can hide callable values through structural assignment or ignored return values, so eager nonprimitive values, Any, unknown and unresolved generics are excluded. React executes function arguments as lazy initializers. Explicit zero-argument lazy callbacks returning a prop directly remain supported for all value types without type services. Opaque casts cannot prove runtime identity; lifecycle changes stay manual.",
|
|
1550
|
+
"An updater read, escape, reassignment or nontrivial destructuring excludes the finding. Unused state values remain owned by unused-variable checks. Files containing direct eval are excluded because it can observe or change lexical bindings. Indirect eval and properties named eval do not establish lexical access. Opaque initialization, property aliases, optional/dynamic paths, rest/default bindings, non-JSX hooks, generated source and tests are outside scope. This does not ban interactive useState or replace the upstream set-state-in-effect rule."
|
|
1332
1551
|
],
|
|
1333
1552
|
references: [
|
|
1334
1553
|
"https://react.dev/learn/choosing-the-state-structure",
|
|
1554
|
+
"https://react.dev/reference/react/useState",
|
|
1335
1555
|
"https://react.dev/reference/eslint-plugin-react-hooks/lints/set-state-in-effect"
|
|
1336
1556
|
],
|
|
1337
1557
|
examples: [
|
|
@@ -1369,19 +1589,19 @@ var no_readonly_prop_state_default = createRule({
|
|
|
1369
1589
|
defaultOptions: [],
|
|
1370
1590
|
create(context) {
|
|
1371
1591
|
if (isGeneratedFile(context, context.sourceCode.text) || isTestFile(context) || !context.sourceCode.ast.body.some(
|
|
1372
|
-
(statement) => statement.type ===
|
|
1373
|
-
)
|
|
1592
|
+
(statement) => statement.type === AST_NODE_TYPES10.ImportDeclaration && statement.source.value === "react" && statement.importKind !== "type"
|
|
1593
|
+
))
|
|
1374
1594
|
return {};
|
|
1375
1595
|
return {
|
|
1376
1596
|
CallExpression(node) {
|
|
1377
1597
|
if (node.optional || node.arguments.length !== 1 || !reactHook(context.sourceCode, node.callee, "useState"))
|
|
1378
1598
|
return;
|
|
1379
1599
|
const declaration = outerExpression(node).parent;
|
|
1380
|
-
if (declaration.type !==
|
|
1600
|
+
if (declaration.type !== AST_NODE_TYPES10.VariableDeclarator || declaration.parent.kind !== "const" || !hasReadonlyStateBinding(context.sourceCode, declaration))
|
|
1381
1601
|
return;
|
|
1382
1602
|
const component = renderFunction(node);
|
|
1383
1603
|
const argument = node.arguments[0];
|
|
1384
|
-
if (component === null || argument === void 0 || argument.type ===
|
|
1604
|
+
if (component === null || argument === void 0 || argument.type === AST_NODE_TYPES10.SpreadElement)
|
|
1385
1605
|
return;
|
|
1386
1606
|
const initial = initializerValue(argument);
|
|
1387
1607
|
if (initial === null || !parameterPath(
|
|
@@ -1391,12 +1611,12 @@ var no_readonly_prop_state_default = createRule({
|
|
|
1391
1611
|
))
|
|
1392
1612
|
return;
|
|
1393
1613
|
const lazy = unwrapExpression(argument);
|
|
1394
|
-
if (lazy.type !==
|
|
1614
|
+
if (lazy.type !== AST_NODE_TYPES10.ArrowFunctionExpression && lazy.type !== AST_NODE_TYPES10.FunctionExpression) {
|
|
1395
1615
|
if (!context.sourceCode.parserServices?.program || !context.sourceCode.parserServices.esTreeNodeToTSNodeMap)
|
|
1396
1616
|
return;
|
|
1397
1617
|
const services = getTypeServices(context);
|
|
1398
1618
|
const type = services.program.getTypeChecker().getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(initial));
|
|
1399
|
-
if (!
|
|
1619
|
+
if (!isPrimitiveType(type)) return;
|
|
1400
1620
|
}
|
|
1401
1621
|
context.report({ node, messageId: "readonlyPropState" });
|
|
1402
1622
|
}
|
|
@@ -1404,9 +1624,9 @@ var no_readonly_prop_state_default = createRule({
|
|
|
1404
1624
|
}
|
|
1405
1625
|
});
|
|
1406
1626
|
function hasReadonlyStateBinding(source, declaration) {
|
|
1407
|
-
if (declaration.id.type !==
|
|
1627
|
+
if (declaration.id.type !== AST_NODE_TYPES10.ArrayPattern) return false;
|
|
1408
1628
|
const [value, setter] = declaration.id.elements;
|
|
1409
|
-
if (value?.type !==
|
|
1629
|
+
if (value?.type !== AST_NODE_TYPES10.Identifier || declaration.id.elements.length > 2 || setter !== void 0 && setter !== null && setter.type !== AST_NODE_TYPES10.Identifier)
|
|
1410
1630
|
return false;
|
|
1411
1631
|
const variables = source.getDeclaredVariables(declaration);
|
|
1412
1632
|
const state = variables.find(
|
|
@@ -1416,7 +1636,7 @@ function hasReadonlyStateBinding(source, declaration) {
|
|
|
1416
1636
|
(reference) => reference.isRead() && !typeOnlyReference(reference)
|
|
1417
1637
|
))
|
|
1418
1638
|
return false;
|
|
1419
|
-
if (setter?.type ===
|
|
1639
|
+
if (setter?.type === AST_NODE_TYPES10.Identifier) {
|
|
1420
1640
|
const updater = variables.find(
|
|
1421
1641
|
(variable) => variable.identifiers.includes(setter)
|
|
1422
1642
|
);
|
|
@@ -1429,21 +1649,22 @@ function hasReadonlyStateBinding(source, declaration) {
|
|
|
1429
1649
|
}
|
|
1430
1650
|
function initializerValue(node) {
|
|
1431
1651
|
node = unwrapExpression(node);
|
|
1432
|
-
if (node.type !==
|
|
1652
|
+
if (node.type !== AST_NODE_TYPES10.ArrowFunctionExpression && node.type !== AST_NODE_TYPES10.FunctionExpression)
|
|
1433
1653
|
return node;
|
|
1434
1654
|
if (node.async || node.generator || node.params.length !== 0) return null;
|
|
1435
|
-
if (node.body.type !==
|
|
1655
|
+
if (node.body.type !== AST_NODE_TYPES10.BlockStatement) return node.body;
|
|
1436
1656
|
const [statement] = node.body.body;
|
|
1437
|
-
return node.body.body.length === 1 && statement?.type ===
|
|
1657
|
+
return node.body.body.length === 1 && statement?.type === AST_NODE_TYPES10.ReturnStatement ? statement.argument : null;
|
|
1438
1658
|
}
|
|
1439
|
-
function
|
|
1440
|
-
if (depth >= MAX_TYPE_DEPTH
|
|
1441
|
-
|
|
1442
|
-
|
|
1659
|
+
function isPrimitiveType(type, depth = 0) {
|
|
1660
|
+
if (depth >= MAX_TYPE_DEPTH) return false;
|
|
1661
|
+
if (type.isIntersection())
|
|
1662
|
+
return type.getCallSignatures().length === 0 && type.getConstructSignatures().length === 0 && type.types.some((member3) => isPrimitiveType(member3, depth + 1));
|
|
1663
|
+
return type.isUnion() ? type.types.every((member3) => isPrimitiveType(member3, depth + 1)) : (type.flags & PRIMITIVE_TYPES) !== 0;
|
|
1443
1664
|
}
|
|
1444
1665
|
|
|
1445
1666
|
// src/rules/no-runtime-typeof.ts
|
|
1446
|
-
import { AST_NODE_TYPES as
|
|
1667
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES11, ASTUtils as ASTUtils5 } from "@typescript-eslint/utils";
|
|
1447
1668
|
var NO_RUNTIME_TYPEOF_DOCUMENTATION = {
|
|
1448
1669
|
defaultLevel: "error",
|
|
1449
1670
|
summary: "Prefer Zod boundary schemas or discriminated unions over runtime typeof checks.",
|
|
@@ -1561,9 +1782,9 @@ var no_runtime_typeof_default = createRule({
|
|
|
1561
1782
|
UnaryExpression(node) {
|
|
1562
1783
|
if (node.operator !== "typeof") return;
|
|
1563
1784
|
const parent = node.parent;
|
|
1564
|
-
if (node.argument.type ===
|
|
1785
|
+
if (node.argument.type === AST_NODE_TYPES11.Identifier && parent.type === AST_NODE_TYPES11.BinaryExpression && ["===", "!==", "==", "!="].includes(parent.operator)) {
|
|
1565
1786
|
const other = parent.left === node ? parent.right : parent.left;
|
|
1566
|
-
if (other.type ===
|
|
1787
|
+
if (other.type === AST_NODE_TYPES11.Literal && other.value === "undefined" && !ASTUtils5.findVariable(context.sourceCode.getScope(node.argument), node.argument.name)?.defs.length) return;
|
|
1567
1788
|
}
|
|
1568
1789
|
context.report({ node, messageId: "runtimeTypeof" });
|
|
1569
1790
|
}
|
|
@@ -1574,7 +1795,7 @@ var no_runtime_typeof_default = createRule({
|
|
|
1574
1795
|
// src/rules/_is-frontend-source.ts
|
|
1575
1796
|
import { existsSync, readFileSync } from "fs";
|
|
1576
1797
|
import { dirname, join, resolve } from "path";
|
|
1577
|
-
import { AST_NODE_TYPES as
|
|
1798
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES12 } from "@typescript-eslint/utils";
|
|
1578
1799
|
var FRONTEND_PACKAGES = /* @__PURE__ */ new Set(["react", "react-dom", "next", "preact", "vue", "svelte", "@angular/core", "solid-js", "@sveltejs/kit", "astro"]);
|
|
1579
1800
|
var FRONTEND_IMPORT = /^(?:react(?:-dom)?|next|preact|vue|svelte|@angular\/core|solid-js|@sveltejs\/kit)(?:\/|$)/u;
|
|
1580
1801
|
function isFrontendSource(context) {
|
|
@@ -1602,15 +1823,15 @@ function declaresFrontend(value) {
|
|
|
1602
1823
|
}
|
|
1603
1824
|
function frontendModule(program) {
|
|
1604
1825
|
return program.body.some(
|
|
1605
|
-
(statement) => statement.type ===
|
|
1826
|
+
(statement) => statement.type === AST_NODE_TYPES12.ExpressionStatement && (statement.directive === "use client" || statement.directive === "use server") || statement.type === AST_NODE_TYPES12.ImportDeclaration && FRONTEND_IMPORT.test(statement.source.value)
|
|
1606
1827
|
);
|
|
1607
1828
|
}
|
|
1608
1829
|
|
|
1609
1830
|
// src/rules/no-test-comments.ts
|
|
1610
|
-
import { AST_NODE_TYPES as
|
|
1831
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES14 } from "@typescript-eslint/utils";
|
|
1611
1832
|
|
|
1612
1833
|
// src/rules/_comments.ts
|
|
1613
|
-
import { AST_NODE_TYPES as
|
|
1834
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES13 } from "@typescript-eslint/utils";
|
|
1614
1835
|
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/;
|
|
1615
1836
|
var VERSION_RE = /(?:>=|<=|==|<|>)\s*v?\d+\.\d+|\bv\d+\.\d+|\b(?:since|until|as of)\s+(?:v?\d+\.\d+|Python\s*\d)/i;
|
|
1616
1837
|
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/;
|
|
@@ -1696,10 +1917,10 @@ var NARRATION_MAX_WORDS = 6;
|
|
|
1696
1917
|
var NARRATION_MIN_CONTENT = 1;
|
|
1697
1918
|
var TOKEN_PLURAL_MIN = 4;
|
|
1698
1919
|
var RESTATABLE_STATEMENTS = /* @__PURE__ */ new Set([
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1920
|
+
AST_NODE_TYPES13.ExpressionStatement,
|
|
1921
|
+
AST_NODE_TYPES13.ReturnStatement,
|
|
1922
|
+
AST_NODE_TYPES13.ThrowStatement,
|
|
1923
|
+
AST_NODE_TYPES13.VariableDeclaration
|
|
1703
1924
|
]);
|
|
1704
1925
|
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;
|
|
1705
1926
|
var NARRATION_STOPWORDS = /* @__PURE__ */ new Set([
|
|
@@ -1758,12 +1979,12 @@ function restatableStatementBelow(comment, sourceCode) {
|
|
|
1758
1979
|
function restatableStatementNodeBelow(comment, sourceCode) {
|
|
1759
1980
|
const token = sourceCode.getTokenAfter(comment, { includeComments: false });
|
|
1760
1981
|
if (token === null || token.loc.start.line !== comment.loc.end.line + 1) return null;
|
|
1761
|
-
for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !==
|
|
1982
|
+
for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !== AST_NODE_TYPES13.Program; node = node.parent) {
|
|
1762
1983
|
if (!RESTATABLE_STATEMENTS.has(node.type)) continue;
|
|
1763
1984
|
if (node.loc.start.line !== token.loc.start.line || node.loc.end.line !== node.loc.start.line) {
|
|
1764
1985
|
return null;
|
|
1765
1986
|
}
|
|
1766
|
-
if (node.type ===
|
|
1987
|
+
if (node.type === AST_NODE_TYPES13.VariableDeclaration && isTrivialInitializer(node)) {
|
|
1767
1988
|
return null;
|
|
1768
1989
|
}
|
|
1769
1990
|
return node;
|
|
@@ -1773,8 +1994,8 @@ function restatableStatementNodeBelow(comment, sourceCode) {
|
|
|
1773
1994
|
function isTrivialInitializer(node) {
|
|
1774
1995
|
return node.declarations.every((declarator) => {
|
|
1775
1996
|
const init = declarator.init;
|
|
1776
|
-
if (init == null || init.type ===
|
|
1777
|
-
return init.type ===
|
|
1997
|
+
if (init == null || init.type === AST_NODE_TYPES13.Literal) return true;
|
|
1998
|
+
return init.type === AST_NODE_TYPES13.ArrayExpression && init.elements.length === 0 || init.type === AST_NODE_TYPES13.ObjectExpression && init.properties.length === 0;
|
|
1778
1999
|
});
|
|
1779
2000
|
}
|
|
1780
2001
|
function restatesStatementHead(body3, statement) {
|
|
@@ -1924,7 +2145,7 @@ function ownsTestComments(context) {
|
|
|
1924
2145
|
if (!isTestFile(context)) return false;
|
|
1925
2146
|
const filename = scopedFilename(context);
|
|
1926
2147
|
const unambiguous = /(?:^|\/)(?:tests?|__tests__|fixtures|__fixtures__|__mocks__)\//u.test(filename) || /\.(?:test|spec|e2e|integration)\.[cm]?[jt]sx?$/u.test(filename);
|
|
1927
|
-
const framework = context.sourceCode.ast.body.some((statement) => statement.type ===
|
|
2148
|
+
const framework = context.sourceCode.ast.body.some((statement) => statement.type === AST_NODE_TYPES14.ImportDeclaration && statement.importKind !== "type" && (statement.specifiers.length === 0 || statement.specifiers.some((specifier) => specifier.type !== AST_NODE_TYPES14.ImportSpecifier || specifier.importKind !== "type")) && ["vitest", "@jest/globals", "@playwright/test", "bun:test", "node:test"].includes(statement.source.value));
|
|
1928
2149
|
return unambiguous || framework;
|
|
1929
2150
|
}
|
|
1930
2151
|
var no_test_comments_default = createRule({
|
|
@@ -2107,7 +2328,7 @@ function emptyCommentRange(text, comment) {
|
|
|
2107
2328
|
}
|
|
2108
2329
|
|
|
2109
2330
|
// src/rules/prefer-dependency-interface.ts
|
|
2110
|
-
import { AST_NODE_TYPES as
|
|
2331
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES15, ASTUtils as ASTUtils6 } from "@typescript-eslint/utils";
|
|
2111
2332
|
var PREFER_DEPENDENCY_INTERFACE_DOCUMENTATION = {
|
|
2112
2333
|
defaultLevel: "warning",
|
|
2113
2334
|
summary: "Annotate retained collaborators with their existing interface when the consumer uses only that contract.",
|
|
@@ -2132,11 +2353,11 @@ var prefer_dependency_interface_default = createRule({
|
|
|
2132
2353
|
if (isGeneratedFile(context, context.sourceCode.text)) return {};
|
|
2133
2354
|
function contract(node) {
|
|
2134
2355
|
const concrete = definition(node);
|
|
2135
|
-
if (concrete?.type !==
|
|
2356
|
+
if (concrete?.type !== AST_NODE_TYPES15.ClassDeclaration || concrete.abstract || concrete.superClass !== null || concrete.decorators.length !== 0 || concrete.typeParameters !== void 0 || concrete.implements.length !== 1) return null;
|
|
2136
2357
|
const heritage = concrete.implements[0];
|
|
2137
|
-
if (heritage?.expression.type !==
|
|
2358
|
+
if (heritage?.expression.type !== AST_NODE_TYPES15.Identifier) return null;
|
|
2138
2359
|
const port = definition(heritage.expression);
|
|
2139
|
-
return port?.type ===
|
|
2360
|
+
return port?.type === AST_NODE_TYPES15.TSInterfaceDeclaration && port.extends.length === 0 && port.typeParameters === void 0 ? port : null;
|
|
2140
2361
|
}
|
|
2141
2362
|
function definition(node) {
|
|
2142
2363
|
const variable = ASTUtils6.findVariable(context.sourceCode.getScope(node), node.name);
|
|
@@ -2145,18 +2366,18 @@ var prefer_dependency_interface_default = createRule({
|
|
|
2145
2366
|
function usesOnlyInterface(owner, name, port) {
|
|
2146
2367
|
const members = /* @__PURE__ */ new Set();
|
|
2147
2368
|
for (const member3 of port.body.body) {
|
|
2148
|
-
if (member3.type !==
|
|
2369
|
+
if (member3.type !== AST_NODE_TYPES15.TSMethodSignature && member3.type !== AST_NODE_TYPES15.TSPropertySignature || member3.computed || member3.key.type !== AST_NODE_TYPES15.Identifier) return false;
|
|
2149
2370
|
members.add(member3.key.name);
|
|
2150
2371
|
}
|
|
2151
2372
|
let uses = 0;
|
|
2152
2373
|
let compatible = true;
|
|
2153
2374
|
function visit(node) {
|
|
2154
|
-
if (node.type ===
|
|
2375
|
+
if (node.type === AST_NODE_TYPES15.MemberExpression && node.object.type === AST_NODE_TYPES15.ThisExpression && ASTUtils6.getPropertyName(node) === name) {
|
|
2155
2376
|
uses += 1;
|
|
2156
2377
|
const parent = node.parent;
|
|
2157
|
-
if (parent.type !==
|
|
2378
|
+
if (parent.type !== AST_NODE_TYPES15.MemberExpression || parent.object !== node || !members.has(ASTUtils6.getPropertyName(parent) ?? "") || parent.parent.type === AST_NODE_TYPES15.AssignmentExpression && parent.parent.left === parent || parent.parent.type === AST_NODE_TYPES15.UpdateExpression) compatible = false;
|
|
2158
2379
|
}
|
|
2159
|
-
if (node !== owner && (node.type ===
|
|
2380
|
+
if (node !== owner && (node.type === AST_NODE_TYPES15.ClassDeclaration || node.type === AST_NODE_TYPES15.ClassExpression)) return;
|
|
2160
2381
|
forEachOwnAstChild(node, visit);
|
|
2161
2382
|
}
|
|
2162
2383
|
visit(owner);
|
|
@@ -2166,9 +2387,9 @@ var prefer_dependency_interface_default = createRule({
|
|
|
2166
2387
|
TSParameterProperty(node) {
|
|
2167
2388
|
const parameter = node.parameter;
|
|
2168
2389
|
const constructor = node.parent.parent;
|
|
2169
|
-
if (!node.readonly || node.accessibility !== "private" || node.decorators.length !== 0 || parameter.type !==
|
|
2390
|
+
if (!node.readonly || node.accessibility !== "private" || node.decorators.length !== 0 || parameter.type !== AST_NODE_TYPES15.Identifier || parameter.typeAnnotation?.typeAnnotation.type !== AST_NODE_TYPES15.TSTypeReference || parameter.typeAnnotation.typeAnnotation.typeName.type !== AST_NODE_TYPES15.Identifier || constructor.type !== AST_NODE_TYPES15.MethodDefinition || constructor.kind !== "constructor" || constructor.value.body?.body.length !== 0 || constructor.parent.type !== AST_NODE_TYPES15.ClassBody) return;
|
|
2170
2391
|
const owner = constructor.parent.parent;
|
|
2171
|
-
if (owner.type !==
|
|
2392
|
+
if (owner.type !== AST_NODE_TYPES15.ClassDeclaration && owner.type !== AST_NODE_TYPES15.ClassExpression) return;
|
|
2172
2393
|
if (owner.decorators.length !== 0 || owner.typeParameters !== void 0) return;
|
|
2173
2394
|
const port = contract(parameter.typeAnnotation.typeAnnotation.typeName);
|
|
2174
2395
|
if (port !== null && usesOnlyInterface(owner, parameter.name, port)) context.report({ node: parameter.typeAnnotation, messageId: "interface", data: { contract: port.id.name } });
|
|
@@ -2178,7 +2399,7 @@ var prefer_dependency_interface_default = createRule({
|
|
|
2178
2399
|
});
|
|
2179
2400
|
|
|
2180
2401
|
// src/rules/no-mutating-input-with-result.ts
|
|
2181
|
-
import { AST_NODE_TYPES as
|
|
2402
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES16, ASTUtils as ASTUtils7 } from "@typescript-eslint/utils";
|
|
2182
2403
|
var NO_MUTATING_INPUT_WITH_RESULT_DOCUMENTATION = {
|
|
2183
2404
|
defaultLevel: "warning",
|
|
2184
2405
|
summary: "Return replacement object values instead of writing input fields in result-returning functions.",
|
|
@@ -2196,8 +2417,8 @@ var NO_MUTATING_INPUT_WITH_RESULT_DOCUMENTATION = {
|
|
|
2196
2417
|
]
|
|
2197
2418
|
};
|
|
2198
2419
|
function command(annotation) {
|
|
2199
|
-
if (annotation.type ===
|
|
2200
|
-
if (annotation.type ===
|
|
2420
|
+
if (annotation.type === AST_NODE_TYPES16.TSVoidKeyword || annotation.type === AST_NODE_TYPES16.TSUndefinedKeyword || annotation.type === AST_NODE_TYPES16.TSNeverKeyword) return true;
|
|
2421
|
+
if (annotation.type === AST_NODE_TYPES16.TSTypeReference && annotation.typeName.type === AST_NODE_TYPES16.Identifier && annotation.typeName.name === "Promise" && annotation.typeArguments?.params.length === 1) {
|
|
2201
2422
|
const result = annotation.typeArguments.params[0];
|
|
2202
2423
|
return result !== void 0 && command(result);
|
|
2203
2424
|
}
|
|
@@ -2212,35 +2433,35 @@ function fields(annotation, sourceCode) {
|
|
|
2212
2433
|
return names;
|
|
2213
2434
|
}
|
|
2214
2435
|
function membersOf(annotation, sourceCode) {
|
|
2215
|
-
if (annotation.type ===
|
|
2216
|
-
if (annotation.type !==
|
|
2436
|
+
if (annotation.type === AST_NODE_TYPES16.TSTypeLiteral) return annotation.members;
|
|
2437
|
+
if (annotation.type !== AST_NODE_TYPES16.TSTypeReference || annotation.typeName.type !== AST_NODE_TYPES16.Identifier || annotation.typeArguments !== void 0) return [];
|
|
2217
2438
|
const variable = ASTUtils7.findVariable(sourceCode.getScope(annotation.typeName), annotation.typeName.name);
|
|
2218
2439
|
if (variable?.defs.length !== 1) return [];
|
|
2219
2440
|
const definition = variable.defs[0]?.node;
|
|
2220
2441
|
switch (definition?.type) {
|
|
2221
|
-
case
|
|
2442
|
+
case AST_NODE_TYPES16.TSInterfaceDeclaration:
|
|
2222
2443
|
return definition.extends.length === 0 && definition.typeParameters === void 0 ? definition.body.body : [];
|
|
2223
|
-
case
|
|
2224
|
-
return definition.typeParameters === void 0 && definition.typeAnnotation.type ===
|
|
2225
|
-
case
|
|
2444
|
+
case AST_NODE_TYPES16.TSTypeAliasDeclaration:
|
|
2445
|
+
return definition.typeParameters === void 0 && definition.typeAnnotation.type === AST_NODE_TYPES16.TSTypeLiteral ? definition.typeAnnotation.members : [];
|
|
2446
|
+
case AST_NODE_TYPES16.ClassDeclaration:
|
|
2226
2447
|
return definition.superClass === null && definition.typeParameters === void 0 && definition.decorators.length === 0 ? definition.body.body : [];
|
|
2227
2448
|
default:
|
|
2228
2449
|
return [];
|
|
2229
2450
|
}
|
|
2230
2451
|
}
|
|
2231
2452
|
function mutableField(member3) {
|
|
2232
|
-
if (member3.type !==
|
|
2233
|
-
if (member3.type ===
|
|
2234
|
-
if (member3.key.type ===
|
|
2235
|
-
return member3.key.type ===
|
|
2453
|
+
if (member3.type !== AST_NODE_TYPES16.TSPropertySignature && member3.type !== AST_NODE_TYPES16.PropertyDefinition || member3.readonly || member3.computed) return null;
|
|
2454
|
+
if (member3.type === AST_NODE_TYPES16.PropertyDefinition && (member3.static || member3.accessibility === "private" || member3.accessibility === "protected")) return null;
|
|
2455
|
+
if (member3.key.type === AST_NODE_TYPES16.Identifier) return member3.key.name;
|
|
2456
|
+
return member3.key.type === AST_NODE_TYPES16.Literal && (typeof member3.key.value === "string" || typeof member3.key.value === "number") ? String(member3.key.value) : null;
|
|
2236
2457
|
}
|
|
2237
2458
|
function walkBody(node, visit) {
|
|
2238
|
-
if (node.type ===
|
|
2459
|
+
if (node.type === AST_NODE_TYPES16.FunctionDeclaration || node.type === AST_NODE_TYPES16.FunctionExpression || node.type === AST_NODE_TYPES16.ArrowFunctionExpression || node.type === AST_NODE_TYPES16.ClassDeclaration || node.type === AST_NODE_TYPES16.ClassExpression) return;
|
|
2239
2460
|
visit(node);
|
|
2240
|
-
if (node.type ===
|
|
2461
|
+
if (node.type === AST_NODE_TYPES16.BlockStatement) {
|
|
2241
2462
|
for (const statement of node.body) {
|
|
2242
2463
|
walkBody(statement, visit);
|
|
2243
|
-
if (statement.type ===
|
|
2464
|
+
if (statement.type === AST_NODE_TYPES16.ReturnStatement || statement.type === AST_NODE_TYPES16.ThrowStatement) break;
|
|
2244
2465
|
}
|
|
2245
2466
|
return;
|
|
2246
2467
|
}
|
|
@@ -2252,15 +2473,15 @@ function walkBody(node, visit) {
|
|
|
2252
2473
|
forEachOwnAstChild(node, (child) => walkBody(child, visit), (key) => key !== "typeAnnotation" && key !== "returnType");
|
|
2253
2474
|
}
|
|
2254
2475
|
function selectedChildren(node) {
|
|
2255
|
-
if (node.type ===
|
|
2476
|
+
if (node.type === AST_NODE_TYPES16.IfStatement && node.test.type === AST_NODE_TYPES16.Literal) {
|
|
2256
2477
|
const branch = node.test.value ? node.consequent : node.alternate;
|
|
2257
2478
|
return branch === null ? [node.test] : [node.test, branch];
|
|
2258
2479
|
}
|
|
2259
|
-
if (node.type ===
|
|
2480
|
+
if (node.type === AST_NODE_TYPES16.LogicalExpression && node.left.type === AST_NODE_TYPES16.Literal) {
|
|
2260
2481
|
const skips = node.operator === "&&" && !node.left.value || node.operator === "||" && !!node.left.value || node.operator === "??" && node.left.value !== null;
|
|
2261
2482
|
return skips ? [node.left] : [node.left, node.right];
|
|
2262
2483
|
}
|
|
2263
|
-
if (node.type ===
|
|
2484
|
+
if (node.type === AST_NODE_TYPES16.ConditionalExpression && node.test.type === AST_NODE_TYPES16.Literal) return [node.test, node.test.value ? node.consequent : node.alternate];
|
|
2264
2485
|
return null;
|
|
2265
2486
|
}
|
|
2266
2487
|
var no_mutating_input_with_result_default = createRule({
|
|
@@ -2281,21 +2502,21 @@ var no_mutating_input_with_result_default = createRule({
|
|
|
2281
2502
|
if (annotation === void 0 || command(annotation) || node.body === void 0) return;
|
|
2282
2503
|
const inputs = /* @__PURE__ */ new Map();
|
|
2283
2504
|
for (const parameter of node.params) {
|
|
2284
|
-
if (parameter.type !==
|
|
2505
|
+
if (parameter.type !== AST_NODE_TYPES16.Identifier || parameter.typeAnnotation === void 0) continue;
|
|
2285
2506
|
const variable = ASTUtils7.findVariable(sourceCode.getScope(parameter), parameter.name);
|
|
2286
2507
|
if (variable === null || variable.references.some((reference) => reference.isWrite())) continue;
|
|
2287
2508
|
const names = fields(parameter.typeAnnotation.typeAnnotation, sourceCode);
|
|
2288
2509
|
if (names.size > 0) inputs.set(variable, names);
|
|
2289
2510
|
}
|
|
2290
2511
|
if (inputs.size === 0) return;
|
|
2291
|
-
let returned2 = node.body.type !==
|
|
2512
|
+
let returned2 = node.body.type !== AST_NODE_TYPES16.BlockStatement;
|
|
2292
2513
|
const writes = [];
|
|
2293
2514
|
walkBody(node.body, (current) => {
|
|
2294
|
-
if (current.type ===
|
|
2295
|
-
const candidate2 = current.type ===
|
|
2515
|
+
if (current.type === AST_NODE_TYPES16.ReturnStatement && current.argument !== null) returned2 = true;
|
|
2516
|
+
const candidate2 = current.type === AST_NODE_TYPES16.AssignmentExpression ? current.left : current.type === AST_NODE_TYPES16.UpdateExpression || current.type === AST_NODE_TYPES16.UnaryExpression && current.operator === "delete" ? current.argument : null;
|
|
2296
2517
|
if (candidate2 === null) return;
|
|
2297
2518
|
const target = unwrapExpression(candidate2);
|
|
2298
|
-
if (target.type !==
|
|
2519
|
+
if (target.type !== AST_NODE_TYPES16.MemberExpression || target.object.type !== AST_NODE_TYPES16.Identifier) return;
|
|
2299
2520
|
const variable = ASTUtils7.findVariable(sourceCode.getScope(target.object), target.object.name);
|
|
2300
2521
|
const property = ASTUtils7.getPropertyName(target);
|
|
2301
2522
|
if (variable !== null && property !== null && inputs.get(variable)?.has(property)) writes.push({ node: target, name: target.object.name });
|
|
@@ -2308,26 +2529,26 @@ var no_mutating_input_with_result_default = createRule({
|
|
|
2308
2529
|
});
|
|
2309
2530
|
|
|
2310
2531
|
// src/rules/no-negative-only-http-status-assertion.ts
|
|
2311
|
-
import { AST_NODE_TYPES as
|
|
2532
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES21, ASTUtils as ASTUtils12 } from "@typescript-eslint/utils";
|
|
2312
2533
|
|
|
2313
2534
|
// src/rules/_native-fetch-reference.ts
|
|
2314
|
-
import { AST_NODE_TYPES as
|
|
2535
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES19, ASTUtils as ASTUtils10 } from "@typescript-eslint/utils";
|
|
2315
2536
|
|
|
2316
2537
|
// src/rules/_native-runtime-unchanged.ts
|
|
2317
|
-
import { AST_NODE_TYPES as
|
|
2538
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES18, ASTUtils as ASTUtils9 } from "@typescript-eslint/utils";
|
|
2318
2539
|
|
|
2319
2540
|
// src/rules/_static-string.ts
|
|
2320
|
-
import { AST_NODE_TYPES as
|
|
2541
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES17, ASTUtils as ASTUtils8 } from "@typescript-eslint/utils";
|
|
2321
2542
|
function staticString(node) {
|
|
2322
2543
|
if (node === void 0) return null;
|
|
2323
2544
|
const value = unwrapExpression(node);
|
|
2324
|
-
if (value.type ===
|
|
2325
|
-
return value.type ===
|
|
2545
|
+
if (value.type === AST_NODE_TYPES17.Literal && typeof value.value === "string") return value.value;
|
|
2546
|
+
return value.type === AST_NODE_TYPES17.TemplateLiteral && value.expressions.length === 0 ? value.quasis[0]?.value.cooked ?? null : null;
|
|
2326
2547
|
}
|
|
2327
2548
|
var SCOPED_STRING_VALUES = /* @__PURE__ */ new WeakMap();
|
|
2328
2549
|
function scopedStaticString(node, sourceCode) {
|
|
2329
2550
|
let value = unwrapExpression(node);
|
|
2330
|
-
if (value.type !==
|
|
2551
|
+
if (value.type !== AST_NODE_TYPES17.Identifier) return staticString(value);
|
|
2331
2552
|
let values = SCOPED_STRING_VALUES.get(sourceCode);
|
|
2332
2553
|
if (values === void 0) {
|
|
2333
2554
|
values = /* @__PURE__ */ new WeakMap();
|
|
@@ -2336,7 +2557,7 @@ function scopedStaticString(node, sourceCode) {
|
|
|
2336
2557
|
const seen = /* @__PURE__ */ new Set();
|
|
2337
2558
|
const pending = [];
|
|
2338
2559
|
let result = null;
|
|
2339
|
-
while (value.type ===
|
|
2560
|
+
while (value.type === AST_NODE_TYPES17.Identifier) {
|
|
2340
2561
|
const binding3 = ASTUtils8.findVariable(sourceCode.getScope(value), value.name);
|
|
2341
2562
|
if (binding3 === null || seen.has(binding3)) break;
|
|
2342
2563
|
if (values.has(binding3)) {
|
|
@@ -2346,9 +2567,9 @@ function scopedStaticString(node, sourceCode) {
|
|
|
2346
2567
|
seen.add(binding3);
|
|
2347
2568
|
pending.push(binding3);
|
|
2348
2569
|
const definition = binding3.defs.length === 1 ? binding3.defs[0] : void 0;
|
|
2349
|
-
if (definition?.type !== "Variable" || definition.node.id.type !==
|
|
2570
|
+
if (definition?.type !== "Variable" || definition.node.id.type !== AST_NODE_TYPES17.Identifier || definition.node.init === null || binding3.references.some((reference) => reference.isWrite() && reference.init !== true)) break;
|
|
2350
2571
|
value = unwrapExpression(definition.node.init);
|
|
2351
|
-
if (value.type !==
|
|
2572
|
+
if (value.type !== AST_NODE_TYPES17.Identifier) result = staticString(value);
|
|
2352
2573
|
}
|
|
2353
2574
|
for (const binding3 of pending) values.set(binding3, result);
|
|
2354
2575
|
return result;
|
|
@@ -2356,7 +2577,7 @@ function scopedStaticString(node, sourceCode) {
|
|
|
2356
2577
|
function staticPropertyName(node, sourceCode) {
|
|
2357
2578
|
const direct = ASTUtils8.getPropertyName(node);
|
|
2358
2579
|
if (direct !== null || !node.computed) return direct;
|
|
2359
|
-
const key = node.type ===
|
|
2580
|
+
const key = node.type === AST_NODE_TYPES17.MemberExpression ? node.property : node.key;
|
|
2360
2581
|
return scopedStaticString(key, sourceCode);
|
|
2361
2582
|
}
|
|
2362
2583
|
|
|
@@ -2367,7 +2588,7 @@ function nativeRuntimeUnchanged(sourceCode, name) {
|
|
|
2367
2588
|
const index = runtimeIndex(sourceCode);
|
|
2368
2589
|
const cached = index.results.get(name);
|
|
2369
2590
|
if (cached !== void 0) return cached;
|
|
2370
|
-
const changed = index.nodes.some((node) => node.type ===
|
|
2591
|
+
const changed = index.nodes.some((node) => node.type === AST_NODE_TYPES18.MemberExpression && staticPropertyName(node, sourceCode) === "constructor" || name === "fetch" && node.type === AST_NODE_TYPES18.Property && node.parent.type === AST_NODE_TYPES18.ObjectPattern && staticPropertyName(node, sourceCode) === "constructor" || name === "RegExp" && node.type === AST_NODE_TYPES18.Literal && "regex" in node) || index.references.some((reference) => (name !== "fetch" || !typeOnlyReference(reference)) && unsafeReference(reference.identifier, sourceCode, name, index));
|
|
2371
2592
|
index.results.set(name, !changed);
|
|
2372
2593
|
return !changed;
|
|
2373
2594
|
}
|
|
@@ -2396,8 +2617,8 @@ function unsafeReference(node, sourceCode, name, index) {
|
|
|
2396
2617
|
if (!GLOBAL_OBJECTS.has(node.name)) return false;
|
|
2397
2618
|
const value = outerExpression(node);
|
|
2398
2619
|
const property = value.parent;
|
|
2399
|
-
if (name === "fetch" && property?.type ===
|
|
2400
|
-
if (property?.type !==
|
|
2620
|
+
if (name === "fetch" && property?.type === AST_NODE_TYPES18.UnaryExpression && property.operator === "typeof") return false;
|
|
2621
|
+
if (property?.type !== AST_NODE_TYPES18.MemberExpression || property.object !== value) {
|
|
2401
2622
|
return name !== "fetch" || !fetchProjection(value, sourceCode, index);
|
|
2402
2623
|
}
|
|
2403
2624
|
const key = staticPropertyName(property, sourceCode);
|
|
@@ -2412,15 +2633,15 @@ function ambient(node, sourceCode) {
|
|
|
2412
2633
|
function fetchUse(node, sourceCode) {
|
|
2413
2634
|
const value = outerExpression(node);
|
|
2414
2635
|
const parent = value.parent;
|
|
2415
|
-
if (parent?.type ===
|
|
2416
|
-
if (parent?.type !==
|
|
2636
|
+
if (parent?.type === AST_NODE_TYPES18.CallExpression && parent.callee === value || parent?.type === AST_NODE_TYPES18.UnaryExpression && parent.operator === "typeof") return true;
|
|
2637
|
+
if (parent?.type !== AST_NODE_TYPES18.VariableDeclarator || parent.init !== value || parent.id.type !== AST_NODE_TYPES18.Identifier) return false;
|
|
2417
2638
|
return stableConstBinding(parent.id, sourceCode) ?? false;
|
|
2418
2639
|
}
|
|
2419
2640
|
function stableConstBinding(node, sourceCode) {
|
|
2420
2641
|
const binding3 = ASTUtils9.findVariable(sourceCode.getScope(node), node.name);
|
|
2421
2642
|
if (binding3 === null || binding3.defs.length !== 1) return null;
|
|
2422
2643
|
const [definition] = binding3.defs;
|
|
2423
|
-
return definition?.type === "Variable" && definition.parent.kind === "const" && definition.node.init !== null && definition.parent.parent.type !==
|
|
2644
|
+
return definition?.type === "Variable" && definition.parent.kind === "const" && definition.node.init !== null && definition.parent.parent.type !== AST_NODE_TYPES18.ExportNamedDeclaration && !binding3.references.some((reference) => reference.isWrite() && reference.init !== true) ? binding3 : null;
|
|
2424
2645
|
}
|
|
2425
2646
|
function fetchRead(node, sourceCode, index) {
|
|
2426
2647
|
const use = fetchUse(node, sourceCode);
|
|
@@ -2463,18 +2684,18 @@ function fetchAliasCaptures(binding3, sourceCode) {
|
|
|
2463
2684
|
}
|
|
2464
2685
|
function fetchProjection(node, sourceCode, index) {
|
|
2465
2686
|
const declaration = node.parent;
|
|
2466
|
-
if (declaration?.type !==
|
|
2687
|
+
if (declaration?.type !== AST_NODE_TYPES18.VariableDeclarator || declaration.init !== node || declaration.id.type !== AST_NODE_TYPES18.ObjectPattern || declaration.id.properties.length !== 1) return false;
|
|
2467
2688
|
const [property] = declaration.id.properties;
|
|
2468
|
-
if (property?.type !==
|
|
2689
|
+
if (property?.type !== AST_NODE_TYPES18.Property || staticPropertyName(property, sourceCode) !== "fetch" || property.value.type !== AST_NODE_TYPES18.Identifier) return false;
|
|
2469
2690
|
const binding3 = stableConstBinding(property.value, sourceCode);
|
|
2470
2691
|
return binding3 !== null && fetchAliasRead(binding3, sourceCode, index);
|
|
2471
2692
|
}
|
|
2472
2693
|
function nativeRead(node, name) {
|
|
2473
2694
|
const value = outerExpression(node);
|
|
2474
2695
|
const parent = value.parent;
|
|
2475
|
-
if (parent?.type ===
|
|
2696
|
+
if (parent?.type === AST_NODE_TYPES18.UnaryExpression && parent.operator === "typeof") return true;
|
|
2476
2697
|
if (name !== "Error") return false;
|
|
2477
|
-
return parent?.type ===
|
|
2698
|
+
return parent?.type === AST_NODE_TYPES18.NewExpression && parent.callee === value || parent?.type === AST_NODE_TYPES18.BinaryExpression && parent.operator === "instanceof" && parent.right === value;
|
|
2478
2699
|
}
|
|
2479
2700
|
|
|
2480
2701
|
// src/rules/_native-fetch-reference.ts
|
|
@@ -2484,34 +2705,34 @@ function nativeFetchReference(node, sourceCode) {
|
|
|
2484
2705
|
}
|
|
2485
2706
|
function lexicalFetchReference(node, sourceCode, seen = /* @__PURE__ */ new Set()) {
|
|
2486
2707
|
const expression = unwrapExpression(node);
|
|
2487
|
-
if (expression.type ===
|
|
2708
|
+
if (expression.type === AST_NODE_TYPES19.MemberExpression) {
|
|
2488
2709
|
return staticPropertyName(expression, sourceCode) === "fetch" && globalReceiver(expression.object, sourceCode);
|
|
2489
2710
|
}
|
|
2490
|
-
if (expression.type !==
|
|
2711
|
+
if (expression.type !== AST_NODE_TYPES19.Identifier) return false;
|
|
2491
2712
|
const binding3 = ASTUtils10.findVariable(sourceCode.getScope(expression), expression.name);
|
|
2492
2713
|
if (binding3 === null || binding3.defs.length === 0) return expression.name === "fetch";
|
|
2493
2714
|
if (seen.has(binding3) || seen.size >= 8 || binding3.defs.length !== 1 || binding3.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
2494
2715
|
seen.add(binding3);
|
|
2495
2716
|
const [definition] = binding3.defs;
|
|
2496
2717
|
if (definition?.type !== "Variable" || definition.parent.kind !== "const" || definition.node.init === null) return false;
|
|
2497
|
-
if (definition.node.id.type ===
|
|
2718
|
+
if (definition.node.id.type === AST_NODE_TYPES19.Identifier) {
|
|
2498
2719
|
return lexicalFetchReference(definition.node.init, sourceCode, seen);
|
|
2499
2720
|
}
|
|
2500
|
-
return definition.node.id.type ===
|
|
2721
|
+
return definition.node.id.type === AST_NODE_TYPES19.ObjectPattern && globalReceiver(definition.node.init, sourceCode) && definition.node.id.properties.some((property) => property.type === AST_NODE_TYPES19.Property && staticPropertyName(property, sourceCode) === "fetch" && property.value.type === AST_NODE_TYPES19.Identifier && ASTUtils10.findVariable(sourceCode.getScope(property.value), property.value.name) === binding3);
|
|
2501
2722
|
}
|
|
2502
2723
|
function globalReceiver(node, sourceCode) {
|
|
2503
2724
|
const receiver = unwrapExpression(node);
|
|
2504
|
-
return receiver.type ===
|
|
2725
|
+
return receiver.type === AST_NODE_TYPES19.Identifier && GLOBAL_RECEIVERS2.has(receiver.name) && !ASTUtils10.findVariable(sourceCode.getScope(receiver), receiver.name)?.defs.length;
|
|
2505
2726
|
}
|
|
2506
2727
|
|
|
2507
2728
|
// src/rules/_test-mock-provenance.ts
|
|
2508
|
-
import { AST_NODE_TYPES as
|
|
2729
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES20, ASTUtils as ASTUtils11 } from "@typescript-eslint/utils";
|
|
2509
2730
|
function importedTestMockNamespace(source, identifier) {
|
|
2510
2731
|
const binding3 = ASTUtils11.findVariable(source.getScope(identifier), identifier.name);
|
|
2511
2732
|
const importedBinding = runtimeImportBinding(binding3);
|
|
2512
|
-
if (importedBinding === null || importedBinding.specifier.type !==
|
|
2733
|
+
if (importedBinding === null || importedBinding.specifier.type !== AST_NODE_TYPES20.ImportSpecifier) return null;
|
|
2513
2734
|
const specifier = importedBinding.specifier;
|
|
2514
|
-
const imported = specifier.imported.type ===
|
|
2735
|
+
const imported = specifier.imported.type === AST_NODE_TYPES20.Identifier ? specifier.imported.name : specifier.imported.value;
|
|
2515
2736
|
const module = importedBinding.module;
|
|
2516
2737
|
if (module === "vitest" && (imported === "vi" || imported === "vitest")) return "vitest";
|
|
2517
2738
|
if (module === "@jest/globals" && imported === "jest") return "jest";
|
|
@@ -2532,22 +2753,22 @@ function runtimeTestFrameworkName(source, identifier, kind) {
|
|
|
2532
2753
|
if (importedBinding === null) return null;
|
|
2533
2754
|
const { specifier, module } = importedBinding;
|
|
2534
2755
|
const isNodeAssertion = kind === "assertion" && (module === "node:assert" || module === "node:assert/strict");
|
|
2535
|
-
if (specifier.type ===
|
|
2756
|
+
if (specifier.type === AST_NODE_TYPES20.ImportSpecifier) {
|
|
2536
2757
|
if (isNodeAssertion) return "assert";
|
|
2537
2758
|
if (!TEST_FRAMEWORK_MODULES.has(module)) return null;
|
|
2538
|
-
const imported = specifier.imported.type ===
|
|
2759
|
+
const imported = specifier.imported.type === AST_NODE_TYPES20.Identifier ? specifier.imported.name : specifier.imported.value;
|
|
2539
2760
|
return imported;
|
|
2540
2761
|
}
|
|
2541
2762
|
if (isNodeAssertion) return "assert";
|
|
2542
|
-
return kind === "test" && module === "node:test" && specifier.type ===
|
|
2763
|
+
return kind === "test" && module === "node:test" && specifier.type === AST_NODE_TYPES20.ImportDefaultSpecifier ? "test" : null;
|
|
2543
2764
|
}
|
|
2544
2765
|
function runtimeImportBinding(binding3) {
|
|
2545
2766
|
if (binding3?.defs.length !== 1) return null;
|
|
2546
2767
|
const definition = binding3.defs[0];
|
|
2547
|
-
if (definition?.type !== "ImportBinding" || definition.parent.type !==
|
|
2768
|
+
if (definition?.type !== "ImportBinding" || definition.parent.type !== AST_NODE_TYPES20.ImportDeclaration || definition.parent.importKind === "type") return null;
|
|
2548
2769
|
const specifier = definition.node;
|
|
2549
|
-
if (specifier.type !==
|
|
2550
|
-
if (specifier.type ===
|
|
2770
|
+
if (specifier.type !== AST_NODE_TYPES20.ImportSpecifier && specifier.type !== AST_NODE_TYPES20.ImportDefaultSpecifier && specifier.type !== AST_NODE_TYPES20.ImportNamespaceSpecifier) return null;
|
|
2771
|
+
if (specifier.type === AST_NODE_TYPES20.ImportSpecifier && specifier.importKind === "type") return null;
|
|
2551
2772
|
return { module: definition.parent.source.value, specifier };
|
|
2552
2773
|
}
|
|
2553
2774
|
function vitestFixtureTestName(source, identifier) {
|
|
@@ -2555,24 +2776,24 @@ function vitestFixtureTestName(source, identifier) {
|
|
|
2555
2776
|
}
|
|
2556
2777
|
function fixtureTestName(node, source, seen) {
|
|
2557
2778
|
node = unwrapExpression(node);
|
|
2558
|
-
if (node.type ===
|
|
2779
|
+
if (node.type === AST_NODE_TYPES20.CallExpression) {
|
|
2559
2780
|
const callee = unwrapExpression(node.callee);
|
|
2560
|
-
return !node.optional && callee.type ===
|
|
2781
|
+
return !node.optional && callee.type === AST_NODE_TYPES20.MemberExpression && !callee.optional && ASTUtils11.getPropertyName(callee) === "extend" && node.arguments.length > 0 && !node.arguments.some((argument) => argument.type === AST_NODE_TYPES20.SpreadElement) ? fixtureTestName(callee.object, source, seen) : null;
|
|
2561
2782
|
}
|
|
2562
|
-
if (node.type !==
|
|
2783
|
+
if (node.type !== AST_NODE_TYPES20.Identifier) return null;
|
|
2563
2784
|
const binding3 = ASTUtils11.findVariable(source.getScope(node), node.name);
|
|
2564
2785
|
if (binding3 === null || seen.has(binding3) || !unchangedFixtureApi(binding3)) return null;
|
|
2565
2786
|
seen.add(binding3);
|
|
2566
2787
|
const imported = runtimeImportBinding(binding3);
|
|
2567
|
-
if (imported?.module === "vitest" && imported.specifier.type ===
|
|
2788
|
+
if (imported?.module === "vitest" && imported.specifier.type === AST_NODE_TYPES20.ImportSpecifier) {
|
|
2568
2789
|
const name = imported.specifier.imported;
|
|
2569
|
-
const value = name.type ===
|
|
2790
|
+
const value = name.type === AST_NODE_TYPES20.Identifier ? name.name : name.value;
|
|
2570
2791
|
return value === "test" || value === "it" ? value : null;
|
|
2571
2792
|
}
|
|
2572
2793
|
const definition = binding3.defs[0];
|
|
2573
|
-
if (binding3.defs.length !== 1 || definition?.node.type !==
|
|
2794
|
+
if (binding3.defs.length !== 1 || definition?.node.type !== AST_NODE_TYPES20.VariableDeclarator || definition.node.id.type !== AST_NODE_TYPES20.Identifier || definition.node.parent.kind !== "const" || definition.node.init === null || definition.node.init.range[1] > node.range[0]) return null;
|
|
2574
2795
|
const initializer = unwrapExpression(definition.node.init);
|
|
2575
|
-
return initializer.type ===
|
|
2796
|
+
return initializer.type === AST_NODE_TYPES20.CallExpression ? fixtureTestName(initializer, source, seen) : null;
|
|
2576
2797
|
}
|
|
2577
2798
|
var FIXTURE_API_STABILITY = /* @__PURE__ */ new WeakMap();
|
|
2578
2799
|
function unchangedFixtureApi(binding3) {
|
|
@@ -2582,9 +2803,9 @@ function unchangedFixtureApi(binding3) {
|
|
|
2582
2803
|
if (reference.isWrite()) return reference.init === true;
|
|
2583
2804
|
if (reference.isTypeReference && !reference.isValueReference) return true;
|
|
2584
2805
|
let use = outerExpression(reference.identifier);
|
|
2585
|
-
while (use.parent?.type ===
|
|
2806
|
+
while (use.parent?.type === AST_NODE_TYPES20.MemberExpression && use.parent.object === use) use = outerExpression(use.parent);
|
|
2586
2807
|
const parent = use.parent;
|
|
2587
|
-
return parent?.type ===
|
|
2808
|
+
return parent?.type === AST_NODE_TYPES20.CallExpression && parent.callee === use || parent?.type === AST_NODE_TYPES20.ExportSpecifier || parent?.type === AST_NODE_TYPES20.ExportDefaultDeclaration || parent?.type === AST_NODE_TYPES20.TSTypeQuery || parent?.type === AST_NODE_TYPES20.UnaryExpression && parent.operator === "typeof";
|
|
2588
2809
|
});
|
|
2589
2810
|
FIXTURE_API_STABILITY.set(binding3, unchanged);
|
|
2590
2811
|
return unchanged;
|
|
@@ -2614,20 +2835,20 @@ var NO_NEGATIVE_ONLY_HTTP_STATUS_ASSERTION_DOCUMENTATION = {
|
|
|
2614
2835
|
]
|
|
2615
2836
|
};
|
|
2616
2837
|
function statusAssertion(source, call) {
|
|
2617
|
-
if (call.arguments.length !== 1 || call.arguments[0]?.type !==
|
|
2838
|
+
if (call.arguments.length !== 1 || call.arguments[0]?.type !== AST_NODE_TYPES21.Literal || typeof call.arguments[0].value !== "number" || call.callee.type !== AST_NODE_TYPES21.MemberExpression) return null;
|
|
2618
2839
|
const matcher = ASTUtils12.getPropertyName(call.callee);
|
|
2619
2840
|
if (matcher === null) return null;
|
|
2620
2841
|
let object = unwrapExpression(call.callee.object);
|
|
2621
|
-
const negative = object.type ===
|
|
2622
|
-
if (negative && object.type ===
|
|
2623
|
-
if (object.type !==
|
|
2842
|
+
const negative = object.type === AST_NODE_TYPES21.MemberExpression && ASTUtils12.getPropertyName(object) === "not";
|
|
2843
|
+
if (negative && object.type === AST_NODE_TYPES21.MemberExpression) object = unwrapExpression(object.object);
|
|
2844
|
+
if (object.type !== AST_NODE_TYPES21.CallExpression || object.arguments.length !== 1 || object.callee.type !== AST_NODE_TYPES21.Identifier || runtimeTestFrameworkName(source, object.callee, "assertion") !== "expect") return null;
|
|
2624
2845
|
const argument = object.arguments[0];
|
|
2625
|
-
const response = argument === void 0 || argument.type ===
|
|
2846
|
+
const response = argument === void 0 || argument.type === AST_NODE_TYPES21.SpreadElement ? null : fetchResponse(source, argument);
|
|
2626
2847
|
return response === null ? null : { response, expected: call.arguments[0].value, matcher, negative };
|
|
2627
2848
|
}
|
|
2628
2849
|
function fetchResponse(source, value) {
|
|
2629
2850
|
const node = unwrapExpression(value);
|
|
2630
|
-
if (node.type !==
|
|
2851
|
+
if (node.type !== AST_NODE_TYPES21.MemberExpression || ASTUtils12.getPropertyName(node) !== "status" || node.object.type !== AST_NODE_TYPES21.Identifier) return null;
|
|
2631
2852
|
return responseBinding(source, node.object);
|
|
2632
2853
|
}
|
|
2633
2854
|
function responseBinding(source, node, seen = /* @__PURE__ */ new Set()) {
|
|
@@ -2636,50 +2857,50 @@ function responseBinding(source, node, seen = /* @__PURE__ */ new Set()) {
|
|
|
2636
2857
|
if (variable?.defs.length !== 1 || seen.has(variable) || variable.references.some((reference) => reference.isWrite() && !reference.init)) return null;
|
|
2637
2858
|
seen.add(variable);
|
|
2638
2859
|
const parameter = variable.defs[0];
|
|
2639
|
-
if (parameter?.type === "Parameter" && parameter.name.type ===
|
|
2860
|
+
if (parameter?.type === "Parameter" && parameter.name.type === AST_NODE_TYPES21.Identifier) {
|
|
2640
2861
|
const annotation = parameter.name.typeAnnotation?.typeAnnotation;
|
|
2641
|
-
return annotation?.type ===
|
|
2862
|
+
return annotation?.type === AST_NODE_TYPES21.TSTypeReference && annotation.typeName.type === AST_NODE_TYPES21.Identifier && annotation.typeName.name === "Response" && (ASTUtils12.findVariable(source.getScope(annotation.typeName), "Response")?.defs.length ?? 0) === 0 ? variable : null;
|
|
2642
2863
|
}
|
|
2643
|
-
if (definition?.type !==
|
|
2864
|
+
if (definition?.type !== AST_NODE_TYPES21.VariableDeclarator || definition.parent.kind !== "const" || definition.init === null) return null;
|
|
2644
2865
|
let initial = unwrapExpression(definition.init);
|
|
2645
|
-
if (initial.type ===
|
|
2646
|
-
if (initial.type ===
|
|
2866
|
+
if (initial.type === AST_NODE_TYPES21.AwaitExpression) initial = unwrapExpression(initial.argument);
|
|
2867
|
+
if (initial.type === AST_NODE_TYPES21.Identifier) return responseBinding(source, initial, seen);
|
|
2647
2868
|
return nativeResponse(initial, source) ? variable : null;
|
|
2648
2869
|
}
|
|
2649
2870
|
function nativeResponse(initial, source) {
|
|
2650
|
-
if (initial.type ===
|
|
2651
|
-
if (initial.type ===
|
|
2652
|
-
if (initial.type !==
|
|
2871
|
+
if (initial.type === AST_NODE_TYPES21.NewExpression && initial.callee.type === AST_NODE_TYPES21.Identifier && initial.callee.name === "Response" && (ASTUtils12.findVariable(source.getScope(initial.callee), "Response")?.defs.length ?? 0) === 0) return true;
|
|
2872
|
+
if (initial.type === AST_NODE_TYPES21.CallExpression && nativeFetchReference(initial.callee, source)) return true;
|
|
2873
|
+
if (initial.type !== AST_NODE_TYPES21.CallExpression || initial.callee.type !== AST_NODE_TYPES21.Identifier) return false;
|
|
2653
2874
|
const callee = initial.callee;
|
|
2654
2875
|
const binding3 = ASTUtils12.findVariable(source.getScope(callee), callee.name);
|
|
2655
2876
|
if ((binding3?.defs.length ?? 0) === 0) return callee.name === "fetch";
|
|
2656
2877
|
const imported = binding3?.defs[0];
|
|
2657
|
-
if (binding3?.defs.length !== 1 || imported?.type !== "ImportBinding" || imported.parent.type !==
|
|
2878
|
+
if (binding3?.defs.length !== 1 || imported?.type !== "ImportBinding" || imported.parent.type !== AST_NODE_TYPES21.ImportDeclaration || imported.parent.importKind === "type" || !FETCH_MODULES.has(imported.parent.source.value)) return false;
|
|
2658
2879
|
const specifier = imported.node;
|
|
2659
|
-
if (specifier.type ===
|
|
2660
|
-
if (specifier.type !==
|
|
2661
|
-
const importedName7 = specifier.imported.type ===
|
|
2880
|
+
if (specifier.type === AST_NODE_TYPES21.ImportDefaultSpecifier) return imported.parent.source.value === "node-fetch";
|
|
2881
|
+
if (specifier.type !== AST_NODE_TYPES21.ImportSpecifier || specifier.importKind === "type") return false;
|
|
2882
|
+
const importedName7 = specifier.imported.type === AST_NODE_TYPES21.Identifier ? specifier.imported.name : specifier.imported.value;
|
|
2662
2883
|
return importedName7 === "fetch";
|
|
2663
2884
|
}
|
|
2664
2885
|
function enclosingTest(source, node) {
|
|
2665
2886
|
for (let current = node.parent; current != null; current = current.parent) {
|
|
2666
|
-
if (current.type ===
|
|
2667
|
-
if (current.type !==
|
|
2887
|
+
if (current.type === AST_NODE_TYPES21.FunctionDeclaration) return null;
|
|
2888
|
+
if (current.type !== AST_NODE_TYPES21.ArrowFunctionExpression && current.type !== AST_NODE_TYPES21.FunctionExpression) continue;
|
|
2668
2889
|
const registration2 = directArgumentCall(current);
|
|
2669
2890
|
const callee = registration2?.callee;
|
|
2670
|
-
if (callee?.type !==
|
|
2891
|
+
if (callee?.type !== AST_NODE_TYPES21.Identifier) return null;
|
|
2671
2892
|
const name = runtimeTestFrameworkName(source, callee, "test") ?? vitestFixtureTestName(source, callee);
|
|
2672
2893
|
return name === "test" || name === "it" ? current : null;
|
|
2673
2894
|
}
|
|
2674
2895
|
return null;
|
|
2675
2896
|
}
|
|
2676
2897
|
function hasExactStatus(source, test, response) {
|
|
2677
|
-
if (test.body.type !==
|
|
2898
|
+
if (test.body.type !== AST_NODE_TYPES21.BlockStatement) return false;
|
|
2678
2899
|
return test.body.body.some((statement) => {
|
|
2679
|
-
if (statement.type !==
|
|
2900
|
+
if (statement.type !== AST_NODE_TYPES21.ExpressionStatement) return false;
|
|
2680
2901
|
let expression = unwrapExpression(statement.expression);
|
|
2681
|
-
if (expression.type ===
|
|
2682
|
-
if (expression.type !==
|
|
2902
|
+
if (expression.type === AST_NODE_TYPES21.AwaitExpression) expression = unwrapExpression(expression.argument);
|
|
2903
|
+
if (expression.type !== AST_NODE_TYPES21.CallExpression) return false;
|
|
2683
2904
|
const assertion = statusAssertion(source, expression);
|
|
2684
2905
|
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;
|
|
2685
2906
|
});
|
|
@@ -2710,7 +2931,7 @@ var no_negative_only_http_status_assertion_default = createRule({
|
|
|
2710
2931
|
});
|
|
2711
2932
|
|
|
2712
2933
|
// src/rules/prefer-test-fixture-reuse.ts
|
|
2713
|
-
import { AST_NODE_TYPES as
|
|
2934
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES22, ASTUtils as ASTUtils13 } from "@typescript-eslint/utils";
|
|
2714
2935
|
var MAX_DEPTH = 8;
|
|
2715
2936
|
var FRAMEWORKS = /* @__PURE__ */ new Set(["vitest", "@playwright/test"]);
|
|
2716
2937
|
var TEST_MODIFIERS = /* @__PURE__ */ new Set(["only", "skip", "concurrent", "sequential"]);
|
|
@@ -2738,18 +2959,18 @@ function stableBinding(source, identifier) {
|
|
|
2738
2959
|
}
|
|
2739
2960
|
function constructorBinding(source, node, depth = 0) {
|
|
2740
2961
|
node = unwrapExpression(node);
|
|
2741
|
-
if (node.type !==
|
|
2962
|
+
if (node.type !== AST_NODE_TYPES22.Identifier || depth >= MAX_DEPTH) return null;
|
|
2742
2963
|
const variable = stableBinding(source, node);
|
|
2743
2964
|
const definition = variable?.defs[0];
|
|
2744
2965
|
if (variable === null || definition === void 0) return null;
|
|
2745
2966
|
if (definition.type === "ClassName") return variable;
|
|
2746
|
-
if (definition.type === "ImportBinding" && definition.parent.type ===
|
|
2747
|
-
if (definition.node.type ===
|
|
2967
|
+
if (definition.type === "ImportBinding" && definition.parent.type === AST_NODE_TYPES22.ImportDeclaration && definition.parent.importKind !== "type" && (definition.node.type !== AST_NODE_TYPES22.ImportSpecifier || definition.node.importKind !== "type")) return variable;
|
|
2968
|
+
if (definition.node.type === AST_NODE_TYPES22.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);
|
|
2748
2969
|
return null;
|
|
2749
2970
|
}
|
|
2750
2971
|
function fixtureApi(source, expression, depth = 0) {
|
|
2751
2972
|
const node = unwrapExpression(expression);
|
|
2752
|
-
if (node.type !==
|
|
2973
|
+
if (node.type !== AST_NODE_TYPES22.Identifier || depth >= MAX_DEPTH) return null;
|
|
2753
2974
|
const variable = stableBinding(source, node);
|
|
2754
2975
|
const definition = variable?.defs[0];
|
|
2755
2976
|
if (variable === null || definition === void 0) return null;
|
|
@@ -2761,35 +2982,35 @@ function fixtureApi(source, expression, depth = 0) {
|
|
|
2761
2982
|
}
|
|
2762
2983
|
function importedFixtureApi(variable) {
|
|
2763
2984
|
const definition = variable.defs[0];
|
|
2764
|
-
if (definition?.type === "ImportBinding" && definition.parent.type ===
|
|
2985
|
+
if (definition?.type === "ImportBinding" && definition.parent.type === AST_NODE_TYPES22.ImportDeclaration && FRAMEWORKS.has(definition.parent.source.value) && definition.parent.importKind !== "type" && definition.node.type === AST_NODE_TYPES22.ImportSpecifier && definition.node.importKind !== "type") {
|
|
2765
2986
|
const imported = definition.node.imported;
|
|
2766
|
-
const name = imported.type ===
|
|
2987
|
+
const name = imported.type === AST_NODE_TYPES22.Identifier ? imported.name : imported.value;
|
|
2767
2988
|
return name === "test" || name === "it";
|
|
2768
2989
|
}
|
|
2769
2990
|
return false;
|
|
2770
2991
|
}
|
|
2771
2992
|
function fixtureExtension(declaration, before) {
|
|
2772
|
-
if (declaration.type !==
|
|
2993
|
+
if (declaration.type !== AST_NODE_TYPES22.VariableDeclarator || declaration.parent.kind !== "const" || declaration.init === null || declaration.range[1] >= before) return null;
|
|
2773
2994
|
const initial = unwrapExpression(declaration.init);
|
|
2774
|
-
if (initial.type !==
|
|
2995
|
+
if (initial.type !== AST_NODE_TYPES22.CallExpression || initial.optional || initial.arguments.length !== 1 || initial.callee.type !== AST_NODE_TYPES22.MemberExpression || initial.callee.optional || ASTUtils13.getPropertyName(initial.callee) !== "extend") return null;
|
|
2775
2996
|
const declarations = initial.arguments[0];
|
|
2776
|
-
if (declarations?.type !==
|
|
2997
|
+
if (declarations?.type !== AST_NODE_TYPES22.ObjectExpression || declarations.properties.some((property) => property.type !== AST_NODE_TYPES22.Property || property.computed || property.kind !== "init")) return null;
|
|
2777
2998
|
return { receiver: initial.callee.object, declarations };
|
|
2778
2999
|
}
|
|
2779
3000
|
function fixtureApiStable(variable) {
|
|
2780
3001
|
return !variable.references.some((reference) => {
|
|
2781
3002
|
if (reference.isWrite() || reference.isTypeReference && !reference.isValueReference) return false;
|
|
2782
3003
|
let use = reference.identifier;
|
|
2783
|
-
while (use.parent?.type ===
|
|
2784
|
-
return use.parent?.type !==
|
|
3004
|
+
while (use.parent?.type === AST_NODE_TYPES22.MemberExpression && use.parent.object === use) use = use.parent;
|
|
3005
|
+
return use.parent?.type !== AST_NODE_TYPES22.CallExpression || use.parent.callee !== use;
|
|
2785
3006
|
});
|
|
2786
3007
|
}
|
|
2787
3008
|
function fixtureConstructors(source, declarations, inherited) {
|
|
2788
3009
|
const result = new Map(inherited);
|
|
2789
3010
|
for (const property of declarations.properties) {
|
|
2790
|
-
if (property.type !==
|
|
3011
|
+
if (property.type !== AST_NODE_TYPES22.Property || property.computed || property.value.type === AST_NODE_TYPES22.AssignmentPattern) continue;
|
|
2791
3012
|
const name = ASTUtils13.getPropertyName(property);
|
|
2792
|
-
if (name === null || property.value.type ===
|
|
3013
|
+
if (name === null || property.value.type === AST_NODE_TYPES22.TSEmptyBodyFunctionExpression) continue;
|
|
2793
3014
|
const constructor = fixtureConstructor(source, property.value);
|
|
2794
3015
|
if (constructor === null) result.delete(name);
|
|
2795
3016
|
else result.set(name, constructor);
|
|
@@ -2798,24 +3019,24 @@ function fixtureConstructors(source, declarations, inherited) {
|
|
|
2798
3019
|
}
|
|
2799
3020
|
function fixtureConstructor(source, value) {
|
|
2800
3021
|
value = unwrapExpression(value);
|
|
2801
|
-
if (value.type !==
|
|
3022
|
+
if (value.type !== AST_NODE_TYPES22.ArrowFunctionExpression && value.type !== AST_NODE_TYPES22.FunctionExpression) return newConstructor(source, value);
|
|
2802
3023
|
const use = value.params[1];
|
|
2803
|
-
if (use?.type !==
|
|
3024
|
+
if (use?.type !== AST_NODE_TYPES22.Identifier) return null;
|
|
2804
3025
|
const binding3 = stableBinding(source, use);
|
|
2805
|
-
const calls = scopeNodes(value.body, source).filter((node) => node.type ===
|
|
3026
|
+
const calls = scopeNodes(value.body, source).filter((node) => node.type === AST_NODE_TYPES22.CallExpression && !node.optional && node.arguments.length === 1 && node.callee.type === AST_NODE_TYPES22.Identifier && stableBinding(source, node.callee) === binding3);
|
|
2806
3027
|
if (calls.length !== 1 || binding3 === null) return null;
|
|
2807
3028
|
const argument = calls[0]?.arguments[0];
|
|
2808
|
-
return argument === void 0 || argument.type ===
|
|
3029
|
+
return argument === void 0 || argument.type === AST_NODE_TYPES22.SpreadElement ? null : newConstructor(source, argument);
|
|
2809
3030
|
}
|
|
2810
3031
|
function newConstructor(source, expression) {
|
|
2811
3032
|
const value = unwrapExpression(expression);
|
|
2812
|
-
if (value.type ===
|
|
2813
|
-
if (value.type !==
|
|
3033
|
+
if (value.type === AST_NODE_TYPES22.NewExpression) return constructorBinding(source, value.callee);
|
|
3034
|
+
if (value.type !== AST_NODE_TYPES22.Identifier) return null;
|
|
2814
3035
|
const variable = stableBinding(source, value);
|
|
2815
3036
|
const declaration = variable?.defs[0]?.node;
|
|
2816
|
-
if (declaration?.type !==
|
|
3037
|
+
if (declaration?.type !== AST_NODE_TYPES22.VariableDeclarator || declaration.parent.kind !== "const" || declaration.init === null || declaration.range[1] >= value.range[0]) return null;
|
|
2817
3038
|
const initial = unwrapExpression(declaration.init);
|
|
2818
|
-
return initial.type ===
|
|
3039
|
+
return initial.type === AST_NODE_TYPES22.NewExpression ? constructorBinding(source, initial.callee) : null;
|
|
2819
3040
|
}
|
|
2820
3041
|
function scopeNodes(root, source) {
|
|
2821
3042
|
const result = [];
|
|
@@ -2824,7 +3045,7 @@ function scopeNodes(root, source) {
|
|
|
2824
3045
|
const node = pending.pop();
|
|
2825
3046
|
if (node === void 0) continue;
|
|
2826
3047
|
result.push(node);
|
|
2827
|
-
if (node !== root && (node.type ===
|
|
3048
|
+
if (node !== root && (node.type === AST_NODE_TYPES22.ArrowFunctionExpression || node.type === AST_NODE_TYPES22.FunctionExpression || node.type === AST_NODE_TYPES22.FunctionDeclaration || node.type === AST_NODE_TYPES22.ClassDeclaration || node.type === AST_NODE_TYPES22.ClassExpression)) continue;
|
|
2828
3049
|
for (const key of source.visitorKeys[node.type] ?? []) {
|
|
2829
3050
|
const value = Reflect.get(node, key);
|
|
2830
3051
|
if (Array.isArray(value)) pending.push(...value.filter(isNode2));
|
|
@@ -2838,13 +3059,13 @@ function isNode2(value) {
|
|
|
2838
3059
|
}
|
|
2839
3060
|
function testApiCallee(expression) {
|
|
2840
3061
|
let node = unwrapExpression(expression);
|
|
2841
|
-
while (node.type ===
|
|
3062
|
+
while (node.type === AST_NODE_TYPES22.MemberExpression && !node.optional && TEST_MODIFIERS.has(ASTUtils13.getPropertyName(node) ?? "")) node = unwrapExpression(node.object);
|
|
2842
3063
|
return node;
|
|
2843
3064
|
}
|
|
2844
3065
|
function requestingFunction(node) {
|
|
2845
3066
|
for (let current = node.parent; current != null; current = current.parent) {
|
|
2846
|
-
if (current.type ===
|
|
2847
|
-
if (current.type ===
|
|
3067
|
+
if (current.type === AST_NODE_TYPES22.ArrowFunctionExpression || current.type === AST_NODE_TYPES22.FunctionExpression) return current;
|
|
3068
|
+
if (current.type === AST_NODE_TYPES22.FunctionDeclaration) return null;
|
|
2848
3069
|
}
|
|
2849
3070
|
return null;
|
|
2850
3071
|
}
|
|
@@ -2866,12 +3087,12 @@ var prefer_test_fixture_reuse_default = createRule({
|
|
|
2866
3087
|
const call = functionNode === null ? null : directArgumentCall(functionNode);
|
|
2867
3088
|
if (functionNode === null || call === null) return;
|
|
2868
3089
|
const parameter = functionNode.params[0];
|
|
2869
|
-
if (parameter?.type !==
|
|
3090
|
+
if (parameter?.type !== AST_NODE_TYPES22.ObjectPattern) return;
|
|
2870
3091
|
const entries = fixtureApi(context.sourceCode, testApiCallee(call.callee));
|
|
2871
3092
|
const constructor = constructorBinding(context.sourceCode, node.callee);
|
|
2872
3093
|
if (entries === null || constructor === null) return;
|
|
2873
3094
|
for (const property of parameter.properties) {
|
|
2874
|
-
if (property.type !==
|
|
3095
|
+
if (property.type !== AST_NODE_TYPES22.Property || property.computed) continue;
|
|
2875
3096
|
const name = ASTUtils13.getPropertyName(property);
|
|
2876
3097
|
if (name !== null && entries.get(name) === constructor) {
|
|
2877
3098
|
context.report({ node, messageId: "reuseFixture", data: { fixture: name } });
|
|
@@ -2884,7 +3105,7 @@ var prefer_test_fixture_reuse_default = createRule({
|
|
|
2884
3105
|
});
|
|
2885
3106
|
|
|
2886
3107
|
// src/rules/no-return-disposed-resource.ts
|
|
2887
|
-
import { AST_NODE_TYPES as
|
|
3108
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES23, ASTUtils as ASTUtils14 } from "@typescript-eslint/utils";
|
|
2888
3109
|
var NO_RETURN_DISPOSED_RESOURCE_DOCUMENTATION = {
|
|
2889
3110
|
defaultLevel: "warning",
|
|
2890
3111
|
summary: "Do not return a resource whose using declaration disposes it before the caller receives it.",
|
|
@@ -2904,16 +3125,16 @@ var NO_RETURN_DISPOSED_RESOURCE_DOCUMENTATION = {
|
|
|
2904
3125
|
};
|
|
2905
3126
|
function owningFunction(node) {
|
|
2906
3127
|
for (let current = node.parent; current != null; current = current.parent) {
|
|
2907
|
-
if (current.type ===
|
|
3128
|
+
if (current.type === AST_NODE_TYPES23.FunctionDeclaration || current.type === AST_NODE_TYPES23.FunctionExpression || current.type === AST_NODE_TYPES23.ArrowFunctionExpression) return current;
|
|
2908
3129
|
}
|
|
2909
3130
|
return null;
|
|
2910
3131
|
}
|
|
2911
3132
|
function resourceOwner(source, value, seen = /* @__PURE__ */ new Set()) {
|
|
2912
3133
|
const node = unwrapExpression(value);
|
|
2913
|
-
if (node.type !==
|
|
3134
|
+
if (node.type !== AST_NODE_TYPES23.Identifier) return null;
|
|
2914
3135
|
const variable = ASTUtils14.findVariable(source.getScope(node), node.name);
|
|
2915
3136
|
const definition = variable?.defs[0];
|
|
2916
|
-
if (variable === null || variable?.defs.length !== 1 || definition === void 0 || seen.has(variable) || variable.references.some((reference) => reference.isWrite() && !reference.init) || definition.node.type !==
|
|
3137
|
+
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_TYPES23.VariableDeclarator) return null;
|
|
2917
3138
|
const declaration = definition.node;
|
|
2918
3139
|
if (declaration.parent.kind === "using" || declaration.parent.kind === "await using") return declaration;
|
|
2919
3140
|
if (declaration.parent.kind !== "const" || declaration.init === null || declaration.range[1] >= node.range[0]) return null;
|
|
@@ -2942,7 +3163,7 @@ var no_return_disposed_resource_default = createRule({
|
|
|
2942
3163
|
});
|
|
2943
3164
|
|
|
2944
3165
|
// src/rules/require-jwt-lifetime.ts
|
|
2945
|
-
import { AST_NODE_TYPES as
|
|
3166
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES24, ASTUtils as ASTUtils15 } from "@typescript-eslint/utils";
|
|
2946
3167
|
var REQUIRE_JWT_LIFETIME_DOCUMENTATION = {
|
|
2947
3168
|
defaultLevel: "warning",
|
|
2948
3169
|
summary: "Require an expiration claim or a maximum token age when returning a verified JWT.",
|
|
@@ -2970,36 +3191,36 @@ var require_jwt_lifetime_default = createRule({
|
|
|
2970
3191
|
function inspect(input) {
|
|
2971
3192
|
if (input === null) return;
|
|
2972
3193
|
let node = unwrapExpression(input);
|
|
2973
|
-
if (node.type ===
|
|
2974
|
-
if (node.type !==
|
|
3194
|
+
if (node.type === AST_NODE_TYPES24.AwaitExpression) node = unwrapExpression(node.argument);
|
|
3195
|
+
if (node.type !== AST_NODE_TYPES24.CallExpression || !isVerifier(node.callee)) return;
|
|
2975
3196
|
if (!missingLifetime(node.arguments[2])) return;
|
|
2976
3197
|
context.report({ node, messageId: "lifetime" });
|
|
2977
3198
|
}
|
|
2978
3199
|
function isVerifier(node) {
|
|
2979
3200
|
node = unwrapExpression(node);
|
|
2980
|
-
if (node.type ===
|
|
3201
|
+
if (node.type === AST_NODE_TYPES24.Identifier) {
|
|
2981
3202
|
const variable = ASTUtils15.findVariable(sourceCode.getScope(node), node.name);
|
|
2982
3203
|
const declaration = variable?.defs[0]?.node;
|
|
2983
|
-
return variable?.defs.length === 1 && declaration?.type ===
|
|
3204
|
+
return variable?.defs.length === 1 && declaration?.type === AST_NODE_TYPES24.ImportSpecifier && declaration.parent.type === AST_NODE_TYPES24.ImportDeclaration && declaration.importKind !== "type" && declaration.parent.importKind !== "type" && declaration.parent.source.value === "jose" && declaration.imported.type === AST_NODE_TYPES24.Identifier && declaration.imported.name === "jwtVerify";
|
|
2984
3205
|
}
|
|
2985
|
-
if (node.type !==
|
|
3206
|
+
if (node.type !== AST_NODE_TYPES24.MemberExpression || ASTUtils15.getPropertyName(node) !== "jwtVerify" || node.object.type !== AST_NODE_TYPES24.Identifier) return false;
|
|
2986
3207
|
const definition = ASTUtils15.findVariable(sourceCode.getScope(node.object), node.object.name)?.defs[0]?.node;
|
|
2987
|
-
return definition?.type ===
|
|
3208
|
+
return definition?.type === AST_NODE_TYPES24.ImportNamespaceSpecifier && definition.parent.importKind !== "type" && definition.parent.source.value === "jose";
|
|
2988
3209
|
}
|
|
2989
3210
|
function missingLifetime(options) {
|
|
2990
3211
|
if (options === void 0) return true;
|
|
2991
|
-
if (options.type !==
|
|
2992
|
-
return !options.properties.some((property) => property.type ===
|
|
3212
|
+
if (options.type !== AST_NODE_TYPES24.ObjectExpression || options.properties.some((property) => property.type !== AST_NODE_TYPES24.Property || property.computed)) return false;
|
|
3213
|
+
return !options.properties.some((property) => property.type === AST_NODE_TYPES24.Property && lifetimeProperty(property));
|
|
2993
3214
|
}
|
|
2994
3215
|
function lifetimeProperty(property) {
|
|
2995
|
-
const name = property.key.type ===
|
|
3216
|
+
const name = property.key.type === AST_NODE_TYPES24.Identifier ? property.key.name : property.key.type === AST_NODE_TYPES24.Literal ? property.key.value : null;
|
|
2996
3217
|
if (name === "maxTokenAge") {
|
|
2997
|
-
if (property.value.type !==
|
|
3218
|
+
if (property.value.type !== AST_NODE_TYPES24.Literal) return true;
|
|
2998
3219
|
return typeof property.value.value === "number" && Number.isFinite(property.value.value) || typeof property.value.value === "string" && property.value.value.trim() !== "";
|
|
2999
3220
|
}
|
|
3000
3221
|
if (name !== "requiredClaims") return false;
|
|
3001
|
-
if (property.value.type !==
|
|
3002
|
-
return property.value.elements.some((element) => element?.type ===
|
|
3222
|
+
if (property.value.type !== AST_NODE_TYPES24.ArrayExpression || property.value.elements.some((element) => element?.type !== AST_NODE_TYPES24.Literal)) return true;
|
|
3223
|
+
return property.value.elements.some((element) => element?.type === AST_NODE_TYPES24.Literal && element.value === "exp");
|
|
3003
3224
|
}
|
|
3004
3225
|
return {
|
|
3005
3226
|
ReturnStatement(node) {
|
|
@@ -3013,7 +3234,7 @@ var require_jwt_lifetime_default = createRule({
|
|
|
3013
3234
|
});
|
|
3014
3235
|
|
|
3015
3236
|
// src/rules/no-discarded-validation-result.ts
|
|
3016
|
-
import { AST_NODE_TYPES as
|
|
3237
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES25, ASTUtils as ASTUtils16 } from "@typescript-eslint/utils";
|
|
3017
3238
|
|
|
3018
3239
|
// src/rules/_zod.ts
|
|
3019
3240
|
var ZOD_SCHEMA_NAME_RE = /Schema$|^Z[A-Z]/;
|
|
@@ -3049,51 +3270,51 @@ var no_discarded_validation_result_default = createRule({
|
|
|
3049
3270
|
function schema(node, depth = 0) {
|
|
3050
3271
|
if (depth > 24) return null;
|
|
3051
3272
|
node = unwrapExpression(node);
|
|
3052
|
-
if (node.type ===
|
|
3273
|
+
if (node.type === AST_NODE_TYPES25.Identifier) {
|
|
3053
3274
|
const variable = ASTUtils16.findVariable(sourceCode.getScope(node), node.name);
|
|
3054
3275
|
const definition = variable?.defs[0]?.node;
|
|
3055
3276
|
if (variable?.defs.length !== 1) return null;
|
|
3056
|
-
if (definition?.type ===
|
|
3057
|
-
if (definition?.type ===
|
|
3058
|
-
if (definition?.type ===
|
|
3277
|
+
if (definition?.type === AST_NODE_TYPES25.ImportSpecifier && definition.parent.type === AST_NODE_TYPES25.ImportDeclaration && definition.importKind !== "type" && definition.parent.importKind !== "type" && isZodModule(definition.parent.source.value)) return { changed: false };
|
|
3278
|
+
if (definition?.type === AST_NODE_TYPES25.ImportNamespaceSpecifier && definition.parent.importKind !== "type" && isZodModule(definition.parent.source.value)) return { changed: false };
|
|
3279
|
+
if (definition?.type === AST_NODE_TYPES25.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);
|
|
3059
3280
|
return null;
|
|
3060
3281
|
}
|
|
3061
|
-
if (node.type ===
|
|
3282
|
+
if (node.type === AST_NODE_TYPES25.MemberExpression) {
|
|
3062
3283
|
const owner2 = schema(node.object, depth + 1);
|
|
3063
3284
|
return owner2;
|
|
3064
3285
|
}
|
|
3065
|
-
if (node.type !==
|
|
3286
|
+
if (node.type !== AST_NODE_TYPES25.CallExpression) return null;
|
|
3066
3287
|
const owner = schema(node.callee, depth + 1);
|
|
3067
3288
|
if (owner === null) return null;
|
|
3068
|
-
const invokedChange = node.callee.type ===
|
|
3069
|
-
const coerced = node.callee.type ===
|
|
3289
|
+
const invokedChange = node.callee.type === AST_NODE_TYPES25.MemberExpression && CHANGING.has(ASTUtils16.getPropertyName(node.callee) ?? "");
|
|
3290
|
+
const coerced = node.callee.type === AST_NODE_TYPES25.MemberExpression && coercionNamespace(node.callee.object);
|
|
3070
3291
|
const changedArgument = node.arguments.some((argument) => {
|
|
3071
|
-
if (argument.type ===
|
|
3072
|
-
if (argument.type ===
|
|
3292
|
+
if (argument.type === AST_NODE_TYPES25.ArrayExpression) return argument.elements.some((element) => element !== null && schema(element, depth + 1)?.changed === true);
|
|
3293
|
+
if (argument.type === AST_NODE_TYPES25.ObjectExpression) return argument.properties.some((property) => property.type === AST_NODE_TYPES25.Property && schema(property.value, depth + 1)?.changed === true);
|
|
3073
3294
|
return schema(argument, depth + 1)?.changed === true;
|
|
3074
3295
|
});
|
|
3075
3296
|
return { changed: owner.changed || invokedChange || coerced || changedArgument };
|
|
3076
3297
|
}
|
|
3077
3298
|
function coercionNamespace(node) {
|
|
3078
3299
|
let namespace = false;
|
|
3079
|
-
if (node.type ===
|
|
3300
|
+
if (node.type === AST_NODE_TYPES25.MemberExpression && ASTUtils16.getPropertyName(node) === "coerce") {
|
|
3080
3301
|
namespace = true;
|
|
3081
3302
|
node = node.object;
|
|
3082
3303
|
}
|
|
3083
|
-
if (node.type !==
|
|
3304
|
+
if (node.type !== AST_NODE_TYPES25.Identifier) return false;
|
|
3084
3305
|
const variable = ASTUtils16.findVariable(sourceCode.getScope(node), node.name);
|
|
3085
3306
|
const definition = variable?.defs[0]?.node;
|
|
3086
|
-
if (variable?.defs.length !== 1 || definition === void 0 || definition.parent.type !==
|
|
3087
|
-
if (definition.type ===
|
|
3088
|
-
if (definition.type !==
|
|
3089
|
-
const name = definition.imported.type ===
|
|
3307
|
+
if (variable?.defs.length !== 1 || definition === void 0 || definition.parent.type !== AST_NODE_TYPES25.ImportDeclaration || definition.parent.importKind === "type" || !isZodModule(definition.parent.source.value)) return false;
|
|
3308
|
+
if (definition.type === AST_NODE_TYPES25.ImportNamespaceSpecifier) return namespace;
|
|
3309
|
+
if (definition.type !== AST_NODE_TYPES25.ImportSpecifier || definition.importKind === "type") return false;
|
|
3310
|
+
const name = definition.imported.type === AST_NODE_TYPES25.Identifier ? definition.imported.name : definition.imported.value;
|
|
3090
3311
|
return namespace ? name === "z" : name === "coerce";
|
|
3091
3312
|
}
|
|
3092
3313
|
return {
|
|
3093
3314
|
ExpressionStatement(statement) {
|
|
3094
3315
|
let expression = unwrapExpression(statement.expression);
|
|
3095
|
-
if (expression.type ===
|
|
3096
|
-
if (expression.type !==
|
|
3316
|
+
if (expression.type === AST_NODE_TYPES25.AwaitExpression) expression = unwrapExpression(expression.argument);
|
|
3317
|
+
if (expression.type !== AST_NODE_TYPES25.CallExpression || expression.callee.type !== AST_NODE_TYPES25.MemberExpression) return;
|
|
3097
3318
|
const method = ASTUtils16.getPropertyName(expression.callee);
|
|
3098
3319
|
if (!(/* @__PURE__ */ new Set(["parse", "parseAsync", "safeParse", "safeParseAsync"])).has(method ?? "")) return;
|
|
3099
3320
|
const owner = schema(expression.callee.object);
|
|
@@ -3104,7 +3325,7 @@ var no_discarded_validation_result_default = createRule({
|
|
|
3104
3325
|
});
|
|
3105
3326
|
|
|
3106
3327
|
// src/rules/production-derived-test-cases.ts
|
|
3107
|
-
import { AST_NODE_TYPES as
|
|
3328
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES26, ASTUtils as ASTUtils17 } from "@typescript-eslint/utils";
|
|
3108
3329
|
var MEMBERSHIP = /(?:^|_)(?:ALLOWED|ELIGIBLE|REQUIRED|SUPPORTED)(?:_|$)/u;
|
|
3109
3330
|
var SUPPORT_PATH = /(?:^|[/_.-])(?:tests?|fixtures?|fakes?|mocks?|stubs?|__tests__)(?:[/_.-]|$)/u;
|
|
3110
3331
|
var PRODUCTION_DERIVED_TEST_CASES_DOCUMENTATION = {
|
|
@@ -3144,47 +3365,47 @@ var production_derived_test_cases_default = createRule({
|
|
|
3144
3365
|
function importedName7(node, module) {
|
|
3145
3366
|
const variable = binding3(node);
|
|
3146
3367
|
const specifier = variable?.defs[0]?.node;
|
|
3147
|
-
if (variable?.defs.length !== 1 || specifier?.type !==
|
|
3148
|
-
return specifier.imported.type ===
|
|
3368
|
+
if (variable?.defs.length !== 1 || specifier?.type !== AST_NODE_TYPES26.ImportSpecifier || specifier.importKind === "type" || specifier.parent.type !== AST_NODE_TYPES26.ImportDeclaration || specifier.parent.importKind === "type" || specifier.parent.source.value !== module || variable.references.some((reference) => reference.isWrite())) return null;
|
|
3369
|
+
return specifier.imported.type === AST_NODE_TYPES26.Identifier ? specifier.imported.name : specifier.imported.value;
|
|
3149
3370
|
}
|
|
3150
3371
|
function production(node) {
|
|
3151
3372
|
node = unwrapExpression(node);
|
|
3152
|
-
if (node.type !==
|
|
3373
|
+
if (node.type !== AST_NODE_TYPES26.Identifier) return null;
|
|
3153
3374
|
const variable = binding3(node);
|
|
3154
3375
|
const specifier = variable?.defs[0]?.node;
|
|
3155
|
-
if (variable?.defs.length !== 1 || specifier?.type !==
|
|
3156
|
-
const name = specifier.imported.type ===
|
|
3376
|
+
if (variable?.defs.length !== 1 || specifier?.type !== AST_NODE_TYPES26.ImportSpecifier || specifier.importKind === "type" || specifier.parent.type !== AST_NODE_TYPES26.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;
|
|
3377
|
+
const name = specifier.imported.type === AST_NODE_TYPES26.Identifier ? specifier.imported.name : specifier.imported.value;
|
|
3157
3378
|
return MEMBERSHIP.test(name) && !name.endsWith("REGISTRY") ? variable : null;
|
|
3158
3379
|
}
|
|
3159
3380
|
function runner(node) {
|
|
3160
3381
|
node = unwrapExpression(node);
|
|
3161
|
-
while (node.type ===
|
|
3162
|
-
if (node.type !==
|
|
3382
|
+
while (node.type === AST_NODE_TYPES26.MemberExpression && ["only", "skip", "concurrent", "sequential"].includes(ASTUtils17.getPropertyName(node) ?? "")) node = unwrapExpression(node.object);
|
|
3383
|
+
if (node.type !== AST_NODE_TYPES26.Identifier) return false;
|
|
3163
3384
|
const name = importedName7(node, "vitest");
|
|
3164
3385
|
return name === "test" || name === "it" || vitestFixtureTestName(sourceCode, node) !== null;
|
|
3165
3386
|
}
|
|
3166
3387
|
function caseTable(node) {
|
|
3167
|
-
return node.type ===
|
|
3388
|
+
return node.type === AST_NODE_TYPES26.CallExpression && node.callee.type === AST_NODE_TYPES26.MemberExpression && ["each", "for"].includes(ASTUtils17.getPropertyName(node.callee) ?? "") && runner(node.callee.object);
|
|
3168
3389
|
}
|
|
3169
3390
|
function literalTable(node, seen = /* @__PURE__ */ new Set()) {
|
|
3170
3391
|
node = unwrapExpression(node);
|
|
3171
3392
|
if (seen.has(node)) return false;
|
|
3172
3393
|
seen.add(node);
|
|
3173
|
-
if (node.type ===
|
|
3394
|
+
if (node.type === AST_NODE_TYPES26.Identifier) {
|
|
3174
3395
|
const variable = binding3(node);
|
|
3175
3396
|
const definition = variable?.defs[0]?.node;
|
|
3176
|
-
return variable?.defs.length === 1 && definition?.type ===
|
|
3397
|
+
return variable?.defs.length === 1 && definition?.type === AST_NODE_TYPES26.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_TYPES26.CallExpression && (caseTable(reference.identifier.parent) || reference.identifier.parent.callee.type === AST_NODE_TYPES26.Identifier && importedName7(reference.identifier.parent.callee, "vitest") === "expect" || reference.identifier.parent.callee.type === AST_NODE_TYPES26.MemberExpression && ["toEqual", "toStrictEqual"].includes(ASTUtils17.getPropertyName(reference.identifier.parent.callee) ?? ""))) && literalTable(definition.init, seen);
|
|
3177
3398
|
}
|
|
3178
|
-
return node.type ===
|
|
3399
|
+
return node.type === AST_NODE_TYPES26.ArrayExpression && node.elements.every((element) => element?.type === AST_NODE_TYPES26.Literal && !("regex" in element));
|
|
3179
3400
|
}
|
|
3180
3401
|
function unconditional(node) {
|
|
3181
3402
|
const statement = node.parent;
|
|
3182
|
-
if (statement.type !==
|
|
3183
|
-
if (statement.parent.type ===
|
|
3403
|
+
if (statement.type !== AST_NODE_TYPES26.ExpressionStatement) return false;
|
|
3404
|
+
if (statement.parent.type === AST_NODE_TYPES26.Program) return true;
|
|
3184
3405
|
const block = statement.parent;
|
|
3185
|
-
if (block.type !==
|
|
3406
|
+
if (block.type !== AST_NODE_TYPES26.BlockStatement || block.parent.type !== AST_NODE_TYPES26.ArrowFunctionExpression && block.parent.type !== AST_NODE_TYPES26.FunctionExpression) return false;
|
|
3186
3407
|
const call = block.parent.parent;
|
|
3187
|
-
return call.type ===
|
|
3408
|
+
return call.type === AST_NODE_TYPES26.CallExpression && runner(call.callee);
|
|
3188
3409
|
}
|
|
3189
3410
|
return {
|
|
3190
3411
|
CallExpression(node) {
|
|
@@ -3192,9 +3413,9 @@ var production_derived_test_cases_default = createRule({
|
|
|
3192
3413
|
const variable2 = production(node.arguments[0]);
|
|
3193
3414
|
if (variable2 !== null) tables.push({ node, variable: variable2 });
|
|
3194
3415
|
}
|
|
3195
|
-
if (node.callee.type !==
|
|
3416
|
+
if (node.callee.type !== AST_NODE_TYPES26.MemberExpression || !["toEqual", "toStrictEqual"].includes(ASTUtils17.getPropertyName(node.callee) ?? "") || node.arguments.length !== 1 || node.arguments[0] === void 0 || !literalTable(node.arguments[0]) || !unconditional(node)) return;
|
|
3196
3417
|
const expect = node.callee.object;
|
|
3197
|
-
if (expect.type !==
|
|
3418
|
+
if (expect.type !== AST_NODE_TYPES26.CallExpression || expect.callee.type !== AST_NODE_TYPES26.Identifier || importedName7(expect.callee, "vitest") !== "expect" || expect.arguments.length !== 1 || expect.arguments[0] === void 0) return;
|
|
3198
3419
|
const variable = production(expect.arguments[0]);
|
|
3199
3420
|
if (variable !== null) asserted.add(variable);
|
|
3200
3421
|
},
|
|
@@ -3206,14 +3427,14 @@ var production_derived_test_cases_default = createRule({
|
|
|
3206
3427
|
});
|
|
3207
3428
|
|
|
3208
3429
|
// src/rules/require-constrained-schema-integer.ts
|
|
3209
|
-
import { AST_NODE_TYPES as
|
|
3430
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES27, ASTUtils as ASTUtils18 } from "@typescript-eslint/utils";
|
|
3210
3431
|
var FIELD_MINIMUMS = /* @__PURE__ */ new Map([["limit", 1], ["version", 0]]);
|
|
3211
3432
|
var NUMBER_FACTORIES = /* @__PURE__ */ new Set(["number", "int", "int32", "uint32"]);
|
|
3212
3433
|
var PRESERVING = /* @__PURE__ */ new Set(["optional", "nullable", "nullish", "default", "catch", "readonly", "brand", "describe", "meta", "max", "lte", "lt", "finite", "safe", "multipleOf"]);
|
|
3213
3434
|
function numericLiteral(node) {
|
|
3214
3435
|
node = unwrapExpression(node);
|
|
3215
|
-
if (node.type ===
|
|
3216
|
-
if (node.type ===
|
|
3436
|
+
if (node.type === AST_NODE_TYPES27.Literal && typeof node.value === "number") return node.value;
|
|
3437
|
+
if (node.type === AST_NODE_TYPES27.UnaryExpression && (node.operator === "-" || node.operator === "+")) {
|
|
3217
3438
|
const value = numericLiteral(node.argument);
|
|
3218
3439
|
return value === null ? null : node.operator === "-" ? -value : value;
|
|
3219
3440
|
}
|
|
@@ -3250,34 +3471,34 @@ var require_constrained_schema_integer_default = createRule({
|
|
|
3250
3471
|
const sourceCode = context.sourceCode;
|
|
3251
3472
|
function factory(node) {
|
|
3252
3473
|
node = unwrapExpression(node);
|
|
3253
|
-
if (node.type ===
|
|
3474
|
+
if (node.type === AST_NODE_TYPES27.Identifier) {
|
|
3254
3475
|
const definition2 = imported(node);
|
|
3255
|
-
return definition2?.type ===
|
|
3476
|
+
return definition2?.type === AST_NODE_TYPES27.ImportSpecifier ? definition2.imported.type === AST_NODE_TYPES27.Identifier ? definition2.imported.name : definition2.imported.value : null;
|
|
3256
3477
|
}
|
|
3257
|
-
if (node.type !==
|
|
3478
|
+
if (node.type !== AST_NODE_TYPES27.MemberExpression) return null;
|
|
3258
3479
|
let receiver = unwrapExpression(node.object);
|
|
3259
|
-
if (receiver.type ===
|
|
3260
|
-
if (receiver.type !==
|
|
3480
|
+
if (receiver.type === AST_NODE_TYPES27.MemberExpression && ASTUtils18.getPropertyName(receiver) === "coerce") receiver = unwrapExpression(receiver.object);
|
|
3481
|
+
if (receiver.type !== AST_NODE_TYPES27.Identifier) return null;
|
|
3261
3482
|
const definition = imported(receiver);
|
|
3262
|
-
if (definition === null || definition.type ===
|
|
3483
|
+
if (definition === null || definition.type === AST_NODE_TYPES27.ImportSpecifier && (definition.imported.type === AST_NODE_TYPES27.Identifier ? definition.imported.name : definition.imported.value) !== "z") return null;
|
|
3263
3484
|
return ASTUtils18.getPropertyName(node);
|
|
3264
3485
|
}
|
|
3265
3486
|
function imported(identifier) {
|
|
3266
3487
|
const variable = ASTUtils18.findVariable(sourceCode.getScope(identifier), identifier.name);
|
|
3267
3488
|
const definition = variable?.defs[0]?.node;
|
|
3268
|
-
if (variable?.defs.length !== 1 || definition?.type !==
|
|
3269
|
-
return definition.type ===
|
|
3489
|
+
if (variable?.defs.length !== 1 || definition?.type !== AST_NODE_TYPES27.ImportSpecifier && definition?.type !== AST_NODE_TYPES27.ImportNamespaceSpecifier || definition.parent.type !== AST_NODE_TYPES27.ImportDeclaration || definition.parent.importKind === "type" || !isZodModule(definition.parent.source.value)) return null;
|
|
3490
|
+
return definition.type === AST_NODE_TYPES27.ImportSpecifier && definition.importKind === "type" ? null : definition;
|
|
3270
3491
|
}
|
|
3271
3492
|
function constrained(value, minimum) {
|
|
3272
3493
|
const calls = [];
|
|
3273
3494
|
value = unwrapExpression(value);
|
|
3274
|
-
while (value.type ===
|
|
3495
|
+
while (value.type === AST_NODE_TYPES27.CallExpression) {
|
|
3275
3496
|
const name = factory(value.callee);
|
|
3276
3497
|
if (name !== null) {
|
|
3277
3498
|
return chainContract(name, calls, minimum);
|
|
3278
3499
|
}
|
|
3279
3500
|
const callee = unwrapExpression(value.callee);
|
|
3280
|
-
if (callee.type !==
|
|
3501
|
+
if (callee.type !== AST_NODE_TYPES27.MemberExpression) return null;
|
|
3281
3502
|
const method = ASTUtils18.getPropertyName(callee);
|
|
3282
3503
|
if (method === null) return null;
|
|
3283
3504
|
calls.push({ method, call: value });
|
|
@@ -3303,7 +3524,7 @@ var require_constrained_schema_integer_default = createRule({
|
|
|
3303
3524
|
}
|
|
3304
3525
|
function lowerBound(call, minimum, exclusive) {
|
|
3305
3526
|
const argument = call.arguments[0];
|
|
3306
|
-
if (argument === void 0 || argument.type ===
|
|
3527
|
+
if (argument === void 0 || argument.type === AST_NODE_TYPES27.SpreadElement) return null;
|
|
3307
3528
|
const bound = numericLiteral(argument);
|
|
3308
3529
|
return bound === null || bound >= minimum - (exclusive ? 1 : 0);
|
|
3309
3530
|
}
|
|
@@ -3312,9 +3533,9 @@ var require_constrained_schema_integer_default = createRule({
|
|
|
3312
3533
|
const name = factory(node.callee);
|
|
3313
3534
|
if (name === null || !["object", "strictObject", "looseObject"].includes(name) || node.arguments.length !== 1) return;
|
|
3314
3535
|
const shape = node.arguments[0];
|
|
3315
|
-
if (shape?.type !==
|
|
3536
|
+
if (shape?.type !== AST_NODE_TYPES27.ObjectExpression) return;
|
|
3316
3537
|
for (const property of shape.properties) {
|
|
3317
|
-
if (property.type !==
|
|
3538
|
+
if (property.type !== AST_NODE_TYPES27.Property || property.computed || property.kind !== "init" || property.method) continue;
|
|
3318
3539
|
const field = ASTUtils18.getPropertyName(property);
|
|
3319
3540
|
const minimum = field === null ? void 0 : FIELD_MINIMUMS.get(field);
|
|
3320
3541
|
if (minimum === void 0 || field === null || constrained(property.value, minimum) !== false) continue;
|
|
@@ -3326,7 +3547,7 @@ var require_constrained_schema_integer_default = createRule({
|
|
|
3326
3547
|
});
|
|
3327
3548
|
|
|
3328
3549
|
// src/rules/no-generic-json-parser.ts
|
|
3329
|
-
import { AST_NODE_TYPES as
|
|
3550
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES28, ASTUtils as ASTUtils19 } from "@typescript-eslint/utils";
|
|
3330
3551
|
var OPEN_FACTORIES = /* @__PURE__ */ new Set(["any", "unknown", "json", "record", "partialRecord"]);
|
|
3331
3552
|
var WRAPPERS = /* @__PURE__ */ new Set(["optional", "nullable", "nullish", "default", "catch", "readonly", "brand", "describe", "meta"]);
|
|
3332
3553
|
var NO_GENERIC_JSON_PARSER_DOCUMENTATION = {
|
|
@@ -3364,19 +3585,19 @@ var no_generic_json_parser_default = createRule({
|
|
|
3364
3585
|
function initializer(node) {
|
|
3365
3586
|
const variable = binding3(node);
|
|
3366
3587
|
const definition = variable?.defs[0];
|
|
3367
|
-
if (variable?.defs.length !== 1 || definition?.node.type !==
|
|
3588
|
+
if (variable?.defs.length !== 1 || definition?.node.type !== AST_NODE_TYPES28.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;
|
|
3368
3589
|
return definition.node.init;
|
|
3369
3590
|
}
|
|
3370
3591
|
function parser(node, seen = /* @__PURE__ */ new Set(), awaited = false) {
|
|
3371
3592
|
node = unwrapExpression(node);
|
|
3372
3593
|
if (seen.has(node)) return null;
|
|
3373
3594
|
seen.add(node);
|
|
3374
|
-
if (node.type ===
|
|
3375
|
-
if (node.type ===
|
|
3595
|
+
if (node.type === AST_NODE_TYPES28.AwaitExpression) return parser(node.argument, seen, true);
|
|
3596
|
+
if (node.type === AST_NODE_TYPES28.Identifier) {
|
|
3376
3597
|
const value = initializer(node);
|
|
3377
3598
|
return value === null ? null : parser(value, seen, awaited);
|
|
3378
3599
|
}
|
|
3379
|
-
if (node.type !==
|
|
3600
|
+
if (node.type !== AST_NODE_TYPES28.CallExpression || node.callee.type !== AST_NODE_TYPES28.MemberExpression || !["parse", "parseAsync"].includes(ASTUtils19.getPropertyName(node.callee) ?? "")) return null;
|
|
3380
3601
|
if (ASTUtils19.getPropertyName(node.callee) === "parseAsync" && !awaited) return null;
|
|
3381
3602
|
return openSchema(node.callee.object) ? node : null;
|
|
3382
3603
|
}
|
|
@@ -3384,29 +3605,29 @@ var no_generic_json_parser_default = createRule({
|
|
|
3384
3605
|
node = unwrapExpression(node);
|
|
3385
3606
|
if (seen.has(node)) return false;
|
|
3386
3607
|
seen.add(node);
|
|
3387
|
-
if (node.type ===
|
|
3608
|
+
if (node.type === AST_NODE_TYPES28.Identifier) {
|
|
3388
3609
|
const value = initializer(node);
|
|
3389
3610
|
return value !== null && openSchema(value, seen);
|
|
3390
3611
|
}
|
|
3391
|
-
if (node.type !==
|
|
3612
|
+
if (node.type !== AST_NODE_TYPES28.CallExpression) return false;
|
|
3392
3613
|
const name = factory(node.callee);
|
|
3393
3614
|
if (name !== null) return OPEN_FACTORIES.has(name);
|
|
3394
3615
|
const callee = unwrapExpression(node.callee);
|
|
3395
|
-
return callee.type ===
|
|
3616
|
+
return callee.type === AST_NODE_TYPES28.MemberExpression && WRAPPERS.has(ASTUtils19.getPropertyName(callee) ?? "") && openSchema(callee.object, seen);
|
|
3396
3617
|
}
|
|
3397
3618
|
function factory(node) {
|
|
3398
3619
|
node = unwrapExpression(node);
|
|
3399
|
-
if (node.type ===
|
|
3620
|
+
if (node.type === AST_NODE_TYPES28.Identifier) {
|
|
3400
3621
|
const definition2 = binding3(node)?.defs[0]?.node;
|
|
3401
|
-
if (definition2?.type !==
|
|
3402
|
-
return definition2.imported.type ===
|
|
3622
|
+
if (definition2?.type !== AST_NODE_TYPES28.ImportSpecifier || definition2.parent.type !== AST_NODE_TYPES28.ImportDeclaration || definition2.importKind === "type" || definition2.parent.importKind === "type" || !isZodModule(definition2.parent.source.value)) return null;
|
|
3623
|
+
return definition2.imported.type === AST_NODE_TYPES28.Identifier ? definition2.imported.name : definition2.imported.value;
|
|
3403
3624
|
}
|
|
3404
|
-
if (node.type !==
|
|
3625
|
+
if (node.type !== AST_NODE_TYPES28.MemberExpression) return null;
|
|
3405
3626
|
const receiver = unwrapExpression(node.object);
|
|
3406
|
-
if (receiver.type !==
|
|
3627
|
+
if (receiver.type !== AST_NODE_TYPES28.Identifier) return null;
|
|
3407
3628
|
const definition = binding3(receiver)?.defs[0]?.node;
|
|
3408
|
-
if (definition === void 0 || definition.type !==
|
|
3409
|
-
if (definition.type ===
|
|
3629
|
+
if (definition === void 0 || definition.type !== AST_NODE_TYPES28.ImportSpecifier && definition.type !== AST_NODE_TYPES28.ImportNamespaceSpecifier || definition.parent.type !== AST_NODE_TYPES28.ImportDeclaration || definition.parent.importKind === "type" || !isZodModule(definition.parent.source.value)) return null;
|
|
3630
|
+
if (definition.type === AST_NODE_TYPES28.ImportSpecifier && (definition.importKind === "type" || (definition.imported.type === AST_NODE_TYPES28.Identifier ? definition.imported.name : definition.imported.value) !== "z")) return null;
|
|
3410
3631
|
return ASTUtils19.getPropertyName(node);
|
|
3411
3632
|
}
|
|
3412
3633
|
const reported = /* @__PURE__ */ new Set();
|
|
@@ -3421,10 +3642,160 @@ var no_generic_json_parser_default = createRule({
|
|
|
3421
3642
|
}
|
|
3422
3643
|
};
|
|
3423
3644
|
}
|
|
3424
|
-
});
|
|
3645
|
+
});
|
|
3646
|
+
|
|
3647
|
+
// src/rules/no-redundant-local-alias.ts
|
|
3648
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES31, ASTUtils as ASTUtils20 } from "@typescript-eslint/utils";
|
|
3649
|
+
|
|
3650
|
+
// src/rules/_unused-private-binding.ts
|
|
3651
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES30 } from "@typescript-eslint/utils";
|
|
3652
|
+
|
|
3653
|
+
// src/rules/_type-binding.ts
|
|
3654
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES29 } from "@typescript-eslint/utils";
|
|
3655
|
+
function typeBinding(source, identifier) {
|
|
3656
|
+
let scope = source.getScope(identifier);
|
|
3657
|
+
while (scope !== null) {
|
|
3658
|
+
const variable = scope.set.get(identifier.name);
|
|
3659
|
+
if (variable !== void 0 && (variable.isTypeVariable || variable.defs.some((definition) => definition.isTypeDefinition))) {
|
|
3660
|
+
return variable;
|
|
3661
|
+
}
|
|
3662
|
+
scope = scope.upper;
|
|
3663
|
+
}
|
|
3664
|
+
return null;
|
|
3665
|
+
}
|
|
3666
|
+
var REFERENCE_INDEXES = /* @__PURE__ */ new WeakMap();
|
|
3667
|
+
function retainsNamedTypeUses(source, removed) {
|
|
3668
|
+
const manager = source.scopeManager;
|
|
3669
|
+
if (manager === null) return false;
|
|
3670
|
+
const index = referenceIndex(source, manager);
|
|
3671
|
+
for (const reference of referencesWithin(index.references, removed)) {
|
|
3672
|
+
if (!reference.isRead()) continue;
|
|
3673
|
+
const binding3 = reference.resolved;
|
|
3674
|
+
if (!binding3 || !reference.isTypeReference && !reference.isValueReference) return false;
|
|
3675
|
+
if (binding3.defs.length === 0) continue;
|
|
3676
|
+
const reads = publicReadExtents(index, binding3);
|
|
3677
|
+
const extent = reference.isTypeReference ? reference.isValueReference ? reads.both : reads.type : reads.value;
|
|
3678
|
+
if (extent === null || extent.minStart >= removed.range[0] && extent.maxEnd <= removed.range[1]) return false;
|
|
3679
|
+
}
|
|
3680
|
+
return true;
|
|
3681
|
+
}
|
|
3682
|
+
function referenceIndex(source, manager) {
|
|
3683
|
+
const cached = REFERENCE_INDEXES.get(source);
|
|
3684
|
+
if (cached?.manager === manager) return cached;
|
|
3685
|
+
const references = manager.scopes.flatMap((scope) => scope.references);
|
|
3686
|
+
references.sort((left, right) => left.identifier.range[0] - right.identifier.range[0]);
|
|
3687
|
+
const index = { manager, references, publicReads: /* @__PURE__ */ new Map() };
|
|
3688
|
+
REFERENCE_INDEXES.set(source, index);
|
|
3689
|
+
return index;
|
|
3690
|
+
}
|
|
3691
|
+
function* referencesWithin(references, removed) {
|
|
3692
|
+
let low = 0;
|
|
3693
|
+
let high = references.length;
|
|
3694
|
+
while (low < high) {
|
|
3695
|
+
const middle = low + Math.floor((high - low) / 2);
|
|
3696
|
+
const reference = references[middle];
|
|
3697
|
+
if (reference === void 0 || reference.identifier.range[0] >= removed.range[0]) high = middle;
|
|
3698
|
+
else low = middle + 1;
|
|
3699
|
+
}
|
|
3700
|
+
for (let index = low; index < references.length; index++) {
|
|
3701
|
+
const reference = references[index];
|
|
3702
|
+
if (reference === void 0) continue;
|
|
3703
|
+
if (reference.identifier.range[0] > removed.range[1]) break;
|
|
3704
|
+
if (insideTypeRange(reference.identifier, removed)) yield reference;
|
|
3705
|
+
}
|
|
3706
|
+
}
|
|
3707
|
+
function publicReadExtents(index, binding3) {
|
|
3708
|
+
const cached = index.publicReads.get(binding3);
|
|
3709
|
+
if (cached !== void 0) return cached;
|
|
3710
|
+
let type = null;
|
|
3711
|
+
let value = null;
|
|
3712
|
+
let both = null;
|
|
3713
|
+
for (const retained of binding3.references) {
|
|
3714
|
+
if (!retained.isRead() || !retained.isTypeReference && !retained.isValueReference || binding3.defs.some((definition) => insideTypeRange(retained.identifier, definition.node)) || !publicTypeUse(retained.identifier)) continue;
|
|
3715
|
+
if (retained.isTypeReference) type = extendExtent(type, retained.identifier);
|
|
3716
|
+
if (retained.isValueReference) value = extendExtent(value, retained.identifier);
|
|
3717
|
+
if (retained.isTypeReference && retained.isValueReference) both = extendExtent(both, retained.identifier);
|
|
3718
|
+
}
|
|
3719
|
+
const result = { type, value, both };
|
|
3720
|
+
index.publicReads.set(binding3, result);
|
|
3721
|
+
return result;
|
|
3722
|
+
}
|
|
3723
|
+
function extendExtent(extent, identifier) {
|
|
3724
|
+
return {
|
|
3725
|
+
minStart: Math.min(extent?.minStart ?? identifier.range[0], identifier.range[0]),
|
|
3726
|
+
maxEnd: Math.max(extent?.maxEnd ?? identifier.range[1], identifier.range[1])
|
|
3727
|
+
};
|
|
3728
|
+
}
|
|
3729
|
+
function publicTypeUse(identifier) {
|
|
3730
|
+
let node = identifier;
|
|
3731
|
+
while (node.parent) {
|
|
3732
|
+
if (node.type === AST_NODE_TYPES29.TSTypeAnnotation || node.type === AST_NODE_TYPES29.TSTypePredicate || node.type === AST_NODE_TYPES29.TSAsExpression || node.type === AST_NODE_TYPES29.TSTypeAssertion) return false;
|
|
3733
|
+
if (node.type === AST_NODE_TYPES29.TSTypeAliasDeclaration) {
|
|
3734
|
+
return node.parent.type === AST_NODE_TYPES29.ExportNamedDeclaration && node.parent.declaration === node && node.parent.parent.type === AST_NODE_TYPES29.Program;
|
|
3735
|
+
}
|
|
3736
|
+
if (node.type === AST_NODE_TYPES29.ExportSpecifier) {
|
|
3737
|
+
return node.parent.type === AST_NODE_TYPES29.ExportNamedDeclaration && node.parent.source === null && node.parent.parent.type === AST_NODE_TYPES29.Program;
|
|
3738
|
+
}
|
|
3739
|
+
node = node.parent;
|
|
3740
|
+
}
|
|
3741
|
+
return false;
|
|
3742
|
+
}
|
|
3743
|
+
function insideTypeRange(node, range) {
|
|
3744
|
+
return node.range[0] >= range.range[0] && node.range[1] <= range.range[1];
|
|
3745
|
+
}
|
|
3746
|
+
|
|
3747
|
+
// src/rules/_unused-private-binding.ts
|
|
3748
|
+
function isUnusedPrivateBinding(sourceCode, declaration, identifier, filename, allowedDeclarations = [declaration]) {
|
|
3749
|
+
if (/\.d\.[cm]?ts$/u.test(filename)) return false;
|
|
3750
|
+
const bindings = sourceCode.getDeclaredVariables(declaration).filter((binding3) => binding3.name === identifier.name);
|
|
3751
|
+
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;
|
|
3752
|
+
if (hasIdentifierNamed(sourceCode.ast, "eval")) return false;
|
|
3753
|
+
const statement = declaration.type === AST_NODE_TYPES30.VariableDeclarator ? declaration.parent : declaration;
|
|
3754
|
+
if (statement.parent.type === AST_NODE_TYPES30.ExportNamedDeclaration || statement.parent.type === AST_NODE_TYPES30.ExportDefaultDeclaration) return false;
|
|
3755
|
+
if (statement.parent.type !== AST_NODE_TYPES30.Program) return statement.parent.type === AST_NODE_TYPES30.BlockStatement;
|
|
3756
|
+
return sourceCode.ast.body.some((node) => node.type === AST_NODE_TYPES30.ImportDeclaration || node.type === AST_NODE_TYPES30.ExportNamedDeclaration || node.type === AST_NODE_TYPES30.ExportDefaultDeclaration || node.type === AST_NODE_TYPES30.ExportAllDeclaration);
|
|
3757
|
+
}
|
|
3758
|
+
function hasOnlyDirectFactoryUses(variable) {
|
|
3759
|
+
return variable.references.every((reference) => {
|
|
3760
|
+
if (reference.isTypeReference && !reference.isValueReference) return true;
|
|
3761
|
+
const identifier = reference.identifier;
|
|
3762
|
+
const parent = identifier.parent;
|
|
3763
|
+
if (parent.type === AST_NODE_TYPES30.CallExpression && parent.callee === identifier) return true;
|
|
3764
|
+
return parent.type === AST_NODE_TYPES30.MemberExpression && parent.object === identifier && !parent.computed && parent.parent.type === AST_NODE_TYPES30.CallExpression && parent.parent.callee === parent;
|
|
3765
|
+
});
|
|
3766
|
+
}
|
|
3767
|
+
var IDENTIFIER_NAMES = /* @__PURE__ */ new WeakMap();
|
|
3768
|
+
function hasIdentifierNamed(node, name) {
|
|
3769
|
+
let names = IDENTIFIER_NAMES.get(node);
|
|
3770
|
+
if (names === void 0) {
|
|
3771
|
+
const collected = /* @__PURE__ */ new Set();
|
|
3772
|
+
const pending = [node];
|
|
3773
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
3774
|
+
while (pending.length > 0) {
|
|
3775
|
+
const current = pending.pop();
|
|
3776
|
+
if (current === void 0 || seen.has(current)) continue;
|
|
3777
|
+
seen.add(current);
|
|
3778
|
+
if (current.type === AST_NODE_TYPES30.Identifier || current.type === AST_NODE_TYPES30.JSXIdentifier) collected.add(current.name);
|
|
3779
|
+
forEachOwnAstChild(current, (child) => {
|
|
3780
|
+
pending.push(child);
|
|
3781
|
+
}, (key) => key !== "tokens" && key !== "comments");
|
|
3782
|
+
}
|
|
3783
|
+
names = collected;
|
|
3784
|
+
IDENTIFIER_NAMES.set(node, names);
|
|
3785
|
+
}
|
|
3786
|
+
return names.has(name);
|
|
3787
|
+
}
|
|
3788
|
+
function privatePredicateBooleanFix(sourceCode, node, annotation, filename) {
|
|
3789
|
+
if (!annotation.typeAnnotation || !retainsNamedTypeUses(sourceCode, annotation.typeAnnotation) || node.type !== AST_NODE_TYPES30.FunctionDeclaration || node.id === null || !isUnusedPrivateBinding(sourceCode, node, node.id, filename) || sourceCode.getCommentsInside(annotation).length > 0) return null;
|
|
3790
|
+
const text = `boolean${sourceCode.getText(annotation).replace(/[^\r\n\u2028\u2029]/gu, "")}`;
|
|
3791
|
+
const neighbor = Math.max(0, annotation.range[0] - 1);
|
|
3792
|
+
const before = sourceCode.text.slice(neighbor, annotation.range[1] + 1).match(/\r\n|[\r\n\u2028\u2029]/gu) ?? [];
|
|
3793
|
+
const after = (sourceCode.text.slice(neighbor, annotation.range[0]) + text + sourceCode.text.slice(annotation.range[1], annotation.range[1] + 1)).match(/\r\n|[\r\n\u2028\u2029]/gu) ?? [];
|
|
3794
|
+
if (before.length !== after.length || before.some((ending, index) => ending !== after[index])) return null;
|
|
3795
|
+
return (fixer) => fixer.replaceText(annotation, text);
|
|
3796
|
+
}
|
|
3425
3797
|
|
|
3426
3798
|
// src/rules/no-redundant-local-alias.ts
|
|
3427
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES30, ASTUtils as ASTUtils20 } from "@typescript-eslint/utils";
|
|
3428
3799
|
var NO_REDUNDANT_LOCAL_ALIAS_DOCUMENTATION = {
|
|
3429
3800
|
defaultLevel: "warning",
|
|
3430
3801
|
summary: "Pass the original local into an object field instead of creating a single-use rename.",
|
|
@@ -3446,24 +3817,24 @@ var NO_REDUNDANT_LOCAL_ALIAS_DOCUMENTATION = {
|
|
|
3446
3817
|
function stableSource(variable, alias) {
|
|
3447
3818
|
const definition = variable.defs[0];
|
|
3448
3819
|
if (variable.defs.length !== 1 || definition === void 0 || variable.references.some((reference) => reference.isWrite() && !reference.init)) return false;
|
|
3449
|
-
return definition.type === "Parameter" || definition.node.type ===
|
|
3820
|
+
return definition.type === "Parameter" || definition.node.type === AST_NODE_TYPES31.VariableDeclarator && definition.node.parent.kind === "const" && definition.node.init !== null && definition.node.range[1] < alias.range[0];
|
|
3450
3821
|
}
|
|
3451
3822
|
var PRIMITIVE_PARAMETERS = /* @__PURE__ */ new Set([
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3823
|
+
AST_NODE_TYPES31.TSStringKeyword,
|
|
3824
|
+
AST_NODE_TYPES31.TSNumberKeyword,
|
|
3825
|
+
AST_NODE_TYPES31.TSBooleanKeyword,
|
|
3826
|
+
AST_NODE_TYPES31.TSBigIntKeyword,
|
|
3827
|
+
AST_NODE_TYPES31.TSSymbolKeyword
|
|
3457
3828
|
]);
|
|
3458
3829
|
function closedPrimitiveReturnFix(sourceCode, node, property, source, target) {
|
|
3459
3830
|
const statement = node.parent;
|
|
3460
3831
|
const body3 = statement.parent;
|
|
3461
|
-
if (body3.type !==
|
|
3832
|
+
if (body3.type !== AST_NODE_TYPES31.BlockStatement) return null;
|
|
3462
3833
|
const owner = body3.parent;
|
|
3463
|
-
if (owner.type !==
|
|
3834
|
+
if (owner.type !== AST_NODE_TYPES31.FunctionDeclaration || owner.parent.type !== AST_NODE_TYPES31.Program || owner.id === null || owner.async || owner.generator || owner.typeParameters !== void 0 || owner.returnType !== void 0 || owner.params.length !== 1 || body3.body.length !== 2 || body3.body[0] !== statement || node.id.type !== AST_NODE_TYPES31.Identifier || node.id.name === "__proto__" || node.init?.type !== AST_NODE_TYPES31.Identifier || sourceCode.getCommentsInside(owner).length !== 0 || hasIdentifierNamed(sourceCode.ast, "eval")) return null;
|
|
3464
3835
|
const parameter = owner.params[0];
|
|
3465
3836
|
const returned2 = body3.body[1];
|
|
3466
|
-
if (parameter?.type !==
|
|
3837
|
+
if (parameter?.type !== AST_NODE_TYPES31.Identifier || parameter.optional === true || parameter.typeAnnotation === void 0 || !PRIMITIVE_PARAMETERS.has(parameter.typeAnnotation.typeAnnotation.type) || returned2?.type !== AST_NODE_TYPES31.ReturnStatement || returned2.argument !== property.parent || property.parent.type !== AST_NODE_TYPES31.ObjectExpression || property.parent.properties.length !== 1 || ASTUtils20.findVariable(sourceCode.getScope(parameter), parameter.name) !== source || ASTUtils20.findVariable(sourceCode.getScope(property), node.init.name) !== source || source.references.some((reference) => reference.isTypeReference) || target.references.some((reference) => reference.isTypeReference)) return null;
|
|
3467
3838
|
const name = owner.id.name;
|
|
3468
3839
|
const bindings = sourceCode.getDeclaredVariables(owner).filter((binding3) => binding3.name === name);
|
|
3469
3840
|
if (bindings.length !== 1 || bindings[0]?.defs.length !== 1 || bindings[0].defs[0]?.node !== owner || bindings[0].references.some((reference) => reference.isTypeReference)) return null;
|
|
@@ -3490,10 +3861,10 @@ var no_redundant_local_alias_default = createRule({
|
|
|
3490
3861
|
defaultOptions: [],
|
|
3491
3862
|
create(context) {
|
|
3492
3863
|
if (isGeneratedFile(context, context.sourceCode.text)) return {};
|
|
3493
|
-
const hasModuleSyntax = context.sourceCode.ast.body.some((candidate2) => candidate2.type ===
|
|
3864
|
+
const hasModuleSyntax = context.sourceCode.ast.body.some((candidate2) => candidate2.type === AST_NODE_TYPES31.ImportDeclaration || candidate2.type === AST_NODE_TYPES31.ExportNamedDeclaration || candidate2.type === AST_NODE_TYPES31.ExportDefaultDeclaration || candidate2.type === AST_NODE_TYPES31.ExportAllDeclaration);
|
|
3494
3865
|
return {
|
|
3495
3866
|
VariableDeclarator(node) {
|
|
3496
|
-
if (node.parent.kind !== "const" || node.parent.declarations.length !== 1 || node.id.type !==
|
|
3867
|
+
if (node.parent.kind !== "const" || node.parent.declarations.length !== 1 || node.id.type !== AST_NODE_TYPES31.Identifier || node.id.typeAnnotation !== void 0 || node.init?.type !== AST_NODE_TYPES31.Identifier) return;
|
|
3497
3868
|
const scope = context.sourceCode.getScope(node);
|
|
3498
3869
|
if (scope.variableScope.type !== "function") return;
|
|
3499
3870
|
const target = ASTUtils20.findVariable(scope, node.id.name);
|
|
@@ -3504,7 +3875,7 @@ var no_redundant_local_alias_default = createRule({
|
|
|
3504
3875
|
const read = reads[0];
|
|
3505
3876
|
if (read === void 0 || read.from.variableScope !== scope.variableScope) return;
|
|
3506
3877
|
const property = read.identifier.parent;
|
|
3507
|
-
if (property.type !==
|
|
3878
|
+
if (property.type !== AST_NODE_TYPES31.Property || !property.shorthand || property.value !== read.identifier || property.parent.type !== AST_NODE_TYPES31.ObjectExpression || property.computed || property.method || property.kind !== "init") return;
|
|
3508
3879
|
context.report({ node, messageId: "redundantAlias", fix: hasModuleSyntax ? closedPrimitiveReturnFix(context.sourceCode, node, property, source, target) : null, data: { source: node.init.name, target: node.id.name } });
|
|
3509
3880
|
}
|
|
3510
3881
|
};
|
|
@@ -3512,14 +3883,14 @@ var no_redundant_local_alias_default = createRule({
|
|
|
3512
3883
|
});
|
|
3513
3884
|
|
|
3514
3885
|
// src/rules/no-mutating-container-transform.ts
|
|
3515
|
-
import { AST_NODE_TYPES as
|
|
3886
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES32, ASTUtils as ASTUtils21 } from "@typescript-eslint/utils";
|
|
3516
3887
|
var MUTATORS = /* @__PURE__ */ new Set(["copyWithin", "fill", "pop", "push", "reverse", "shift", "sort", "splice", "unshift"]);
|
|
3517
3888
|
var PRIMITIVES = /* @__PURE__ */ new Set([
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3889
|
+
AST_NODE_TYPES32.TSStringKeyword,
|
|
3890
|
+
AST_NODE_TYPES32.TSNumberKeyword,
|
|
3891
|
+
AST_NODE_TYPES32.TSBooleanKeyword,
|
|
3892
|
+
AST_NODE_TYPES32.TSBigIntKeyword,
|
|
3893
|
+
AST_NODE_TYPES32.TSSymbolKeyword
|
|
3523
3894
|
]);
|
|
3524
3895
|
var NO_MUTATING_CONTAINER_TRANSFORM_DOCUMENTATION = {
|
|
3525
3896
|
defaultLevel: "warning",
|
|
@@ -3538,27 +3909,27 @@ var NO_MUTATING_CONTAINER_TRANSFORM_DOCUMENTATION = {
|
|
|
3538
3909
|
]
|
|
3539
3910
|
};
|
|
3540
3911
|
function arrayElement(node, sourceCode) {
|
|
3541
|
-
if (node.type ===
|
|
3542
|
-
if (node.type ===
|
|
3912
|
+
if (node.type === AST_NODE_TYPES32.TSArrayType) return node.elementType;
|
|
3913
|
+
if (node.type === AST_NODE_TYPES32.TSTypeReference && node.typeName.type === AST_NODE_TYPES32.Identifier && (node.typeName.name === "Array" || node.typeName.name === "ReadonlyArray") && (ASTUtils21.findVariable(sourceCode.getScope(node.typeName), node.typeName.name)?.defs.length ?? 0) === 0 && node.typeArguments?.params.length === 1) return node.typeArguments.params[0] ?? null;
|
|
3543
3914
|
return null;
|
|
3544
3915
|
}
|
|
3545
3916
|
function returnsArray(node, sourceCode) {
|
|
3546
3917
|
let annotation = node.returnType?.typeAnnotation;
|
|
3547
|
-
if (annotation?.type ===
|
|
3918
|
+
if (annotation?.type === AST_NODE_TYPES32.TSTypeReference && annotation.typeName.type === AST_NODE_TYPES32.Identifier && annotation.typeName.name === "Promise" && (ASTUtils21.findVariable(sourceCode.getScope(annotation.typeName), "Promise")?.defs.length ?? 0) === 0 && annotation.typeArguments?.params.length === 1) annotation = annotation.typeArguments.params[0];
|
|
3548
3919
|
return annotation !== void 0 && arrayElement(annotation, sourceCode) !== null;
|
|
3549
3920
|
}
|
|
3550
3921
|
function supported(statements) {
|
|
3551
3922
|
return statements.every((statement) => {
|
|
3552
3923
|
switch (statement.type) {
|
|
3553
|
-
case
|
|
3554
|
-
case
|
|
3555
|
-
case
|
|
3556
|
-
case
|
|
3557
|
-
case
|
|
3924
|
+
case AST_NODE_TYPES32.ExpressionStatement:
|
|
3925
|
+
case AST_NODE_TYPES32.VariableDeclaration:
|
|
3926
|
+
case AST_NODE_TYPES32.ReturnStatement:
|
|
3927
|
+
case AST_NODE_TYPES32.ThrowStatement:
|
|
3928
|
+
case AST_NODE_TYPES32.EmptyStatement:
|
|
3558
3929
|
return true;
|
|
3559
|
-
case
|
|
3930
|
+
case AST_NODE_TYPES32.BlockStatement:
|
|
3560
3931
|
return supported(statement.body);
|
|
3561
|
-
case
|
|
3932
|
+
case AST_NODE_TYPES32.IfStatement:
|
|
3562
3933
|
return supported([statement.consequent]) && (statement.alternate === null || supported([statement.alternate]));
|
|
3563
3934
|
default:
|
|
3564
3935
|
return false;
|
|
@@ -3579,13 +3950,13 @@ var no_mutating_container_transform_default = createRule({
|
|
|
3579
3950
|
if (isGeneratedFile(context, context.sourceCode.text)) return {};
|
|
3580
3951
|
const sourceCode = context.sourceCode;
|
|
3581
3952
|
function binding3(node) {
|
|
3582
|
-
return node.type ===
|
|
3953
|
+
return node.type === AST_NODE_TYPES32.Identifier ? ASTUtils21.findVariable(sourceCode.getScope(node), node.name) : null;
|
|
3583
3954
|
}
|
|
3584
3955
|
function inspect(node) {
|
|
3585
|
-
if (node.body?.type !==
|
|
3956
|
+
if (node.body?.type !== AST_NODE_TYPES32.BlockStatement || !returnsArray(node, sourceCode) || !supported(node.body.body)) return;
|
|
3586
3957
|
const initial = /* @__PURE__ */ new Map();
|
|
3587
3958
|
for (const parameter of node.params) {
|
|
3588
|
-
if (parameter.type !==
|
|
3959
|
+
if (parameter.type !== AST_NODE_TYPES32.Identifier || parameter.typeAnnotation === void 0) continue;
|
|
3589
3960
|
const element = arrayElement(parameter.typeAnnotation.typeAnnotation, sourceCode);
|
|
3590
3961
|
const variable = binding3(parameter);
|
|
3591
3962
|
if (element !== null && PRIMITIVES.has(element.type) && variable !== null) initial.set(variable, parameter.name);
|
|
@@ -3598,26 +3969,26 @@ var no_mutating_container_transform_default = createRule({
|
|
|
3598
3969
|
}
|
|
3599
3970
|
function expression(current, state) {
|
|
3600
3971
|
switch (current.type) {
|
|
3601
|
-
case
|
|
3602
|
-
case
|
|
3603
|
-
case
|
|
3972
|
+
case AST_NODE_TYPES32.FunctionExpression:
|
|
3973
|
+
case AST_NODE_TYPES32.ArrowFunctionExpression:
|
|
3974
|
+
case AST_NODE_TYPES32.ClassExpression:
|
|
3604
3975
|
return;
|
|
3605
|
-
case
|
|
3976
|
+
case AST_NODE_TYPES32.AssignmentExpression:
|
|
3606
3977
|
assignment(current, state);
|
|
3607
3978
|
return;
|
|
3608
|
-
case
|
|
3979
|
+
case AST_NODE_TYPES32.LogicalExpression:
|
|
3609
3980
|
logical(current, state);
|
|
3610
3981
|
return;
|
|
3611
|
-
case
|
|
3982
|
+
case AST_NODE_TYPES32.ConditionalExpression:
|
|
3612
3983
|
conditional(current, state);
|
|
3613
3984
|
return;
|
|
3614
|
-
case
|
|
3985
|
+
case AST_NODE_TYPES32.UpdateExpression:
|
|
3615
3986
|
write(current.argument, state);
|
|
3616
3987
|
break;
|
|
3617
|
-
case
|
|
3988
|
+
case AST_NODE_TYPES32.UnaryExpression:
|
|
3618
3989
|
if (current.operator === "delete") write(current.argument, state);
|
|
3619
3990
|
break;
|
|
3620
|
-
case
|
|
3991
|
+
case AST_NODE_TYPES32.CallExpression:
|
|
3621
3992
|
mutationCall(current, state);
|
|
3622
3993
|
break;
|
|
3623
3994
|
default:
|
|
@@ -3637,13 +4008,13 @@ var no_mutating_container_transform_default = createRule({
|
|
|
3637
4008
|
function logical(current, state) {
|
|
3638
4009
|
expression(current.left, state);
|
|
3639
4010
|
const left = unwrapExpression(current.left);
|
|
3640
|
-
if (left.type ===
|
|
4011
|
+
if (left.type === AST_NODE_TYPES32.Literal && (current.operator === "&&" && !left.value || current.operator === "||" && !!left.value || current.operator === "??" && left.value !== null)) return;
|
|
3641
4012
|
expression(current.right, state);
|
|
3642
4013
|
}
|
|
3643
4014
|
function conditional(current, state) {
|
|
3644
4015
|
expression(current.test, state);
|
|
3645
4016
|
const test = unwrapExpression(current.test);
|
|
3646
|
-
if (test.type ===
|
|
4017
|
+
if (test.type === AST_NODE_TYPES32.Literal) {
|
|
3647
4018
|
expression(test.value ? current.consequent : current.alternate, state);
|
|
3648
4019
|
return;
|
|
3649
4020
|
}
|
|
@@ -3651,13 +4022,13 @@ var no_mutating_container_transform_default = createRule({
|
|
|
3651
4022
|
expression(current.alternate, state);
|
|
3652
4023
|
}
|
|
3653
4024
|
function mutationCall(current, state) {
|
|
3654
|
-
if (current.callee.type !==
|
|
4025
|
+
if (current.callee.type !== AST_NODE_TYPES32.MemberExpression || !MUTATORS.has(ASTUtils21.getPropertyName(current.callee) ?? "")) return;
|
|
3655
4026
|
const parameter = origin(current.callee.object, state);
|
|
3656
4027
|
if (parameter !== void 0 && first === null) first = { node: current, parameter };
|
|
3657
4028
|
}
|
|
3658
4029
|
function write(target, state) {
|
|
3659
4030
|
target = unwrapExpression(target);
|
|
3660
|
-
if (target.type !==
|
|
4031
|
+
if (target.type !== AST_NODE_TYPES32.MemberExpression || !target.computed && ASTUtils21.getPropertyName(target) !== "length") return;
|
|
3661
4032
|
const parameter = origin(target.object, state);
|
|
3662
4033
|
if (parameter !== void 0 && first === null) first = { node: target, parameter };
|
|
3663
4034
|
}
|
|
@@ -3667,18 +4038,18 @@ var no_mutating_container_transform_default = createRule({
|
|
|
3667
4038
|
}
|
|
3668
4039
|
function statement(current, state) {
|
|
3669
4040
|
switch (current.type) {
|
|
3670
|
-
case
|
|
4041
|
+
case AST_NODE_TYPES32.BlockStatement:
|
|
3671
4042
|
return statements(current.body, state);
|
|
3672
|
-
case
|
|
4043
|
+
case AST_NODE_TYPES32.IfStatement:
|
|
3673
4044
|
return branch(current, state);
|
|
3674
|
-
case
|
|
4045
|
+
case AST_NODE_TYPES32.VariableDeclaration:
|
|
3675
4046
|
declarations(current, state);
|
|
3676
4047
|
return false;
|
|
3677
|
-
case
|
|
3678
|
-
case
|
|
4048
|
+
case AST_NODE_TYPES32.ReturnStatement:
|
|
4049
|
+
case AST_NODE_TYPES32.ThrowStatement:
|
|
3679
4050
|
if (current.argument !== null) expression(current.argument, state);
|
|
3680
4051
|
return true;
|
|
3681
|
-
case
|
|
4052
|
+
case AST_NODE_TYPES32.ExpressionStatement:
|
|
3682
4053
|
expression(current.expression, state);
|
|
3683
4054
|
return false;
|
|
3684
4055
|
default:
|
|
@@ -3687,7 +4058,7 @@ var no_mutating_container_transform_default = createRule({
|
|
|
3687
4058
|
}
|
|
3688
4059
|
function branch(current, state) {
|
|
3689
4060
|
expression(current.test, state);
|
|
3690
|
-
if (current.test.type ===
|
|
4061
|
+
if (current.test.type === AST_NODE_TYPES32.Literal) return current.test.value ? statements([current.consequent], state) : current.alternate !== null && statements([current.alternate], state);
|
|
3691
4062
|
const left = new Map(state);
|
|
3692
4063
|
const right = new Map(state);
|
|
3693
4064
|
const leftEnds = statements([current.consequent], left);
|
|
@@ -3722,60 +4093,8 @@ var no_mutating_container_transform_default = createRule({
|
|
|
3722
4093
|
import { AST_NODE_TYPES as AST_NODE_TYPES34 } from "@typescript-eslint/utils";
|
|
3723
4094
|
import ts11 from "typescript";
|
|
3724
4095
|
|
|
3725
|
-
// src/rules/_checked-native-source.ts
|
|
3726
|
-
import ts5 from "typescript";
|
|
3727
|
-
var CHECKED = /* @__PURE__ */ new WeakMap();
|
|
3728
|
-
var SINGLE_LINE_DIRECTIVE = /^\/\/\/?\s*@(?:ts-expect-error|ts-ignore)/u;
|
|
3729
|
-
var MULTI_LINE_DIRECTIVE = /^[/*]*\s*@(?:ts-expect-error|ts-ignore)/u;
|
|
3730
|
-
var SINGLE_LINE_PRAGMA = /^\/\/\/?\s*@([^\s:]+)(?:(?:[^\S\r\n]|:).*)?$/mu;
|
|
3731
|
-
function currentNativeSource(sourceCode, services) {
|
|
3732
|
-
const source = services.esTreeNodeToTSNodeMap.get(sourceCode.ast);
|
|
3733
|
-
return ts5.isSourceFile(source) && services.program.getSourceFile(source.fileName) === source && source.text === sourceCode.text ? source : null;
|
|
3734
|
-
}
|
|
3735
|
-
function checkedNativeSource(program, source) {
|
|
3736
|
-
let files = CHECKED.get(program);
|
|
3737
|
-
if (!files) {
|
|
3738
|
-
files = /* @__PURE__ */ new WeakMap();
|
|
3739
|
-
CHECKED.set(program, files);
|
|
3740
|
-
}
|
|
3741
|
-
const known2 = files.get(source);
|
|
3742
|
-
if (known2 !== void 0) return known2;
|
|
3743
|
-
const available = !program.getCompilerOptions().noCheck && !source.isDeclarationFile && (source.flags & (ts5.NodeFlags.JavaScriptFile | ts5.NodeFlags.JsonFile)) === 0 && !program.getProjectReferences()?.length && !program.getResolvedProjectReferences()?.length && program.getSourceFile(source.fileName) === source && !program.isSourceFileFromExternalLibrary(source) && !program.isSourceFileDefaultLibrary(source) && !program.getSyntacticDiagnostics(source).some((diagnostic) => diagnostic.category === ts5.DiagnosticCategory.Error && diagnostic.file === source) && !checkingSuppressed(source) && !program.getSemanticDiagnostics(source).some((diagnostic) => diagnostic.category === ts5.DiagnosticCategory.Error && diagnostic.file === source);
|
|
3744
|
-
files.set(source, available);
|
|
3745
|
-
return available;
|
|
3746
|
-
}
|
|
3747
|
-
function checkingSuppressed(source) {
|
|
3748
|
-
if (!/@ts-/iu.test(source.text)) return false;
|
|
3749
|
-
if (ts5.getLeadingCommentRanges(source.text, 0)?.some((comment) => comment.kind === ts5.SyntaxKind.SingleLineCommentTrivia && SINGLE_LINE_PRAGMA.exec(source.text.slice(comment.pos, comment.end))?.[1]?.toLowerCase() === "ts-nocheck")) return true;
|
|
3750
|
-
const pending = [source];
|
|
3751
|
-
while (pending.length) {
|
|
3752
|
-
const node = pending.pop();
|
|
3753
|
-
if (!node || ts5.isJsxText(node) || ts5.isJSDoc(node) || (node.flags & ts5.NodeFlags.JSDoc) !== 0) continue;
|
|
3754
|
-
if (!ts5.isToken(node)) {
|
|
3755
|
-
for (const child of node.getChildren(source)) pending.push(child);
|
|
3756
|
-
continue;
|
|
3757
|
-
}
|
|
3758
|
-
if (tokenTriviaSuppressesChecking(node, source)) return true;
|
|
3759
|
-
}
|
|
3760
|
-
return false;
|
|
3761
|
-
}
|
|
3762
|
-
function tokenTriviaSuppressesChecking(node, source) {
|
|
3763
|
-
const start = node.getStart(source);
|
|
3764
|
-
for (const comment of [...ts5.getLeadingCommentRanges(source.text, node.pos) ?? [], ...ts5.getTrailingCommentRanges(source.text, node.pos) ?? []]) {
|
|
3765
|
-
if (comment.pos < node.pos || comment.end > start) continue;
|
|
3766
|
-
if (commentSuppressesChecking(source.text.slice(comment.pos, comment.end), comment.kind)) return true;
|
|
3767
|
-
}
|
|
3768
|
-
return false;
|
|
3769
|
-
}
|
|
3770
|
-
function commentSuppressesChecking(text, kind) {
|
|
3771
|
-
if (kind === ts5.SyntaxKind.SingleLineCommentTrivia) return SINGLE_LINE_DIRECTIVE.test(text);
|
|
3772
|
-
let lastLine = text.length;
|
|
3773
|
-
while (lastLine > 0 && !ts5.isLineBreak(text.charCodeAt(lastLine - 1))) lastLine--;
|
|
3774
|
-
return MULTI_LINE_DIRECTIVE.test(text.slice(lastLine).trimStart());
|
|
3775
|
-
}
|
|
3776
|
-
|
|
3777
4096
|
// src/rules/_closed-object-contract.ts
|
|
3778
|
-
import
|
|
4097
|
+
import ts9 from "typescript";
|
|
3779
4098
|
function closedObjectContract(type, checker, singlePropertyOrigins = false) {
|
|
3780
4099
|
return visitContract(type, {
|
|
3781
4100
|
checker,
|
|
@@ -3797,7 +4116,7 @@ function visitContract(type, proof) {
|
|
|
3797
4116
|
function completeObject(type, proof) {
|
|
3798
4117
|
if (!ordinaryObject(type, proof.checker)) return false;
|
|
3799
4118
|
if (proof.origins && !singleOrigins(type, proof.origins)) return false;
|
|
3800
|
-
const declarations = type.getSymbol()?.getDeclarations()?.filter((declaration) =>
|
|
4119
|
+
const declarations = type.getSymbol()?.getDeclarations()?.filter((declaration) => ts9.isInterfaceDeclaration(declaration) || ts9.isTypeLiteralNode(declaration));
|
|
3801
4120
|
if (!declarations?.length) return false;
|
|
3802
4121
|
return declarations.every((declaration) => completeDeclaration(declaration, proof));
|
|
3803
4122
|
}
|
|
@@ -3811,36 +4130,36 @@ function singleOrigins(type, origins) {
|
|
|
3811
4130
|
return true;
|
|
3812
4131
|
}
|
|
3813
4132
|
function ordinaryObject(type, checker) {
|
|
3814
|
-
if ((type.flags &
|
|
4133
|
+
if ((type.flags & ts9.TypeFlags.Object) === 0 || type.isUnion() || checker.getIndexInfosOfType(type).length > 0) return false;
|
|
3815
4134
|
const object = type;
|
|
3816
|
-
if ((object.objectFlags & (
|
|
3817
|
-
if ((object.objectFlags &
|
|
3818
|
-
return checker.getSignaturesOfType(type,
|
|
4135
|
+
if ((object.objectFlags & (ts9.ObjectFlags.Class | ts9.ObjectFlags.Mapped)) !== 0) return false;
|
|
4136
|
+
if ((object.objectFlags & ts9.ObjectFlags.Reference) !== 0 && checker.getTypeArguments(type).some((argument) => (argument.flags & (ts9.TypeFlags.Any | ts9.TypeFlags.Unknown | ts9.TypeFlags.TypeParameter)) !== 0)) return false;
|
|
4137
|
+
return checker.getSignaturesOfType(type, ts9.SignatureKind.Call).length === 0 && checker.getSignaturesOfType(type, ts9.SignatureKind.Construct).length === 0;
|
|
3819
4138
|
}
|
|
3820
4139
|
function completeDeclaration(declaration, proof) {
|
|
3821
4140
|
if (!declaration.members.every((member3) => finiteMember(member3, proof.checker))) return false;
|
|
3822
|
-
if (!
|
|
4141
|
+
if (!ts9.isInterfaceDeclaration(declaration)) return true;
|
|
3823
4142
|
if (declaration.typeParameters?.length) return false;
|
|
3824
4143
|
return (declaration.heritageClauses ?? []).every((heritage) => heritage.types.every((base) => visitContract(proof.checker.getTypeAtLocation(base), proof)));
|
|
3825
4144
|
}
|
|
3826
4145
|
function finiteMember(member3, checker) {
|
|
3827
|
-
if (
|
|
3828
|
-
if (!member3.name || !
|
|
3829
|
-
return (checker.getTypeAtLocation(member3.name.expression).flags & (
|
|
4146
|
+
if (ts9.isIndexSignatureDeclaration(member3)) return false;
|
|
4147
|
+
if (!member3.name || !ts9.isComputedPropertyName(member3.name)) return true;
|
|
4148
|
+
return (checker.getTypeAtLocation(member3.name.expression).flags & (ts9.TypeFlags.StringLiteral | ts9.TypeFlags.NumberLiteral | ts9.TypeFlags.UniqueESSymbol)) !== 0;
|
|
3830
4149
|
}
|
|
3831
4150
|
|
|
3832
4151
|
// src/rules/_private-consumer-fix.ts
|
|
3833
|
-
import { AST_NODE_TYPES as
|
|
3834
|
-
import
|
|
3835
|
-
var UNSAFE =
|
|
4152
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES33 } from "@typescript-eslint/utils";
|
|
4153
|
+
import ts10 from "typescript";
|
|
4154
|
+
var UNSAFE = ts10.TypeFlags.Any | ts10.TypeFlags.Unknown | ts10.TypeFlags.Never | ts10.TypeFlags.TypeParameter | ts10.TypeFlags.Conditional | ts10.TypeFlags.IndexedAccess | ts10.TypeFlags.Substitution;
|
|
3836
4155
|
function validConsumerFixCalls(node, parameter, sourceCode, services) {
|
|
3837
4156
|
if (sourceCode.getAllComments().some((comment) => /@ts-(?:expect-error|ignore|nocheck)\b/u.test(comment.value))) return false;
|
|
3838
|
-
const owner = node.type ===
|
|
3839
|
-
if (owner.type !==
|
|
4157
|
+
const owner = node.type === AST_NODE_TYPES33.FunctionDeclaration ? node : node.parent;
|
|
4158
|
+
if (owner.type !== AST_NODE_TYPES33.FunctionDeclaration && owner.type !== AST_NODE_TYPES33.VariableDeclarator) return false;
|
|
3840
4159
|
const binding3 = sourceCode.getDeclaredVariables(owner).find((variable) => variable.defs.some((definition) => definition.node === owner && (definition.type === "FunctionName" || definition.type === "Variable")));
|
|
3841
4160
|
if (!binding3) return false;
|
|
3842
4161
|
const declaration = services.esTreeNodeToTSNodeMap.get(node);
|
|
3843
|
-
if (!
|
|
4162
|
+
if (!ts10.isFunctionDeclaration(declaration) && !ts10.isArrowFunction(declaration) || parameter.parent !== declaration || declaration.parameters.some((entry) => ts10.isIdentifier(entry.name) && entry.name.text === "this")) return false;
|
|
3844
4163
|
const selected = declaration.parameters.indexOf(parameter);
|
|
3845
4164
|
if (selected < 0) return false;
|
|
3846
4165
|
const checker = services.program.getTypeChecker();
|
|
@@ -3856,7 +4175,7 @@ function validConsumerFixCalls(node, parameter, sourceCode, services) {
|
|
|
3856
4175
|
const validArguments = (call) => {
|
|
3857
4176
|
if (declaration.parameters.length > 1) {
|
|
3858
4177
|
const nativeCall = services.esTreeNodeToTSNodeMap.get(call);
|
|
3859
|
-
if (!
|
|
4178
|
+
if (!ts10.isCallExpression(nativeCall) || checker.getResolvedSignature(nativeCall)?.declaration !== declaration) return false;
|
|
3860
4179
|
}
|
|
3861
4180
|
return call.arguments.every((argument, index) => {
|
|
3862
4181
|
const target = originals[index];
|
|
@@ -3872,7 +4191,7 @@ function validConsumerFixCalls(node, parameter, sourceCode, services) {
|
|
|
3872
4191
|
continue;
|
|
3873
4192
|
}
|
|
3874
4193
|
const call = reference.identifier.parent;
|
|
3875
|
-
if (reference.isTypeReference || !reference.isReadOnly() || call.type !==
|
|
4194
|
+
if (reference.isTypeReference || !reference.isReadOnly() || call.type !== AST_NODE_TYPES33.CallExpression || call.callee !== reference.identifier || call.optional || call.typeArguments || call.arguments.length !== declaration.parameters.length || !call.arguments.every((argument) => argument.type === AST_NODE_TYPES33.Identifier) || !validArguments(call)) return false;
|
|
3876
4195
|
calls += 1;
|
|
3877
4196
|
}
|
|
3878
4197
|
return calls > 0;
|
|
@@ -3923,250 +4242,6 @@ function minimalConsumerFix(sourceCode, annotation, removed) {
|
|
|
3923
4242
|
return sameLineTerminators(sourceCode, annotation, text) ? (fixer) => fixer.replaceText(annotation, text) : null;
|
|
3924
4243
|
}
|
|
3925
4244
|
|
|
3926
|
-
// src/rules/_private-scalar-consumer.ts
|
|
3927
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES33 } from "@typescript-eslint/utils";
|
|
3928
|
-
import ts10 from "typescript";
|
|
3929
|
-
|
|
3930
|
-
// src/rules/_scalar-parameter-view.ts
|
|
3931
|
-
import ts9 from "typescript";
|
|
3932
|
-
|
|
3933
|
-
// src/rules/_native-const-value.ts
|
|
3934
|
-
import ts8 from "typescript";
|
|
3935
|
-
function constInitializer(declaration) {
|
|
3936
|
-
if (!declaration || !ts8.isVariableDeclaration(declaration) || !ts8.isVariableDeclarationList(declaration.parent) || (declaration.parent.flags & ts8.NodeFlags.BlockScoped) !== ts8.NodeFlags.Const) return void 0;
|
|
3937
|
-
let initializer = declaration.initializer;
|
|
3938
|
-
while (initializer && ts8.isParenthesizedExpression(initializer)) initializer = initializer.expression;
|
|
3939
|
-
return initializer;
|
|
3940
|
-
}
|
|
3941
|
-
function unassertedValue(node) {
|
|
3942
|
-
let value = node;
|
|
3943
|
-
while (ts8.isParenthesizedExpression(value) || ts8.isAsExpression(value) || ts8.isTypeAssertionExpression(value) || ts8.isNonNullExpression(value) || ts8.isSatisfiesExpression(value)) value = value.expression;
|
|
3944
|
-
return value;
|
|
3945
|
-
}
|
|
3946
|
-
|
|
3947
|
-
// src/rules/_scalar-parameter-view.ts
|
|
3948
|
-
var SCALAR_OPERATORS = /* @__PURE__ */ new Set([
|
|
3949
|
-
ts9.SyntaxKind.PlusToken,
|
|
3950
|
-
ts9.SyntaxKind.MinusToken,
|
|
3951
|
-
ts9.SyntaxKind.AsteriskToken,
|
|
3952
|
-
ts9.SyntaxKind.SlashToken,
|
|
3953
|
-
ts9.SyntaxKind.PercentToken,
|
|
3954
|
-
ts9.SyntaxKind.AsteriskAsteriskToken,
|
|
3955
|
-
ts9.SyntaxKind.LessThanToken,
|
|
3956
|
-
ts9.SyntaxKind.LessThanEqualsToken,
|
|
3957
|
-
ts9.SyntaxKind.GreaterThanToken,
|
|
3958
|
-
ts9.SyntaxKind.GreaterThanEqualsToken,
|
|
3959
|
-
ts9.SyntaxKind.EqualsEqualsEqualsToken,
|
|
3960
|
-
ts9.SyntaxKind.ExclamationEqualsEqualsToken,
|
|
3961
|
-
ts9.SyntaxKind.EqualsEqualsToken,
|
|
3962
|
-
ts9.SyntaxKind.ExclamationEqualsToken,
|
|
3963
|
-
ts9.SyntaxKind.AmpersandAmpersandToken,
|
|
3964
|
-
ts9.SyntaxKind.BarBarToken,
|
|
3965
|
-
ts9.SyntaxKind.QuestionQuestionToken
|
|
3966
|
-
]);
|
|
3967
|
-
var SCALAR_PREFIXES = /* @__PURE__ */ new Set([ts9.SyntaxKind.PlusToken, ts9.SyntaxKind.MinusToken, ts9.SyntaxKind.ExclamationToken, ts9.SyntaxKind.TildeToken]);
|
|
3968
|
-
var RETURNED_OPERANDS = /* @__PURE__ */ new Set([ts9.SyntaxKind.AmpersandAmpersandToken, ts9.SyntaxKind.BarBarToken, ts9.SyntaxKind.QuestionQuestionToken]);
|
|
3969
|
-
function scalarParameterView(parameter, body3, checker) {
|
|
3970
|
-
return parameterReads(parameter, body3, checker, true);
|
|
3971
|
-
}
|
|
3972
|
-
function scalarParameterReads(parameter, body3, checker, callProgram, auxiliaries) {
|
|
3973
|
-
return parameterReads(parameter, body3, checker, false, callProgram, auxiliaries);
|
|
3974
|
-
}
|
|
3975
|
-
function parameterReads(parameter, body3, checker, jsx, callProgram, auxiliaries) {
|
|
3976
|
-
if (parameter.dotDotDotToken || parameter.initializer || ts9.isArrayBindingPattern(parameter.name)) return null;
|
|
3977
|
-
const root = ts9.isIdentifier(parameter.name) ? checker.getSymbolAtLocation(parameter.name) : void 0;
|
|
3978
|
-
if (ts9.isIdentifier(parameter.name) && !root) return null;
|
|
3979
|
-
const reads = /* @__PURE__ */ new Set();
|
|
3980
|
-
const aliases = parameterAliases(parameter.name, checker, reads);
|
|
3981
|
-
if (!aliases) return null;
|
|
3982
|
-
const expression = returnedExpression(body3);
|
|
3983
|
-
const view = { checker, props: checker.getTypeAtLocation(parameter), root, aliases, reads, callProgram, auxiliaries };
|
|
3984
|
-
return expression && scalarView(expression, view, jsx) ? reads : null;
|
|
3985
|
-
}
|
|
3986
|
-
function scalarType(type, allowUndefined = true) {
|
|
3987
|
-
if (type.isUnion()) return type.types.every((part) => scalarType(part, allowUndefined));
|
|
3988
|
-
const flags = ts9.TypeFlags.StringLike | ts9.TypeFlags.NumberLike | ts9.TypeFlags.BooleanLike | ts9.TypeFlags.BigIntLike | ts9.TypeFlags.Null;
|
|
3989
|
-
return (type.flags & (allowUndefined ? flags | ts9.TypeFlags.Undefined : flags)) !== 0;
|
|
3990
|
-
}
|
|
3991
|
-
function parameterAliases(name, checker, reads) {
|
|
3992
|
-
const aliases = /* @__PURE__ */ new Map();
|
|
3993
|
-
if (ts9.isIdentifier(name)) return aliases;
|
|
3994
|
-
for (const element of name.elements) {
|
|
3995
|
-
const key = element.propertyName ?? element.name;
|
|
3996
|
-
if (element.dotDotDotToken || element.initializer || !ts9.isIdentifier(element.name) || !ts9.isIdentifier(key) && !ts9.isStringLiteralLike(key) && !ts9.isNumericLiteral(key)) return null;
|
|
3997
|
-
const binding3 = checker.getSymbolAtLocation(element.name);
|
|
3998
|
-
if (!binding3) return null;
|
|
3999
|
-
reads.add(key.text);
|
|
4000
|
-
aliases.set(binding3, key.text);
|
|
4001
|
-
}
|
|
4002
|
-
return aliases;
|
|
4003
|
-
}
|
|
4004
|
-
function returnedExpression(body3) {
|
|
4005
|
-
if (!ts9.isBlock(body3)) return body3;
|
|
4006
|
-
const statement = body3.statements.length === 1 ? body3.statements[0] : void 0;
|
|
4007
|
-
return statement && ts9.isReturnStatement(statement) ? statement.expression : void 0;
|
|
4008
|
-
}
|
|
4009
|
-
function scalarView(node, view, jsx = false) {
|
|
4010
|
-
if (scalarLiteral(node)) return true;
|
|
4011
|
-
if (ts9.isCallExpression(node)) return !jsx && scalarCall(node, view);
|
|
4012
|
-
if (ts9.isJsxExpression(node)) return !node.dotDotDotToken && (!node.expression || scalarView(node.expression, view, jsx));
|
|
4013
|
-
if (ts9.isIdentifier(node)) {
|
|
4014
|
-
const binding3 = view.checker.getSymbolAtLocation(node);
|
|
4015
|
-
if (binding3 && view.auxiliaries?.has(binding3)) return scalarType(view.checker.getTypeAtLocation(node));
|
|
4016
|
-
const key = binding3 && view.aliases.get(binding3);
|
|
4017
|
-
return key !== void 0 && readField(node, key, view);
|
|
4018
|
-
}
|
|
4019
|
-
if (ts9.isPropertyAccessExpression(node) || ts9.isElementAccessExpression(node)) return memberRead(node, view);
|
|
4020
|
-
return scalarOperation(node, view, jsx);
|
|
4021
|
-
}
|
|
4022
|
-
function scalarOperation(node, view, jsx) {
|
|
4023
|
-
if (ts9.isParenthesizedExpression(node) || ts9.isNonNullExpression(node)) return scalarView(node.expression, view, jsx);
|
|
4024
|
-
if (ts9.isTypeOfExpression(node)) return scalarView(node.expression, view);
|
|
4025
|
-
if (ts9.isConditionalExpression(node)) return scalarView(node.condition, view) && scalarView(node.whenTrue, view, jsx) && scalarView(node.whenFalse, view, jsx);
|
|
4026
|
-
if (ts9.isBinaryExpression(node)) return binaryView(node, view, jsx);
|
|
4027
|
-
if (ts9.isPrefixUnaryExpression(node)) return SCALAR_PREFIXES.has(node.operator) && scalarView(node.operand, view);
|
|
4028
|
-
if (ts9.isTemplateExpression(node)) return node.templateSpans.every((span) => scalarView(span.expression, view));
|
|
4029
|
-
return jsx && jsxView(node, view);
|
|
4030
|
-
}
|
|
4031
|
-
function scalarCall(node, view) {
|
|
4032
|
-
if (!view.callProgram || node.questionDotToken || node.typeArguments?.length || !ts9.isIdentifier(node.expression) || !node.arguments.length || node.arguments.some(ts9.isSpreadElement)) return false;
|
|
4033
|
-
const declarations = view.checker.getSymbolAtLocation(node.expression)?.declarations;
|
|
4034
|
-
const declaration = declarations?.length === 1 ? declarations[0] : void 0;
|
|
4035
|
-
const helper = declaration && localHelper(declaration);
|
|
4036
|
-
if (!helper || helper.getSourceFile() !== node.getSourceFile() || helper.typeParameters?.length || !helper.type || !node.arguments.every((argument) => scalarView(argument, view))) return false;
|
|
4037
|
-
if (!checkedNativeSource(view.callProgram, node.getSourceFile())) return false;
|
|
4038
|
-
const signature = view.checker.getResolvedSignature(node);
|
|
4039
|
-
return signature?.declaration === helper && !view.checker.getTypePredicateOfSignature(signature) && scalarType(view.checker.getTypeAtLocation(node));
|
|
4040
|
-
}
|
|
4041
|
-
function localHelper(node) {
|
|
4042
|
-
if (ts9.isFunctionDeclaration(node)) return node.body && ts9.isSourceFile(node.parent) ? node : void 0;
|
|
4043
|
-
if (!ts9.isVariableDeclaration(node) || node.type || !node.initializer || constInitializer(node) !== node.initializer || !ts9.isArrowFunction(node.initializer) || !ts9.isVariableStatement(node.parent.parent) || !ts9.isSourceFile(node.parent.parent.parent)) return void 0;
|
|
4044
|
-
return node.initializer;
|
|
4045
|
-
}
|
|
4046
|
-
function binaryView(node, view, jsx) {
|
|
4047
|
-
const returned2 = jsx && RETURNED_OPERANDS.has(node.operatorToken.kind);
|
|
4048
|
-
return SCALAR_OPERATORS.has(node.operatorToken.kind) && scalarView(node.left, view, returned2) && scalarView(node.right, view, returned2);
|
|
4049
|
-
}
|
|
4050
|
-
function scalarLiteral(node) {
|
|
4051
|
-
return ts9.isStringLiteralLike(node) || ts9.isNumericLiteral(node) || ts9.isBigIntLiteral(node) || ts9.isJsxText(node) || node.kind === ts9.SyntaxKind.TrueKeyword || node.kind === ts9.SyntaxKind.FalseKeyword || node.kind === ts9.SyntaxKind.NullKeyword;
|
|
4052
|
-
}
|
|
4053
|
-
function memberRead(node, view) {
|
|
4054
|
-
if (!view.root || !ts9.isIdentifier(node.expression) || view.checker.getSymbolAtLocation(node.expression) !== view.root) return false;
|
|
4055
|
-
const key = ts9.isPropertyAccessExpression(node) ? node.name.text : node.argumentExpression && (ts9.isStringLiteralLike(node.argumentExpression) || ts9.isNumericLiteral(node.argumentExpression)) ? node.argumentExpression.text : void 0;
|
|
4056
|
-
return key !== void 0 && readField(node, key, view);
|
|
4057
|
-
}
|
|
4058
|
-
function readField(node, key, view) {
|
|
4059
|
-
if (!view.checker.getPropertyOfType(view.props, key) || !scalarType(view.checker.getTypeAtLocation(node))) return false;
|
|
4060
|
-
view.reads.add(key);
|
|
4061
|
-
return true;
|
|
4062
|
-
}
|
|
4063
|
-
function jsxView(node, view) {
|
|
4064
|
-
if (ts9.isJsxFragment(node)) return node.children.every((child) => scalarView(child, view, true));
|
|
4065
|
-
if (ts9.isJsxElement(node)) return jsxView(node.openingElement, view) && node.children.every((child) => scalarView(child, view, true));
|
|
4066
|
-
if (!ts9.isJsxOpeningElement(node) && !ts9.isJsxSelfClosingElement(node)) return false;
|
|
4067
|
-
if (!ts9.isIdentifier(node.tagName) || !/^[a-z][A-Za-z0-9]*$/u.test(node.tagName.text)) return false;
|
|
4068
|
-
return node.attributes.properties.every((attribute) => intrinsicAttribute(attribute, view));
|
|
4069
|
-
}
|
|
4070
|
-
function intrinsicAttribute(attribute, view) {
|
|
4071
|
-
return ts9.isJsxAttribute(attribute) && ts9.isIdentifier(attribute.name) && attribute.name.text !== "is" && (!attribute.initializer || scalarView(attribute.initializer, view));
|
|
4072
|
-
}
|
|
4073
|
-
|
|
4074
|
-
// src/rules/_private-scalar-consumer.ts
|
|
4075
|
-
function directEval(node) {
|
|
4076
|
-
let callee = unwrapExpression(node.callee);
|
|
4077
|
-
while (callee.type === AST_NODE_TYPES33.TSInstantiationExpression) callee = unwrapExpression(callee.expression);
|
|
4078
|
-
return callee.type === AST_NODE_TYPES33.Identifier && callee.name === "eval";
|
|
4079
|
-
}
|
|
4080
|
-
function primitiveKeyword(node) {
|
|
4081
|
-
return node !== void 0 && (node.kind === ts10.SyntaxKind.StringKeyword || node.kind === ts10.SyntaxKind.NumberKeyword || node.kind === ts10.SyntaxKind.BooleanKeyword || node.kind === ts10.SyntaxKind.BigIntKeyword);
|
|
4082
|
-
}
|
|
4083
|
-
function nullishPrimitiveUnion(node) {
|
|
4084
|
-
return node !== void 0 && ts10.isUnionTypeNode(node) && node.types.length === 2 && node.types.some(primitiveKeyword) && node.types.some((part) => part.kind === ts10.SyntaxKind.UndefinedKeyword || ts10.isLiteralTypeNode(part) && part.literal.kind === ts10.SyntaxKind.NullKeyword);
|
|
4085
|
-
}
|
|
4086
|
-
function consumerAnnotation(node, auxiliaryScalars = false) {
|
|
4087
|
-
if (node.params.length !== 1) {
|
|
4088
|
-
if (!auxiliaryScalars) return void 0;
|
|
4089
|
-
let annotation;
|
|
4090
|
-
for (const parameter2 of node.params) {
|
|
4091
|
-
if (parameter2.type !== AST_NODE_TYPES33.Identifier && parameter2.type !== AST_NODE_TYPES33.ObjectPattern) continue;
|
|
4092
|
-
const current = parameter2.typeAnnotation?.typeAnnotation;
|
|
4093
|
-
if (current?.type !== AST_NODE_TYPES33.TSTypeLiteral) continue;
|
|
4094
|
-
if (annotation) return void 0;
|
|
4095
|
-
annotation = current;
|
|
4096
|
-
}
|
|
4097
|
-
return annotation;
|
|
4098
|
-
}
|
|
4099
|
-
const parameter = node.params[0];
|
|
4100
|
-
return parameter?.type === AST_NODE_TYPES33.Identifier || parameter?.type === AST_NODE_TYPES33.ObjectPattern ? parameter.typeAnnotation?.typeAnnotation : void 0;
|
|
4101
|
-
}
|
|
4102
|
-
function exportedSymbols(source, checker) {
|
|
4103
|
-
const symbol = checker.getSymbolAtLocation(source);
|
|
4104
|
-
return new Set(symbol ? checker.getExportsOfModule(symbol).map((entry) => (entry.flags & ts10.SymbolFlags.Alias) !== 0 ? checker.getAliasedSymbol(entry) : entry) : []);
|
|
4105
|
-
}
|
|
4106
|
-
function privateScalarConsumer(node, sourceCode, services, exports, options = {}) {
|
|
4107
|
-
const native = services.esTreeNodeToTSNodeMap.get(node);
|
|
4108
|
-
if (!ts10.isFunctionDeclaration(native) && !ts10.isArrowFunction(native) || !native.body) return null;
|
|
4109
|
-
let parameter = native.parameters[0];
|
|
4110
|
-
if (native.parameters.length !== 1) {
|
|
4111
|
-
const annotation = consumerAnnotation(node, options.auxiliaryScalars);
|
|
4112
|
-
const selected = annotation && services.esTreeNodeToTSNodeMap.get(annotation);
|
|
4113
|
-
parameter = native.parameters.find((entry) => entry.type === selected);
|
|
4114
|
-
}
|
|
4115
|
-
if (!parameter || !independentSignature(native, parameter, options.auxiliaryScalars === true)) return null;
|
|
4116
|
-
const checker = services.program.getTypeChecker();
|
|
4117
|
-
if (!ts10.isExternalModule(native.getSourceFile()) || !services.program.getCompilerOptions().strict) return null;
|
|
4118
|
-
if (!privateDirectCallable(node, native, sourceCode, checker, exports)) return null;
|
|
4119
|
-
const signature = checker.getSignatureFromDeclaration(native);
|
|
4120
|
-
if (!signature || signature.typeParameters?.length || checker.getTypePredicateOfSignature(signature)) return null;
|
|
4121
|
-
const expression = returnedExpression(native.body);
|
|
4122
|
-
if (!expression || !checker.isTypeAssignableTo(checker.getTypeAtLocation(expression), checker.getReturnTypeOfSignature(signature))) return null;
|
|
4123
|
-
const auxiliaries = native.parameters.length > 1 ? auxiliaryBindings(native, parameter, checker) : void 0;
|
|
4124
|
-
if (auxiliaries === null) return null;
|
|
4125
|
-
const reads = scalarParameterReads(parameter, native.body, checker, options.scalarCalls ? services.program : void 0, auxiliaries);
|
|
4126
|
-
return reads?.size ? { parameter, reads } : null;
|
|
4127
|
-
}
|
|
4128
|
-
function privateDirectCallable(node, native, sourceCode, checker, exports) {
|
|
4129
|
-
const binding3 = callableBinding(node, sourceCode);
|
|
4130
|
-
if (!binding3 || binding3.defs.length !== 1) return false;
|
|
4131
|
-
const name = ts10.isFunctionDeclaration(native) ? native.name : ts10.isVariableDeclaration(native.parent) ? native.parent.name : void 0;
|
|
4132
|
-
const symbol = name && checker.getSymbolAtLocation(name);
|
|
4133
|
-
return symbol !== void 0 && symbol.declarations?.length === 1 && !exports.has(symbol) && directCalls(binding3, native.parameters.length);
|
|
4134
|
-
}
|
|
4135
|
-
function independentSignature(native, selected, auxiliaryScalars) {
|
|
4136
|
-
if (!auxiliaryScalars && native.parameters.length !== 1 || native.typeParameters?.length || native.asteriskToken || native.modifiers?.length || !primitiveKeyword(native.type)) return false;
|
|
4137
|
-
return native.parameters.every((parameter) => parameter.type !== void 0 && !parameter.modifiers?.length && !parameter.questionToken && !parameter.initializer && !parameter.dotDotDotToken && (!ts10.isIdentifier(parameter.name) || parameter.name.text !== "this") && (parameter === selected || ts10.isIdentifier(parameter.name) && primitiveKeyword(parameter.type)));
|
|
4138
|
-
}
|
|
4139
|
-
function auxiliaryBindings(native, selected, checker) {
|
|
4140
|
-
const bindings = /* @__PURE__ */ new Set();
|
|
4141
|
-
for (const parameter of native.parameters) {
|
|
4142
|
-
if (parameter === selected) continue;
|
|
4143
|
-
const symbol = ts10.isIdentifier(parameter.name) ? checker.getSymbolAtLocation(parameter.name) : void 0;
|
|
4144
|
-
if (!symbol || symbol.declarations?.length !== 1 || symbol.declarations[0] !== parameter || bindings.has(symbol)) return null;
|
|
4145
|
-
bindings.add(symbol);
|
|
4146
|
-
}
|
|
4147
|
-
return bindings;
|
|
4148
|
-
}
|
|
4149
|
-
function callableBinding(node, sourceCode) {
|
|
4150
|
-
if (node.type === AST_NODE_TYPES33.FunctionDeclaration) {
|
|
4151
|
-
if (node.parent.type !== AST_NODE_TYPES33.Program) return void 0;
|
|
4152
|
-
return sourceCode.getDeclaredVariables(node).find((variable) => variable.defs.some((definition) => definition.type === "FunctionName" && definition.node === node));
|
|
4153
|
-
}
|
|
4154
|
-
const declaration = node.parent;
|
|
4155
|
-
if (declaration.type !== AST_NODE_TYPES33.VariableDeclarator || declaration.init !== node || declaration.id.type !== AST_NODE_TYPES33.Identifier || declaration.id.typeAnnotation || declaration.parent.kind !== "const" || declaration.parent.parent.type !== AST_NODE_TYPES33.Program) return void 0;
|
|
4156
|
-
return sourceCode.getDeclaredVariables(declaration).find((variable) => variable.defs.some((definition) => definition.type === "Variable" && definition.node === declaration));
|
|
4157
|
-
}
|
|
4158
|
-
function directCalls(binding3, arity) {
|
|
4159
|
-
let calls = 0;
|
|
4160
|
-
const stable2 = stableValueBinding(binding3, (reference) => {
|
|
4161
|
-
const identifier = reference.identifier;
|
|
4162
|
-
const call = identifier.parent;
|
|
4163
|
-
if (reference.isTypeReference || !reference.isReadOnly() || call.type !== AST_NODE_TYPES33.CallExpression || call.callee !== identifier || call.optional || call.typeArguments || call.arguments.length !== arity || !call.arguments.every((argument) => argument.type === AST_NODE_TYPES33.Identifier)) return false;
|
|
4164
|
-
calls += 1;
|
|
4165
|
-
return true;
|
|
4166
|
-
});
|
|
4167
|
-
return stable2 && calls > 0;
|
|
4168
|
-
}
|
|
4169
|
-
|
|
4170
4245
|
// src/rules/no-redundant-consumer-union.ts
|
|
4171
4246
|
var CONFIG3 = { path: "tsconfig.json", source: '{"compilerOptions":{"strict":true,"target":"ESNext","module":"ESNext","moduleResolution":"Bundler"}}' };
|
|
4172
4247
|
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);';
|
|
@@ -5494,7 +5569,7 @@ function isSearchParamReceiver(call, services) {
|
|
|
5494
5569
|
// package.json
|
|
5495
5570
|
var package_default = {
|
|
5496
5571
|
name: "@sarj/eslint-plugin",
|
|
5497
|
-
version: "18.0.
|
|
5572
|
+
version: "18.0.5",
|
|
5498
5573
|
packageManager: "npm@12.2.1",
|
|
5499
5574
|
description: "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
|
|
5500
5575
|
type: "module",
|
|
@@ -28689,7 +28764,7 @@ import {
|
|
|
28689
28764
|
AST_NODE_TYPES as AST_NODE_TYPES148,
|
|
28690
28765
|
ASTUtils as ASTUtils96
|
|
28691
28766
|
} from "@typescript-eslint/utils";
|
|
28692
|
-
var
|
|
28767
|
+
var PRIMITIVE_TYPES2 = /* @__PURE__ */ new Set([
|
|
28693
28768
|
"TSStringKeyword",
|
|
28694
28769
|
"TSNumberKeyword",
|
|
28695
28770
|
"TSBooleanKeyword",
|
|
@@ -28746,7 +28821,7 @@ function tokenSignature(sourceCode, node) {
|
|
|
28746
28821
|
);
|
|
28747
28822
|
}
|
|
28748
28823
|
function closedType(node) {
|
|
28749
|
-
if (
|
|
28824
|
+
if (PRIMITIVE_TYPES2.has(node.type)) return true;
|
|
28750
28825
|
switch (node.type) {
|
|
28751
28826
|
case AST_NODE_TYPES148.TSLiteralType:
|
|
28752
28827
|
return node.literal.type === AST_NODE_TYPES148.Literal || node.literal.type === AST_NODE_TYPES148.UnaryExpression && node.literal.operator === "-" && node.literal.argument.type === AST_NODE_TYPES148.Literal;
|
|
@@ -30737,8 +30812,8 @@ var memberValidationPolarity = (test, access) => {
|
|
|
30737
30812
|
}
|
|
30738
30813
|
if (test.type === AST_NODE_TYPES157.BinaryExpression) {
|
|
30739
30814
|
const isMatchingTypeof = (node) => node.type === AST_NODE_TYPES157.UnaryExpression && node.operator === "typeof" && isSamePlainMember(node.argument, access);
|
|
30740
|
-
const
|
|
30741
|
-
if (!(isMatchingTypeof(test.left) &&
|
|
30815
|
+
const isPrimitiveType2 = (node) => node.type === AST_NODE_TYPES157.Literal && typeof node.value === "string" && PRIMITIVE_TYPEOF_RESULTS.has(node.value);
|
|
30816
|
+
if (!(isMatchingTypeof(test.left) && isPrimitiveType2(test.right) || isMatchingTypeof(test.right) && isPrimitiveType2(test.left))) {
|
|
30742
30817
|
return null;
|
|
30743
30818
|
}
|
|
30744
30819
|
if (test.operator === "===" || test.operator === "==") {
|