@sarj/eslint-plugin 16.38.55 → 16.39.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{_docs-IZjowAEc.d.cts → _docs-_eXGTNOq.d.cts} +1 -1
- package/dist/{_docs-IZjowAEc.d.ts → _docs-_eXGTNOq.d.ts} +1 -1
- package/dist/index.cjs +570 -471
- package/dist/index.d.cts +34 -215
- package/dist/index.d.ts +34 -215
- package/dist/index.js +555 -456
- package/dist/rule-examples.cjs +6 -3
- package/dist/rule-examples.d.cts +5 -1
- package/dist/rule-examples.d.ts +5 -1
- package/dist/rule-examples.js +6 -3
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1763,32 +1763,215 @@ var no_generic_json_parser_default = createRule({
|
|
|
1763
1763
|
});
|
|
1764
1764
|
|
|
1765
1765
|
// src/rules/no-redundant-local-alias.ts
|
|
1766
|
-
import { AST_NODE_TYPES as
|
|
1766
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES19, ASTUtils as ASTUtils15 } from "@typescript-eslint/utils";
|
|
1767
|
+
|
|
1768
|
+
// src/rules/_unused-private-binding.ts
|
|
1769
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES18 } from "@typescript-eslint/utils";
|
|
1770
|
+
|
|
1771
|
+
// src/rules/_type-binding.ts
|
|
1772
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES17 } from "@typescript-eslint/utils";
|
|
1773
|
+
function typeBinding(source, identifier) {
|
|
1774
|
+
let scope = source.getScope(identifier);
|
|
1775
|
+
while (scope !== null) {
|
|
1776
|
+
const variable = scope.set.get(identifier.name);
|
|
1777
|
+
if (variable !== void 0 && (variable.isTypeVariable || variable.defs.some((definition) => definition.isTypeDefinition))) {
|
|
1778
|
+
return variable;
|
|
1779
|
+
}
|
|
1780
|
+
scope = scope.upper;
|
|
1781
|
+
}
|
|
1782
|
+
return null;
|
|
1783
|
+
}
|
|
1784
|
+
var REFERENCE_INDEXES = /* @__PURE__ */ new WeakMap();
|
|
1785
|
+
function retainsNamedTypeUses(source, removed) {
|
|
1786
|
+
const manager = source.scopeManager;
|
|
1787
|
+
if (manager === null) return false;
|
|
1788
|
+
const index = referenceIndex(source, manager);
|
|
1789
|
+
for (const reference of referencesWithin(index.references, removed)) {
|
|
1790
|
+
if (!reference.isRead()) continue;
|
|
1791
|
+
const binding3 = reference.resolved;
|
|
1792
|
+
if (!binding3 || !reference.isTypeReference && !reference.isValueReference) return false;
|
|
1793
|
+
if (binding3.defs.length === 0) continue;
|
|
1794
|
+
const reads = publicReadExtents(index, binding3);
|
|
1795
|
+
const extent = reference.isTypeReference ? reference.isValueReference ? reads.both : reads.type : reads.value;
|
|
1796
|
+
if (extent === null || extent.minStart >= removed.range[0] && extent.maxEnd <= removed.range[1]) return false;
|
|
1797
|
+
}
|
|
1798
|
+
return true;
|
|
1799
|
+
}
|
|
1800
|
+
function referenceIndex(source, manager) {
|
|
1801
|
+
const cached = REFERENCE_INDEXES.get(source);
|
|
1802
|
+
if (cached?.manager === manager) return cached;
|
|
1803
|
+
const references = manager.scopes.flatMap((scope) => scope.references);
|
|
1804
|
+
references.sort((left, right) => left.identifier.range[0] - right.identifier.range[0]);
|
|
1805
|
+
const index = { manager, references, publicReads: /* @__PURE__ */ new Map() };
|
|
1806
|
+
REFERENCE_INDEXES.set(source, index);
|
|
1807
|
+
return index;
|
|
1808
|
+
}
|
|
1809
|
+
function* referencesWithin(references, removed) {
|
|
1810
|
+
let low = 0;
|
|
1811
|
+
let high = references.length;
|
|
1812
|
+
while (low < high) {
|
|
1813
|
+
const middle = low + Math.floor((high - low) / 2);
|
|
1814
|
+
const reference = references[middle];
|
|
1815
|
+
if (reference === void 0 || reference.identifier.range[0] >= removed.range[0]) high = middle;
|
|
1816
|
+
else low = middle + 1;
|
|
1817
|
+
}
|
|
1818
|
+
for (let index = low; index < references.length; index++) {
|
|
1819
|
+
const reference = references[index];
|
|
1820
|
+
if (reference === void 0) continue;
|
|
1821
|
+
if (reference.identifier.range[0] > removed.range[1]) break;
|
|
1822
|
+
if (insideTypeRange(reference.identifier, removed)) yield reference;
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
function publicReadExtents(index, binding3) {
|
|
1826
|
+
const cached = index.publicReads.get(binding3);
|
|
1827
|
+
if (cached !== void 0) return cached;
|
|
1828
|
+
let type = null;
|
|
1829
|
+
let value = null;
|
|
1830
|
+
let both = null;
|
|
1831
|
+
for (const retained of binding3.references) {
|
|
1832
|
+
if (!retained.isRead() || !retained.isTypeReference && !retained.isValueReference || binding3.defs.some((definition) => insideTypeRange(retained.identifier, definition.node)) || !publicTypeUse(retained.identifier)) continue;
|
|
1833
|
+
if (retained.isTypeReference) type = extendExtent(type, retained.identifier);
|
|
1834
|
+
if (retained.isValueReference) value = extendExtent(value, retained.identifier);
|
|
1835
|
+
if (retained.isTypeReference && retained.isValueReference) both = extendExtent(both, retained.identifier);
|
|
1836
|
+
}
|
|
1837
|
+
const result = { type, value, both };
|
|
1838
|
+
index.publicReads.set(binding3, result);
|
|
1839
|
+
return result;
|
|
1840
|
+
}
|
|
1841
|
+
function extendExtent(extent, identifier) {
|
|
1842
|
+
return {
|
|
1843
|
+
minStart: Math.min(extent?.minStart ?? identifier.range[0], identifier.range[0]),
|
|
1844
|
+
maxEnd: Math.max(extent?.maxEnd ?? identifier.range[1], identifier.range[1])
|
|
1845
|
+
};
|
|
1846
|
+
}
|
|
1847
|
+
function publicTypeUse(identifier) {
|
|
1848
|
+
let node = identifier;
|
|
1849
|
+
while (node.parent) {
|
|
1850
|
+
if (node.type === AST_NODE_TYPES17.TSTypeAnnotation || node.type === AST_NODE_TYPES17.TSTypePredicate || node.type === AST_NODE_TYPES17.TSAsExpression || node.type === AST_NODE_TYPES17.TSTypeAssertion) return false;
|
|
1851
|
+
if (node.type === AST_NODE_TYPES17.TSTypeAliasDeclaration) {
|
|
1852
|
+
return node.parent.type === AST_NODE_TYPES17.ExportNamedDeclaration && node.parent.declaration === node && node.parent.parent.type === AST_NODE_TYPES17.Program;
|
|
1853
|
+
}
|
|
1854
|
+
if (node.type === AST_NODE_TYPES17.ExportSpecifier) {
|
|
1855
|
+
return node.parent.type === AST_NODE_TYPES17.ExportNamedDeclaration && node.parent.source === null && node.parent.parent.type === AST_NODE_TYPES17.Program;
|
|
1856
|
+
}
|
|
1857
|
+
node = node.parent;
|
|
1858
|
+
}
|
|
1859
|
+
return false;
|
|
1860
|
+
}
|
|
1861
|
+
function insideTypeRange(node, range) {
|
|
1862
|
+
return node.range[0] >= range.range[0] && node.range[1] <= range.range[1];
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
// src/rules/_unused-private-binding.ts
|
|
1866
|
+
function isUnusedPrivateBinding(sourceCode, declaration, identifier, filename, allowedDeclarations = [declaration]) {
|
|
1867
|
+
if (/\.d\.[cm]?ts$/u.test(filename)) return false;
|
|
1868
|
+
const bindings = sourceCode.getDeclaredVariables(declaration).filter((binding3) => binding3.name === identifier.name);
|
|
1869
|
+
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;
|
|
1870
|
+
if (hasIdentifierNamed(sourceCode.ast, "eval")) return false;
|
|
1871
|
+
const statement = declaration.type === AST_NODE_TYPES18.VariableDeclarator ? declaration.parent : declaration;
|
|
1872
|
+
if (statement.parent.type === AST_NODE_TYPES18.ExportNamedDeclaration || statement.parent.type === AST_NODE_TYPES18.ExportDefaultDeclaration) return false;
|
|
1873
|
+
if (statement.parent.type !== AST_NODE_TYPES18.Program) return statement.parent.type === AST_NODE_TYPES18.BlockStatement;
|
|
1874
|
+
return sourceCode.ast.body.some((node) => node.type === AST_NODE_TYPES18.ImportDeclaration || node.type === AST_NODE_TYPES18.ExportNamedDeclaration || node.type === AST_NODE_TYPES18.ExportDefaultDeclaration || node.type === AST_NODE_TYPES18.ExportAllDeclaration);
|
|
1875
|
+
}
|
|
1876
|
+
function hasOnlyDirectFactoryUses(variable) {
|
|
1877
|
+
return variable.references.every((reference) => {
|
|
1878
|
+
if (reference.isTypeReference && !reference.isValueReference) return true;
|
|
1879
|
+
const identifier = reference.identifier;
|
|
1880
|
+
const parent = identifier.parent;
|
|
1881
|
+
if (parent.type === AST_NODE_TYPES18.CallExpression && parent.callee === identifier) return true;
|
|
1882
|
+
return parent.type === AST_NODE_TYPES18.MemberExpression && parent.object === identifier && !parent.computed && parent.parent.type === AST_NODE_TYPES18.CallExpression && parent.parent.callee === parent;
|
|
1883
|
+
});
|
|
1884
|
+
}
|
|
1885
|
+
var IDENTIFIER_NAMES = /* @__PURE__ */ new WeakMap();
|
|
1886
|
+
function hasIdentifierNamed(node, name) {
|
|
1887
|
+
let names = IDENTIFIER_NAMES.get(node);
|
|
1888
|
+
if (names === void 0) {
|
|
1889
|
+
const collected = /* @__PURE__ */ new Set();
|
|
1890
|
+
const pending = [node];
|
|
1891
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
1892
|
+
while (pending.length > 0) {
|
|
1893
|
+
const current = pending.pop();
|
|
1894
|
+
if (current === void 0 || seen.has(current)) continue;
|
|
1895
|
+
seen.add(current);
|
|
1896
|
+
if (current.type === AST_NODE_TYPES18.Identifier || current.type === AST_NODE_TYPES18.JSXIdentifier) collected.add(current.name);
|
|
1897
|
+
forEachOwnAstChild(current, (child) => {
|
|
1898
|
+
pending.push(child);
|
|
1899
|
+
}, (key) => key !== "tokens" && key !== "comments");
|
|
1900
|
+
}
|
|
1901
|
+
names = collected;
|
|
1902
|
+
IDENTIFIER_NAMES.set(node, names);
|
|
1903
|
+
}
|
|
1904
|
+
return names.has(name);
|
|
1905
|
+
}
|
|
1906
|
+
function privatePredicateBooleanFix(sourceCode, node, annotation, filename) {
|
|
1907
|
+
if (!annotation.typeAnnotation || !retainsNamedTypeUses(sourceCode, annotation.typeAnnotation) || node.type !== AST_NODE_TYPES18.FunctionDeclaration || node.id === null || !isUnusedPrivateBinding(sourceCode, node, node.id, filename) || sourceCode.getCommentsInside(annotation).length > 0) return null;
|
|
1908
|
+
const text = `boolean${sourceCode.getText(annotation).replace(/[^\r\n\u2028\u2029]/gu, "")}`;
|
|
1909
|
+
const neighbor = Math.max(0, annotation.range[0] - 1);
|
|
1910
|
+
const before = sourceCode.text.slice(neighbor, annotation.range[1] + 1).match(/\r\n|[\r\n\u2028\u2029]/gu) ?? [];
|
|
1911
|
+
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) ?? [];
|
|
1912
|
+
if (before.length !== after.length || before.some((ending, index) => ending !== after[index])) return null;
|
|
1913
|
+
return (fixer) => fixer.replaceText(annotation, text);
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
// src/rules/no-redundant-local-alias.ts
|
|
1767
1917
|
var NO_REDUNDANT_LOCAL_ALIAS_DOCUMENTATION = {
|
|
1768
1918
|
defaultLevel: "warning",
|
|
1769
1919
|
summary: "Pass the original local into an object field instead of creating a single-use rename.",
|
|
1770
1920
|
rationale: "An unannotated alias used only by its matching object field adds a second name without adding a contract.",
|
|
1771
1921
|
remediation: "Write the object property with the original binding, then remove the redundant alias. Keep annotations, captured snapshots and independently useful names.",
|
|
1772
1922
|
category: "maintainability",
|
|
1923
|
+
autofix: "safe",
|
|
1773
1924
|
limitations: [
|
|
1774
1925
|
"Checks an unannotated local const alias of a stable parameter or earlier const. Its single read must be a shorthand property in the same function scope. Module exports, imported bindings, captures, reassignment, positional uses and typed aliases are preserved.",
|
|
1775
|
-
"
|
|
1926
|
+
"Safe fixes are limited to a plain module-scope function with one explicitly intrinsic-primitive parameter and exactly a const alias followed by a returned object containing that sole shorthand field. The source binding must remain the same at the returned field. Generics, return annotations, optional/default parameters, destructuring, overloads, comments, eval, async/generator functions and the special __proto__ key remain manual. Other diagnostics require review."
|
|
1776
1927
|
],
|
|
1777
1928
|
examples: [
|
|
1778
1929
|
{ id: "redundant-alias", title: "The property already supplies the name", outcome: "match", files: [{ path: "src/request.ts", source: "function request(value: string) { const accountId = value; return { accountId }; }" }], focusPath: "src/request.ts", expectedCount: 1, public: true },
|
|
1779
|
-
{ id: "direct-property", title: "Use the original binding", outcome: "no-match", files: [{ path: "src/request.ts", source: "function request(value: string) { return { accountId: value }; }" }], focusPath: "src/request.ts", expectedCount: 0, public: true }
|
|
1930
|
+
{ id: "direct-property", title: "Use the original binding", outcome: "no-match", files: [{ path: "src/request.ts", source: "function request(value: string) { return { accountId: value }; }" }], focusPath: "src/request.ts", expectedCount: 0, public: true },
|
|
1931
|
+
{ id: "closed-primitive-parameter-alias", scenarioId: "closed-primitive-parameter-alias", title: "The closed primitive return preserves the data-field contract", outcome: "match", files: [{ path: "src/request.ts", source: "export {};\nfunction request(value: string) {\n const accountId = value;\n return { accountId };\n}\n" }], fixedFiles: [{ path: "src/request.ts", source: "export {};\nfunction request(value: string) {\n\n return { accountId: value };\n}\n" }], focusPath: "src/request.ts", expectedCount: 1, public: true },
|
|
1932
|
+
{ id: "closed-primitive-parameter-alias-fixed", scenarioId: "closed-primitive-parameter-alias", title: "The direct data field needs no local alias", outcome: "no-match", files: [{ path: "src/request.ts", source: "export {};\nfunction request(value: string) {\n\n return { accountId: value };\n}\n" }], focusPath: "src/request.ts", expectedCount: 0, public: true }
|
|
1780
1933
|
]
|
|
1781
1934
|
};
|
|
1782
1935
|
function stableSource(variable, alias) {
|
|
1783
1936
|
const definition = variable.defs[0];
|
|
1784
1937
|
if (variable.defs.length !== 1 || definition === void 0 || variable.references.some((reference) => reference.isWrite() && !reference.init)) return false;
|
|
1785
|
-
return definition.type === "Parameter" || definition.node.type ===
|
|
1938
|
+
return definition.type === "Parameter" || definition.node.type === AST_NODE_TYPES19.VariableDeclarator && definition.node.parent.kind === "const" && definition.node.init !== null && definition.node.range[1] < alias.range[0];
|
|
1939
|
+
}
|
|
1940
|
+
var PRIMITIVE_PARAMETERS = /* @__PURE__ */ new Set([
|
|
1941
|
+
AST_NODE_TYPES19.TSStringKeyword,
|
|
1942
|
+
AST_NODE_TYPES19.TSNumberKeyword,
|
|
1943
|
+
AST_NODE_TYPES19.TSBooleanKeyword,
|
|
1944
|
+
AST_NODE_TYPES19.TSBigIntKeyword,
|
|
1945
|
+
AST_NODE_TYPES19.TSSymbolKeyword
|
|
1946
|
+
]);
|
|
1947
|
+
function closedPrimitiveReturnFix(sourceCode, node, property, source, target) {
|
|
1948
|
+
const statement = node.parent;
|
|
1949
|
+
const body3 = statement.parent;
|
|
1950
|
+
if (body3.type !== AST_NODE_TYPES19.BlockStatement) return null;
|
|
1951
|
+
const owner = body3.parent;
|
|
1952
|
+
if (owner.type !== AST_NODE_TYPES19.FunctionDeclaration || owner.parent.type !== AST_NODE_TYPES19.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_TYPES19.Identifier || node.id.name === "__proto__" || node.init?.type !== AST_NODE_TYPES19.Identifier || sourceCode.getCommentsInside(owner).length !== 0 || hasIdentifierNamed(sourceCode.ast, "eval")) return null;
|
|
1953
|
+
const parameter = owner.params[0];
|
|
1954
|
+
const returned2 = body3.body[1];
|
|
1955
|
+
if (parameter?.type !== AST_NODE_TYPES19.Identifier || parameter.optional === true || parameter.typeAnnotation === void 0 || !PRIMITIVE_PARAMETERS.has(parameter.typeAnnotation.typeAnnotation.type) || returned2?.type !== AST_NODE_TYPES19.ReturnStatement || returned2.argument !== property.parent || property.parent.type !== AST_NODE_TYPES19.ObjectExpression || property.parent.properties.length !== 1 || ASTUtils15.findVariable(sourceCode.getScope(parameter), parameter.name) !== source || ASTUtils15.findVariable(sourceCode.getScope(property), node.init.name) !== source || source.references.some((reference) => reference.isTypeReference) || target.references.some((reference) => reference.isTypeReference)) return null;
|
|
1956
|
+
const name = owner.id.name;
|
|
1957
|
+
const bindings = sourceCode.getDeclaredVariables(owner).filter((binding3) => binding3.name === name);
|
|
1958
|
+
if (bindings.length !== 1 || bindings[0]?.defs.length !== 1 || bindings[0].defs[0]?.node !== owner || bindings[0].references.some((reference) => reference.isTypeReference)) return null;
|
|
1959
|
+
const span = [body3.range[0] + 1, statement.range[1]];
|
|
1960
|
+
const boundaries = sourceCode.text.slice(...span).replace(/[^\r\n\u2028\u2029]/gu, "");
|
|
1961
|
+
const neighbor = Math.max(0, span[0] - 1);
|
|
1962
|
+
const before = sourceCode.text.slice(neighbor, span[1] + 1).match(/\r\n|[\r\n\u2028\u2029]/gu) ?? [];
|
|
1963
|
+
const after = (sourceCode.text.slice(neighbor, span[0]) + boundaries + sourceCode.text.slice(span[1], span[1] + 1)).match(/\r\n|[\r\n\u2028\u2029]/gu) ?? [];
|
|
1964
|
+
if (before.length !== after.length || before.some((ending, index) => ending !== after[index])) return null;
|
|
1965
|
+
const key = sourceCode.getText(property.key);
|
|
1966
|
+
const value = sourceCode.getText(node.init);
|
|
1967
|
+
return (fixer) => [fixer.replaceTextRange(span, boundaries), fixer.replaceText(property, `${key}: ${value}`)];
|
|
1786
1968
|
}
|
|
1787
1969
|
var no_redundant_local_alias_default = createRule({
|
|
1788
1970
|
name: "no-redundant-local-alias",
|
|
1789
1971
|
documentation: NO_REDUNDANT_LOCAL_ALIAS_DOCUMENTATION,
|
|
1790
1972
|
meta: {
|
|
1791
1973
|
type: "suggestion",
|
|
1974
|
+
fixable: "code",
|
|
1792
1975
|
docs: { description: NO_REDUNDANT_LOCAL_ALIAS_DOCUMENTATION.summary },
|
|
1793
1976
|
schema: [],
|
|
1794
1977
|
messages: { redundantAlias: "This alias is read only by its matching object field; pass `{{source}}` directly as `{{target}}: {{source}}`." }
|
|
@@ -1796,9 +1979,10 @@ var no_redundant_local_alias_default = createRule({
|
|
|
1796
1979
|
defaultOptions: [],
|
|
1797
1980
|
create(context) {
|
|
1798
1981
|
if (isGeneratedFile(context, context.sourceCode.text)) return {};
|
|
1982
|
+
const hasModuleSyntax = context.sourceCode.ast.body.some((candidate2) => candidate2.type === AST_NODE_TYPES19.ImportDeclaration || candidate2.type === AST_NODE_TYPES19.ExportNamedDeclaration || candidate2.type === AST_NODE_TYPES19.ExportDefaultDeclaration || candidate2.type === AST_NODE_TYPES19.ExportAllDeclaration);
|
|
1799
1983
|
return {
|
|
1800
1984
|
VariableDeclarator(node) {
|
|
1801
|
-
if (node.parent.kind !== "const" || node.parent.declarations.length !== 1 || node.id.type !==
|
|
1985
|
+
if (node.parent.kind !== "const" || node.parent.declarations.length !== 1 || node.id.type !== AST_NODE_TYPES19.Identifier || node.id.typeAnnotation !== void 0 || node.init?.type !== AST_NODE_TYPES19.Identifier) return;
|
|
1802
1986
|
const scope = context.sourceCode.getScope(node);
|
|
1803
1987
|
if (scope.variableScope.type !== "function") return;
|
|
1804
1988
|
const target = ASTUtils15.findVariable(scope, node.id.name);
|
|
@@ -1809,18 +1993,18 @@ var no_redundant_local_alias_default = createRule({
|
|
|
1809
1993
|
const read = reads[0];
|
|
1810
1994
|
if (read === void 0 || read.from.variableScope !== scope.variableScope) return;
|
|
1811
1995
|
const property = read.identifier.parent;
|
|
1812
|
-
if (property.type !==
|
|
1813
|
-
context.report({ node, messageId: "redundantAlias", data: { source: node.init.name, target: node.id.name } });
|
|
1996
|
+
if (property.type !== AST_NODE_TYPES19.Property || !property.shorthand || property.value !== read.identifier || property.parent.type !== AST_NODE_TYPES19.ObjectExpression || property.computed || property.method || property.kind !== "init") return;
|
|
1997
|
+
context.report({ node, messageId: "redundantAlias", fix: hasModuleSyntax ? closedPrimitiveReturnFix(context.sourceCode, node, property, source, target) : null, data: { source: node.init.name, target: node.id.name } });
|
|
1814
1998
|
}
|
|
1815
1999
|
};
|
|
1816
2000
|
}
|
|
1817
2001
|
});
|
|
1818
2002
|
|
|
1819
2003
|
// src/rules/no-test-comments.ts
|
|
1820
|
-
import { AST_NODE_TYPES as
|
|
2004
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES21 } from "@typescript-eslint/utils";
|
|
1821
2005
|
|
|
1822
2006
|
// src/rules/_comments.ts
|
|
1823
|
-
import { AST_NODE_TYPES as
|
|
2007
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES20 } from "@typescript-eslint/utils";
|
|
1824
2008
|
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/;
|
|
1825
2009
|
var VERSION_RE = /(?:>=|<=|==|<|>)\s*v?\d+\.\d+|\bv\d+\.\d+|\b(?:since|until|as of)\s+(?:v?\d+\.\d+|Python\s*\d)/i;
|
|
1826
2010
|
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/;
|
|
@@ -1906,10 +2090,10 @@ var NARRATION_MAX_WORDS = 6;
|
|
|
1906
2090
|
var NARRATION_MIN_CONTENT = 1;
|
|
1907
2091
|
var TOKEN_PLURAL_MIN = 4;
|
|
1908
2092
|
var RESTATABLE_STATEMENTS = /* @__PURE__ */ new Set([
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
2093
|
+
AST_NODE_TYPES20.ExpressionStatement,
|
|
2094
|
+
AST_NODE_TYPES20.ReturnStatement,
|
|
2095
|
+
AST_NODE_TYPES20.ThrowStatement,
|
|
2096
|
+
AST_NODE_TYPES20.VariableDeclaration
|
|
1913
2097
|
]);
|
|
1914
2098
|
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;
|
|
1915
2099
|
var NARRATION_STOPWORDS = /* @__PURE__ */ new Set([
|
|
@@ -1968,12 +2152,12 @@ function restatableStatementBelow(comment, sourceCode) {
|
|
|
1968
2152
|
function restatableStatementNodeBelow(comment, sourceCode) {
|
|
1969
2153
|
const token = sourceCode.getTokenAfter(comment, { includeComments: false });
|
|
1970
2154
|
if (token === null || token.loc.start.line !== comment.loc.end.line + 1) return null;
|
|
1971
|
-
for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !==
|
|
2155
|
+
for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !== AST_NODE_TYPES20.Program; node = node.parent) {
|
|
1972
2156
|
if (!RESTATABLE_STATEMENTS.has(node.type)) continue;
|
|
1973
2157
|
if (node.loc.start.line !== token.loc.start.line || node.loc.end.line !== node.loc.start.line) {
|
|
1974
2158
|
return null;
|
|
1975
2159
|
}
|
|
1976
|
-
if (node.type ===
|
|
2160
|
+
if (node.type === AST_NODE_TYPES20.VariableDeclaration && isTrivialInitializer(node)) {
|
|
1977
2161
|
return null;
|
|
1978
2162
|
}
|
|
1979
2163
|
return node;
|
|
@@ -1983,8 +2167,8 @@ function restatableStatementNodeBelow(comment, sourceCode) {
|
|
|
1983
2167
|
function isTrivialInitializer(node) {
|
|
1984
2168
|
return node.declarations.every((declarator) => {
|
|
1985
2169
|
const init = declarator.init;
|
|
1986
|
-
if (init == null || init.type ===
|
|
1987
|
-
return init.type ===
|
|
2170
|
+
if (init == null || init.type === AST_NODE_TYPES20.Literal) return true;
|
|
2171
|
+
return init.type === AST_NODE_TYPES20.ArrayExpression && init.elements.length === 0 || init.type === AST_NODE_TYPES20.ObjectExpression && init.properties.length === 0;
|
|
1988
2172
|
});
|
|
1989
2173
|
}
|
|
1990
2174
|
function restatesStatementHead(body3, statement) {
|
|
@@ -2045,7 +2229,11 @@ function trailingCommentRemovalRange(text, comment) {
|
|
|
2045
2229
|
return { range: [start, contentEnd] };
|
|
2046
2230
|
}
|
|
2047
2231
|
function commentLineEndings(text, removal) {
|
|
2048
|
-
|
|
2232
|
+
const replacement = text.slice(...removal.range).replace(/[^\r\n\u2028\u2029]/gu, "");
|
|
2233
|
+
const neighbor = Math.max(0, removal.range[0] - 1);
|
|
2234
|
+
const original = text.slice(neighbor, removal.range[1] + 1).match(/\r\n|[\r\n\u2028\u2029]/gu) ?? [];
|
|
2235
|
+
const rendered = (text.slice(neighbor, removal.range[0]) + replacement + text.slice(removal.range[1], removal.range[1] + 1)).match(/\r\n|[\r\n\u2028\u2029]/gu) ?? [];
|
|
2236
|
+
return original.length === rendered.length && original.every((ending, index) => ending === rendered[index]) ? replacement : null;
|
|
2049
2237
|
}
|
|
2050
2238
|
function exactMemberCommentRemovalRange(text, comment, key) {
|
|
2051
2239
|
if (key.type !== "Identifier") return null;
|
|
@@ -2075,6 +2263,7 @@ var NO_TEST_COMMENTS_DOCUMENTATION = {
|
|
|
2075
2263
|
]
|
|
2076
2264
|
};
|
|
2077
2265
|
var DIRECTIVE = /^(?:eslint(?:-\S+)?\b|(?:biome|oxlint|jshint|jslint|c8|v8|istanbul|vitest|prettier|dprint)\b|@(?:ts-(?:check|nocheck|expect-error|ignore)|vitest-environment|jest-environment|jsx\w*|license|preserve)\b|[#!]\s*__(?:PURE|NO_SIDE_EFFECTS)__|\/\s*<(?:reference|amd-module|amd-dependency)\b)/u;
|
|
2266
|
+
var BEHAVIORAL_DIRECTIVE = /(?:[@#]__(?:PURE|NO_SIDE_EFFECTS)__|@vite-ignore\b|\bwebpack(?:ChunkName|Mode|Exports|FetchPriority|Include|Exclude|Prefetch|Preload|Ignore)\s*:)/u;
|
|
2078
2267
|
var LEGAL = /(?:^|\n)\s*\*?\s*(?:Copyright\b|SPDX-License-Identifier:|Licensed under\b|@license\b|@preserve\b)/iu;
|
|
2079
2268
|
var TYPE_CONTRACT = /@(?:type|typedef|template|param|returns?|satisfies|callback|overload|implements|extends|augments|enum|this|import)\b/u;
|
|
2080
2269
|
var DETECT_SECRETS_COMMENT_MARKERS = [
|
|
@@ -2094,12 +2283,13 @@ var PYTHON_EXTRA_WHITESPACE = /* @__PURE__ */ new Set(["", "", "", ""]);
|
|
|
2094
2283
|
function hasDetectSecretsPragma(comment, text) {
|
|
2095
2284
|
if (!comment.value.includes("pragma:")) return false;
|
|
2096
2285
|
let lineStart = Math.max(text.lastIndexOf("\r", comment.range[0] - 1), text.lastIndexOf("\n", comment.range[0] - 1)) + 1;
|
|
2286
|
+
const readerLineEndings = /\r\n?|\n/gu;
|
|
2287
|
+
readerLineEndings.lastIndex = lineStart;
|
|
2097
2288
|
while (lineStart < comment.range[1]) {
|
|
2098
|
-
const
|
|
2099
|
-
const
|
|
2100
|
-
const lineEnd = Math.min(nextCr < 0 ? text.length : nextCr, nextLf < 0 ? text.length : nextLf);
|
|
2289
|
+
const ending = readerLineEndings.exec(text);
|
|
2290
|
+
const lineEnd = ending?.index ?? text.length;
|
|
2101
2291
|
if (hasPragmaInReaderLine(comment, text.slice(lineStart, lineEnd), lineStart)) return true;
|
|
2102
|
-
lineStart = lineEnd + (
|
|
2292
|
+
lineStart = lineEnd + (ending?.[0].length ?? 1);
|
|
2103
2293
|
}
|
|
2104
2294
|
return false;
|
|
2105
2295
|
}
|
|
@@ -2138,7 +2328,7 @@ var no_test_comments_default = createRule({
|
|
|
2138
2328
|
if (!isTestFile(context) || isGeneratedFile(context, context.sourceCode.text)) return {};
|
|
2139
2329
|
const filename = scopedFilename(context);
|
|
2140
2330
|
const unambiguous = /(?:^|\/)(?:tests?|__tests__|fixtures|__fixtures__|__mocks__)\//u.test(filename) || /\.(?:test|spec|e2e|integration)\.[cm]?[jt]sx?$/u.test(filename);
|
|
2141
|
-
const framework = context.sourceCode.ast.body.some((statement) => statement.type ===
|
|
2331
|
+
const framework = context.sourceCode.ast.body.some((statement) => statement.type === AST_NODE_TYPES21.ImportDeclaration && statement.importKind !== "type" && (statement.specifiers.length === 0 || statement.specifiers.some((specifier) => specifier.type !== AST_NODE_TYPES21.ImportSpecifier || specifier.importKind !== "type")) && ["vitest", "@jest/globals", "@playwright/test", "bun:test", "node:test"].includes(statement.source.value));
|
|
2142
2332
|
if (!unambiguous && !framework) return {};
|
|
2143
2333
|
return {
|
|
2144
2334
|
Program() {
|
|
@@ -2159,26 +2349,35 @@ var no_test_comments_default = createRule({
|
|
|
2159
2349
|
}
|
|
2160
2350
|
for (const [index, comment] of comments.entries()) {
|
|
2161
2351
|
const body3 = comment.value.trim().replace(/^\*\s*/u, "");
|
|
2162
|
-
if (DIRECTIVE.test(body3) || LEGAL.test(comment.value) || legalLines.has(index) || TYPE_CONTRACT.test(comment.value) || hasDetectSecretsPragma(comment, context.sourceCode.text)) continue;
|
|
2352
|
+
if (DIRECTIVE.test(body3) || BEHAVIORAL_DIRECTIVE.test(comment.value) || LEGAL.test(comment.value) || legalLines.has(index) || TYPE_CONTRACT.test(comment.value) || hasDetectSecretsPragma(comment, context.sourceCode.text)) continue;
|
|
2163
2353
|
context.report({
|
|
2164
2354
|
node: comment,
|
|
2165
2355
|
messageId: "testComment",
|
|
2166
2356
|
fix: (fixer) => {
|
|
2167
2357
|
const text = context.sourceCode.text;
|
|
2358
|
+
const preserveLineTerminators = (edit) => {
|
|
2359
|
+
const neighbor = Math.max(0, edit.range[0] - 1);
|
|
2360
|
+
const original = text.slice(neighbor, edit.range[1] + 1).match(/\r\n|[\r\n\u2028\u2029]/gu) ?? [];
|
|
2361
|
+
const rendered = (text.slice(neighbor, edit.range[0]) + edit.text + text.slice(edit.range[1], edit.range[1] + 1)).match(/\r\n|[\r\n\u2028\u2029]/gu) ?? [];
|
|
2362
|
+
return original.length === rendered.length && original.every((ending, position) => ending === rendered[position]) ? edit : null;
|
|
2363
|
+
};
|
|
2168
2364
|
const own = ownLineCommentRemovalRange(text, comment);
|
|
2169
|
-
if (own !== null)
|
|
2365
|
+
if (own !== null) {
|
|
2366
|
+
const ownEndings = commentLineEndings(text, own);
|
|
2367
|
+
return ownEndings === null ? null : preserveLineTerminators(fixer.replaceTextRange(own.range, ownEndings));
|
|
2368
|
+
}
|
|
2170
2369
|
const trailing = trailingCommentRemovalRange(text, comment);
|
|
2171
|
-
if (trailing !== null) return fixer.replaceTextRange(trailing.range, "");
|
|
2370
|
+
if (trailing !== null) return preserveLineTerminators(fixer.replaceTextRange(trailing.range, ""));
|
|
2172
2371
|
const endings = context.sourceCode.getText(comment).replace(/[^\r\n\u2028\u2029]/gu, "");
|
|
2173
2372
|
if (endings.length > 0) {
|
|
2174
2373
|
let start = comment.range[0];
|
|
2175
2374
|
while (start > 0 && /[\t ]/u.test(text[start - 1] ?? "")) start--;
|
|
2176
|
-
return fixer.replaceTextRange([start, comment.range[1]], endings);
|
|
2375
|
+
return preserveLineTerminators(fixer.replaceTextRange([start, comment.range[1]], endings));
|
|
2177
2376
|
}
|
|
2178
2377
|
const before = text[comment.range[0] - 1] ?? "";
|
|
2179
2378
|
const after = text[comment.range[1]] ?? "";
|
|
2180
2379
|
const separator = before.length > 0 && after.length > 0 && !/\s/u.test(before + after) ? " " : "";
|
|
2181
|
-
return fixer.replaceText(comment, separator);
|
|
2380
|
+
return preserveLineTerminators(fixer.replaceText(comment, separator));
|
|
2182
2381
|
}
|
|
2183
2382
|
});
|
|
2184
2383
|
}
|
|
@@ -2188,14 +2387,14 @@ var no_test_comments_default = createRule({
|
|
|
2188
2387
|
});
|
|
2189
2388
|
|
|
2190
2389
|
// src/rules/no-mutating-container-transform.ts
|
|
2191
|
-
import { AST_NODE_TYPES as
|
|
2390
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES22, ASTUtils as ASTUtils16 } from "@typescript-eslint/utils";
|
|
2192
2391
|
var MUTATORS = /* @__PURE__ */ new Set(["copyWithin", "fill", "pop", "push", "reverse", "shift", "sort", "splice", "unshift"]);
|
|
2193
2392
|
var PRIMITIVES = /* @__PURE__ */ new Set([
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2393
|
+
AST_NODE_TYPES22.TSStringKeyword,
|
|
2394
|
+
AST_NODE_TYPES22.TSNumberKeyword,
|
|
2395
|
+
AST_NODE_TYPES22.TSBooleanKeyword,
|
|
2396
|
+
AST_NODE_TYPES22.TSBigIntKeyword,
|
|
2397
|
+
AST_NODE_TYPES22.TSSymbolKeyword
|
|
2199
2398
|
]);
|
|
2200
2399
|
var NO_MUTATING_CONTAINER_TRANSFORM_DOCUMENTATION = {
|
|
2201
2400
|
defaultLevel: "warning",
|
|
@@ -2214,27 +2413,27 @@ var NO_MUTATING_CONTAINER_TRANSFORM_DOCUMENTATION = {
|
|
|
2214
2413
|
]
|
|
2215
2414
|
};
|
|
2216
2415
|
function arrayElement(node, sourceCode) {
|
|
2217
|
-
if (node.type ===
|
|
2218
|
-
if (node.type ===
|
|
2416
|
+
if (node.type === AST_NODE_TYPES22.TSArrayType) return node.elementType;
|
|
2417
|
+
if (node.type === AST_NODE_TYPES22.TSTypeReference && node.typeName.type === AST_NODE_TYPES22.Identifier && (node.typeName.name === "Array" || node.typeName.name === "ReadonlyArray") && (ASTUtils16.findVariable(sourceCode.getScope(node.typeName), node.typeName.name)?.defs.length ?? 0) === 0 && node.typeArguments?.params.length === 1) return node.typeArguments.params[0] ?? null;
|
|
2219
2418
|
return null;
|
|
2220
2419
|
}
|
|
2221
2420
|
function returnsArray(node, sourceCode) {
|
|
2222
2421
|
let annotation = node.returnType?.typeAnnotation;
|
|
2223
|
-
if (annotation?.type ===
|
|
2422
|
+
if (annotation?.type === AST_NODE_TYPES22.TSTypeReference && annotation.typeName.type === AST_NODE_TYPES22.Identifier && annotation.typeName.name === "Promise" && (ASTUtils16.findVariable(sourceCode.getScope(annotation.typeName), "Promise")?.defs.length ?? 0) === 0 && annotation.typeArguments?.params.length === 1) annotation = annotation.typeArguments.params[0];
|
|
2224
2423
|
return annotation !== void 0 && arrayElement(annotation, sourceCode) !== null;
|
|
2225
2424
|
}
|
|
2226
2425
|
function supported(statements) {
|
|
2227
2426
|
return statements.every((statement) => {
|
|
2228
2427
|
switch (statement.type) {
|
|
2229
|
-
case
|
|
2230
|
-
case
|
|
2231
|
-
case
|
|
2232
|
-
case
|
|
2233
|
-
case
|
|
2428
|
+
case AST_NODE_TYPES22.ExpressionStatement:
|
|
2429
|
+
case AST_NODE_TYPES22.VariableDeclaration:
|
|
2430
|
+
case AST_NODE_TYPES22.ReturnStatement:
|
|
2431
|
+
case AST_NODE_TYPES22.ThrowStatement:
|
|
2432
|
+
case AST_NODE_TYPES22.EmptyStatement:
|
|
2234
2433
|
return true;
|
|
2235
|
-
case
|
|
2434
|
+
case AST_NODE_TYPES22.BlockStatement:
|
|
2236
2435
|
return supported(statement.body);
|
|
2237
|
-
case
|
|
2436
|
+
case AST_NODE_TYPES22.IfStatement:
|
|
2238
2437
|
return supported([statement.consequent]) && (statement.alternate === null || supported([statement.alternate]));
|
|
2239
2438
|
default:
|
|
2240
2439
|
return false;
|
|
@@ -2255,13 +2454,13 @@ var no_mutating_container_transform_default = createRule({
|
|
|
2255
2454
|
if (isGeneratedFile(context, context.sourceCode.text)) return {};
|
|
2256
2455
|
const sourceCode = context.sourceCode;
|
|
2257
2456
|
function binding3(node) {
|
|
2258
|
-
return node.type ===
|
|
2457
|
+
return node.type === AST_NODE_TYPES22.Identifier ? ASTUtils16.findVariable(sourceCode.getScope(node), node.name) : null;
|
|
2259
2458
|
}
|
|
2260
2459
|
function inspect(node) {
|
|
2261
|
-
if (node.body?.type !==
|
|
2460
|
+
if (node.body?.type !== AST_NODE_TYPES22.BlockStatement || !returnsArray(node, sourceCode) || !supported(node.body.body)) return;
|
|
2262
2461
|
const initial = /* @__PURE__ */ new Map();
|
|
2263
2462
|
for (const parameter of node.params) {
|
|
2264
|
-
if (parameter.type !==
|
|
2463
|
+
if (parameter.type !== AST_NODE_TYPES22.Identifier || parameter.typeAnnotation === void 0) continue;
|
|
2265
2464
|
const element = arrayElement(parameter.typeAnnotation.typeAnnotation, sourceCode);
|
|
2266
2465
|
const variable = binding3(parameter);
|
|
2267
2466
|
if (element !== null && PRIMITIVES.has(element.type) && variable !== null) initial.set(variable, parameter.name);
|
|
@@ -2274,26 +2473,26 @@ var no_mutating_container_transform_default = createRule({
|
|
|
2274
2473
|
}
|
|
2275
2474
|
function expression(current, state) {
|
|
2276
2475
|
switch (current.type) {
|
|
2277
|
-
case
|
|
2278
|
-
case
|
|
2279
|
-
case
|
|
2476
|
+
case AST_NODE_TYPES22.FunctionExpression:
|
|
2477
|
+
case AST_NODE_TYPES22.ArrowFunctionExpression:
|
|
2478
|
+
case AST_NODE_TYPES22.ClassExpression:
|
|
2280
2479
|
return;
|
|
2281
|
-
case
|
|
2480
|
+
case AST_NODE_TYPES22.AssignmentExpression:
|
|
2282
2481
|
assignment(current, state);
|
|
2283
2482
|
return;
|
|
2284
|
-
case
|
|
2483
|
+
case AST_NODE_TYPES22.LogicalExpression:
|
|
2285
2484
|
logical(current, state);
|
|
2286
2485
|
return;
|
|
2287
|
-
case
|
|
2486
|
+
case AST_NODE_TYPES22.ConditionalExpression:
|
|
2288
2487
|
conditional(current, state);
|
|
2289
2488
|
return;
|
|
2290
|
-
case
|
|
2489
|
+
case AST_NODE_TYPES22.UpdateExpression:
|
|
2291
2490
|
write(current.argument, state);
|
|
2292
2491
|
break;
|
|
2293
|
-
case
|
|
2492
|
+
case AST_NODE_TYPES22.UnaryExpression:
|
|
2294
2493
|
if (current.operator === "delete") write(current.argument, state);
|
|
2295
2494
|
break;
|
|
2296
|
-
case
|
|
2495
|
+
case AST_NODE_TYPES22.CallExpression:
|
|
2297
2496
|
mutationCall(current, state);
|
|
2298
2497
|
break;
|
|
2299
2498
|
default:
|
|
@@ -2313,13 +2512,13 @@ var no_mutating_container_transform_default = createRule({
|
|
|
2313
2512
|
function logical(current, state) {
|
|
2314
2513
|
expression(current.left, state);
|
|
2315
2514
|
const left = unwrapExpression(current.left);
|
|
2316
|
-
if (left.type ===
|
|
2515
|
+
if (left.type === AST_NODE_TYPES22.Literal && (current.operator === "&&" && !left.value || current.operator === "||" && !!left.value || current.operator === "??" && left.value !== null)) return;
|
|
2317
2516
|
expression(current.right, state);
|
|
2318
2517
|
}
|
|
2319
2518
|
function conditional(current, state) {
|
|
2320
2519
|
expression(current.test, state);
|
|
2321
2520
|
const test = unwrapExpression(current.test);
|
|
2322
|
-
if (test.type ===
|
|
2521
|
+
if (test.type === AST_NODE_TYPES22.Literal) {
|
|
2323
2522
|
expression(test.value ? current.consequent : current.alternate, state);
|
|
2324
2523
|
return;
|
|
2325
2524
|
}
|
|
@@ -2327,13 +2526,13 @@ var no_mutating_container_transform_default = createRule({
|
|
|
2327
2526
|
expression(current.alternate, state);
|
|
2328
2527
|
}
|
|
2329
2528
|
function mutationCall(current, state) {
|
|
2330
|
-
if (current.callee.type !==
|
|
2529
|
+
if (current.callee.type !== AST_NODE_TYPES22.MemberExpression || !MUTATORS.has(ASTUtils16.getPropertyName(current.callee) ?? "")) return;
|
|
2331
2530
|
const parameter = origin(current.callee.object, state);
|
|
2332
2531
|
if (parameter !== void 0 && first === null) first = { node: current, parameter };
|
|
2333
2532
|
}
|
|
2334
2533
|
function write(target, state) {
|
|
2335
2534
|
target = unwrapExpression(target);
|
|
2336
|
-
if (target.type !==
|
|
2535
|
+
if (target.type !== AST_NODE_TYPES22.MemberExpression || !target.computed && ASTUtils16.getPropertyName(target) !== "length") return;
|
|
2337
2536
|
const parameter = origin(target.object, state);
|
|
2338
2537
|
if (parameter !== void 0 && first === null) first = { node: target, parameter };
|
|
2339
2538
|
}
|
|
@@ -2343,18 +2542,18 @@ var no_mutating_container_transform_default = createRule({
|
|
|
2343
2542
|
}
|
|
2344
2543
|
function statement(current, state) {
|
|
2345
2544
|
switch (current.type) {
|
|
2346
|
-
case
|
|
2545
|
+
case AST_NODE_TYPES22.BlockStatement:
|
|
2347
2546
|
return statements(current.body, state);
|
|
2348
|
-
case
|
|
2547
|
+
case AST_NODE_TYPES22.IfStatement:
|
|
2349
2548
|
return branch(current, state);
|
|
2350
|
-
case
|
|
2549
|
+
case AST_NODE_TYPES22.VariableDeclaration:
|
|
2351
2550
|
declarations(current, state);
|
|
2352
2551
|
return false;
|
|
2353
|
-
case
|
|
2354
|
-
case
|
|
2552
|
+
case AST_NODE_TYPES22.ReturnStatement:
|
|
2553
|
+
case AST_NODE_TYPES22.ThrowStatement:
|
|
2355
2554
|
if (current.argument !== null) expression(current.argument, state);
|
|
2356
2555
|
return true;
|
|
2357
|
-
case
|
|
2556
|
+
case AST_NODE_TYPES22.ExpressionStatement:
|
|
2358
2557
|
expression(current.expression, state);
|
|
2359
2558
|
return false;
|
|
2360
2559
|
default:
|
|
@@ -2363,7 +2562,7 @@ var no_mutating_container_transform_default = createRule({
|
|
|
2363
2562
|
}
|
|
2364
2563
|
function branch(current, state) {
|
|
2365
2564
|
expression(current.test, state);
|
|
2366
|
-
if (current.test.type ===
|
|
2565
|
+
if (current.test.type === AST_NODE_TYPES22.Literal) return current.test.value ? statements([current.consequent], state) : current.alternate !== null && statements([current.alternate], state);
|
|
2367
2566
|
const left = new Map(state);
|
|
2368
2567
|
const right = new Map(state);
|
|
2369
2568
|
const leftEnds = statements([current.consequent], left);
|
|
@@ -2395,7 +2594,7 @@ var no_mutating_container_transform_default = createRule({
|
|
|
2395
2594
|
});
|
|
2396
2595
|
|
|
2397
2596
|
// src/rules/no-redundant-consumer-union.ts
|
|
2398
|
-
import { AST_NODE_TYPES as
|
|
2597
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES25, ESLintUtils as ESLintUtils2 } from "@typescript-eslint/utils";
|
|
2399
2598
|
import ts7 from "typescript";
|
|
2400
2599
|
|
|
2401
2600
|
// src/rules/_checked-native-source.ts
|
|
@@ -2506,109 +2705,13 @@ function finiteMember(member3, checker) {
|
|
|
2506
2705
|
}
|
|
2507
2706
|
|
|
2508
2707
|
// src/rules/_private-consumer-fix.ts
|
|
2509
|
-
import { AST_NODE_TYPES as
|
|
2708
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES23 } from "@typescript-eslint/utils";
|
|
2510
2709
|
import ts3 from "typescript";
|
|
2511
|
-
|
|
2512
|
-
// src/rules/_type-binding.ts
|
|
2513
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES21 } from "@typescript-eslint/utils";
|
|
2514
|
-
function typeBinding(source, identifier) {
|
|
2515
|
-
let scope = source.getScope(identifier);
|
|
2516
|
-
while (scope !== null) {
|
|
2517
|
-
const variable = scope.set.get(identifier.name);
|
|
2518
|
-
if (variable !== void 0 && (variable.isTypeVariable || variable.defs.some((definition) => definition.isTypeDefinition))) {
|
|
2519
|
-
return variable;
|
|
2520
|
-
}
|
|
2521
|
-
scope = scope.upper;
|
|
2522
|
-
}
|
|
2523
|
-
return null;
|
|
2524
|
-
}
|
|
2525
|
-
var REFERENCE_INDEXES = /* @__PURE__ */ new WeakMap();
|
|
2526
|
-
function retainsNamedTypeUses(source, removed) {
|
|
2527
|
-
const manager = source.scopeManager;
|
|
2528
|
-
if (manager === null) return false;
|
|
2529
|
-
const index = referenceIndex(source, manager);
|
|
2530
|
-
for (const reference of referencesWithin(index.references, removed)) {
|
|
2531
|
-
if (!reference.isRead()) continue;
|
|
2532
|
-
const binding3 = reference.resolved;
|
|
2533
|
-
if (!binding3 || !reference.isTypeReference && !reference.isValueReference) return false;
|
|
2534
|
-
if (binding3.defs.length === 0) continue;
|
|
2535
|
-
const reads = publicReadExtents(index, binding3);
|
|
2536
|
-
const extent = reference.isTypeReference ? reference.isValueReference ? reads.both : reads.type : reads.value;
|
|
2537
|
-
if (extent === null || extent.minStart >= removed.range[0] && extent.maxEnd <= removed.range[1]) return false;
|
|
2538
|
-
}
|
|
2539
|
-
return true;
|
|
2540
|
-
}
|
|
2541
|
-
function referenceIndex(source, manager) {
|
|
2542
|
-
const cached = REFERENCE_INDEXES.get(source);
|
|
2543
|
-
if (cached?.manager === manager) return cached;
|
|
2544
|
-
const references = manager.scopes.flatMap((scope) => scope.references);
|
|
2545
|
-
references.sort((left, right) => left.identifier.range[0] - right.identifier.range[0]);
|
|
2546
|
-
const index = { manager, references, publicReads: /* @__PURE__ */ new Map() };
|
|
2547
|
-
REFERENCE_INDEXES.set(source, index);
|
|
2548
|
-
return index;
|
|
2549
|
-
}
|
|
2550
|
-
function* referencesWithin(references, removed) {
|
|
2551
|
-
let low = 0;
|
|
2552
|
-
let high = references.length;
|
|
2553
|
-
while (low < high) {
|
|
2554
|
-
const middle = low + Math.floor((high - low) / 2);
|
|
2555
|
-
const reference = references[middle];
|
|
2556
|
-
if (reference === void 0 || reference.identifier.range[0] >= removed.range[0]) high = middle;
|
|
2557
|
-
else low = middle + 1;
|
|
2558
|
-
}
|
|
2559
|
-
for (let index = low; index < references.length; index++) {
|
|
2560
|
-
const reference = references[index];
|
|
2561
|
-
if (reference === void 0) continue;
|
|
2562
|
-
if (reference.identifier.range[0] > removed.range[1]) break;
|
|
2563
|
-
if (insideTypeRange(reference.identifier, removed)) yield reference;
|
|
2564
|
-
}
|
|
2565
|
-
}
|
|
2566
|
-
function publicReadExtents(index, binding3) {
|
|
2567
|
-
const cached = index.publicReads.get(binding3);
|
|
2568
|
-
if (cached !== void 0) return cached;
|
|
2569
|
-
let type = null;
|
|
2570
|
-
let value = null;
|
|
2571
|
-
let both = null;
|
|
2572
|
-
for (const retained of binding3.references) {
|
|
2573
|
-
if (!retained.isRead() || !retained.isTypeReference && !retained.isValueReference || binding3.defs.some((definition) => insideTypeRange(retained.identifier, definition.node)) || !publicTypeUse(retained.identifier)) continue;
|
|
2574
|
-
if (retained.isTypeReference) type = extendExtent(type, retained.identifier);
|
|
2575
|
-
if (retained.isValueReference) value = extendExtent(value, retained.identifier);
|
|
2576
|
-
if (retained.isTypeReference && retained.isValueReference) both = extendExtent(both, retained.identifier);
|
|
2577
|
-
}
|
|
2578
|
-
const result = { type, value, both };
|
|
2579
|
-
index.publicReads.set(binding3, result);
|
|
2580
|
-
return result;
|
|
2581
|
-
}
|
|
2582
|
-
function extendExtent(extent, identifier) {
|
|
2583
|
-
return {
|
|
2584
|
-
minStart: Math.min(extent?.minStart ?? identifier.range[0], identifier.range[0]),
|
|
2585
|
-
maxEnd: Math.max(extent?.maxEnd ?? identifier.range[1], identifier.range[1])
|
|
2586
|
-
};
|
|
2587
|
-
}
|
|
2588
|
-
function publicTypeUse(identifier) {
|
|
2589
|
-
let node = identifier;
|
|
2590
|
-
while (node.parent) {
|
|
2591
|
-
if (node.type === AST_NODE_TYPES21.TSTypeAnnotation || node.type === AST_NODE_TYPES21.TSTypePredicate || node.type === AST_NODE_TYPES21.TSAsExpression || node.type === AST_NODE_TYPES21.TSTypeAssertion) return false;
|
|
2592
|
-
if (node.type === AST_NODE_TYPES21.TSTypeAliasDeclaration) {
|
|
2593
|
-
return node.parent.type === AST_NODE_TYPES21.ExportNamedDeclaration && node.parent.declaration === node && node.parent.parent.type === AST_NODE_TYPES21.Program;
|
|
2594
|
-
}
|
|
2595
|
-
if (node.type === AST_NODE_TYPES21.ExportSpecifier) {
|
|
2596
|
-
return node.parent.type === AST_NODE_TYPES21.ExportNamedDeclaration && node.parent.source === null && node.parent.parent.type === AST_NODE_TYPES21.Program;
|
|
2597
|
-
}
|
|
2598
|
-
node = node.parent;
|
|
2599
|
-
}
|
|
2600
|
-
return false;
|
|
2601
|
-
}
|
|
2602
|
-
function insideTypeRange(node, range) {
|
|
2603
|
-
return node.range[0] >= range.range[0] && node.range[1] <= range.range[1];
|
|
2604
|
-
}
|
|
2605
|
-
|
|
2606
|
-
// src/rules/_private-consumer-fix.ts
|
|
2607
2710
|
var UNSAFE = ts3.TypeFlags.Any | ts3.TypeFlags.Unknown | ts3.TypeFlags.Never | ts3.TypeFlags.TypeParameter | ts3.TypeFlags.Conditional | ts3.TypeFlags.IndexedAccess | ts3.TypeFlags.Substitution;
|
|
2608
2711
|
function validConsumerFixCalls(node, parameter, sourceCode, services) {
|
|
2609
2712
|
if (sourceCode.getAllComments().some((comment) => /@ts-(?:expect-error|ignore|nocheck)\b/u.test(comment.value))) return false;
|
|
2610
|
-
const owner = node.type ===
|
|
2611
|
-
if (owner.type !==
|
|
2713
|
+
const owner = node.type === AST_NODE_TYPES23.FunctionDeclaration ? node : node.parent;
|
|
2714
|
+
if (owner.type !== AST_NODE_TYPES23.FunctionDeclaration && owner.type !== AST_NODE_TYPES23.VariableDeclarator) return false;
|
|
2612
2715
|
const binding3 = sourceCode.getDeclaredVariables(owner).find((variable) => variable.defs.some((definition) => definition.node === owner && (definition.type === "FunctionName" || definition.type === "Variable")));
|
|
2613
2716
|
if (!binding3) return false;
|
|
2614
2717
|
const declaration = services.esTreeNodeToTSNodeMap.get(node);
|
|
@@ -2644,7 +2747,7 @@ function validConsumerFixCalls(node, parameter, sourceCode, services) {
|
|
|
2644
2747
|
continue;
|
|
2645
2748
|
}
|
|
2646
2749
|
const call = reference.identifier.parent;
|
|
2647
|
-
if (reference.isTypeReference || !reference.isReadOnly() || call.type !==
|
|
2750
|
+
if (reference.isTypeReference || !reference.isReadOnly() || call.type !== AST_NODE_TYPES23.CallExpression || call.callee !== reference.identifier || call.optional || call.typeArguments || call.arguments.length !== declaration.parameters.length || !call.arguments.every((argument) => argument.type === AST_NODE_TYPES23.Identifier) || !validArguments(call)) return false;
|
|
2648
2751
|
calls += 1;
|
|
2649
2752
|
}
|
|
2650
2753
|
return calls > 0;
|
|
@@ -2696,7 +2799,7 @@ function minimalConsumerFix(sourceCode, annotation, removed) {
|
|
|
2696
2799
|
}
|
|
2697
2800
|
|
|
2698
2801
|
// src/rules/_private-scalar-consumer.ts
|
|
2699
|
-
import { AST_NODE_TYPES as
|
|
2802
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES24 } from "@typescript-eslint/utils";
|
|
2700
2803
|
import ts6 from "typescript";
|
|
2701
2804
|
|
|
2702
2805
|
// src/rules/_scalar-parameter-view.ts
|
|
@@ -2846,8 +2949,8 @@ function intrinsicAttribute(attribute, view) {
|
|
|
2846
2949
|
// src/rules/_private-scalar-consumer.ts
|
|
2847
2950
|
function directEval(node) {
|
|
2848
2951
|
let callee = unwrapExpression(node.callee);
|
|
2849
|
-
while (callee.type ===
|
|
2850
|
-
return callee.type ===
|
|
2952
|
+
while (callee.type === AST_NODE_TYPES24.TSInstantiationExpression) callee = unwrapExpression(callee.expression);
|
|
2953
|
+
return callee.type === AST_NODE_TYPES24.Identifier && callee.name === "eval";
|
|
2851
2954
|
}
|
|
2852
2955
|
function primitiveKeyword(node) {
|
|
2853
2956
|
return node !== void 0 && (node.kind === ts6.SyntaxKind.StringKeyword || node.kind === ts6.SyntaxKind.NumberKeyword || node.kind === ts6.SyntaxKind.BooleanKeyword || node.kind === ts6.SyntaxKind.BigIntKeyword);
|
|
@@ -2860,16 +2963,16 @@ function consumerAnnotation(node, auxiliaryScalars = false) {
|
|
|
2860
2963
|
if (!auxiliaryScalars) return void 0;
|
|
2861
2964
|
let annotation;
|
|
2862
2965
|
for (const parameter2 of node.params) {
|
|
2863
|
-
if (parameter2.type !==
|
|
2966
|
+
if (parameter2.type !== AST_NODE_TYPES24.Identifier && parameter2.type !== AST_NODE_TYPES24.ObjectPattern) continue;
|
|
2864
2967
|
const current = parameter2.typeAnnotation?.typeAnnotation;
|
|
2865
|
-
if (current?.type !==
|
|
2968
|
+
if (current?.type !== AST_NODE_TYPES24.TSTypeLiteral) continue;
|
|
2866
2969
|
if (annotation) return void 0;
|
|
2867
2970
|
annotation = current;
|
|
2868
2971
|
}
|
|
2869
2972
|
return annotation;
|
|
2870
2973
|
}
|
|
2871
2974
|
const parameter = node.params[0];
|
|
2872
|
-
return parameter?.type ===
|
|
2975
|
+
return parameter?.type === AST_NODE_TYPES24.Identifier || parameter?.type === AST_NODE_TYPES24.ObjectPattern ? parameter.typeAnnotation?.typeAnnotation : void 0;
|
|
2873
2976
|
}
|
|
2874
2977
|
function exportedSymbols(source, checker) {
|
|
2875
2978
|
const symbol = checker.getSymbolAtLocation(source);
|
|
@@ -2919,12 +3022,12 @@ function auxiliaryBindings(native, selected, checker) {
|
|
|
2919
3022
|
return bindings;
|
|
2920
3023
|
}
|
|
2921
3024
|
function callableBinding(node, sourceCode) {
|
|
2922
|
-
if (node.type ===
|
|
2923
|
-
if (node.parent.type !==
|
|
3025
|
+
if (node.type === AST_NODE_TYPES24.FunctionDeclaration) {
|
|
3026
|
+
if (node.parent.type !== AST_NODE_TYPES24.Program) return void 0;
|
|
2924
3027
|
return sourceCode.getDeclaredVariables(node).find((variable) => variable.defs.some((definition) => definition.type === "FunctionName" && definition.node === node));
|
|
2925
3028
|
}
|
|
2926
3029
|
const declaration = node.parent;
|
|
2927
|
-
if (declaration.type !==
|
|
3030
|
+
if (declaration.type !== AST_NODE_TYPES24.VariableDeclarator || declaration.init !== node || declaration.id.type !== AST_NODE_TYPES24.Identifier || declaration.id.typeAnnotation || declaration.parent.kind !== "const" || declaration.parent.parent.type !== AST_NODE_TYPES24.Program) return void 0;
|
|
2928
3031
|
return sourceCode.getDeclaredVariables(declaration).find((variable) => variable.defs.some((definition) => definition.type === "Variable" && definition.node === declaration));
|
|
2929
3032
|
}
|
|
2930
3033
|
function directCalls(binding3, arity) {
|
|
@@ -2932,7 +3035,7 @@ function directCalls(binding3, arity) {
|
|
|
2932
3035
|
const stable2 = stableValueBinding(binding3, (reference) => {
|
|
2933
3036
|
const identifier = reference.identifier;
|
|
2934
3037
|
const call = identifier.parent;
|
|
2935
|
-
if (reference.isTypeReference || !reference.isReadOnly() || call.type !==
|
|
3038
|
+
if (reference.isTypeReference || !reference.isReadOnly() || call.type !== AST_NODE_TYPES24.CallExpression || call.callee !== identifier || call.optional || call.typeArguments || call.arguments.length !== arity || !call.arguments.every((argument) => argument.type === AST_NODE_TYPES24.Identifier)) return false;
|
|
2936
3039
|
calls += 1;
|
|
2937
3040
|
return true;
|
|
2938
3041
|
});
|
|
@@ -2944,6 +3047,8 @@ var CONFIG = { path: "tsconfig.json", source: '{"compilerOptions":{"strict":true
|
|
|
2944
3047
|
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);';
|
|
2945
3048
|
var NULLABLE_EXAMPLE = EXAMPLE.replace("readonly name: string", "readonly name: string | null").replace("return value.name;", "return value.name ?? '';");
|
|
2946
3049
|
var OPTIONAL_EXAMPLE = EXAMPLE.replace("readonly breed: string", "readonly breed?: string");
|
|
3050
|
+
var SCALAR_HELPER_EXAMPLE = EXAMPLE.replace("return value.name;", "return formatName(value.name);").replace("function label", "function formatName(value: string): string {return '[' + value + ']';} function label");
|
|
3051
|
+
var WHOLE_OBJECT_HELPER_EXAMPLE = EXAMPLE.replace("return value.name;", "return formatAnimal(value);").replace("function label", "function formatAnimal(value: Animal): string {return value.name;} function label");
|
|
2947
3052
|
var NO_REDUNDANT_CONSUMER_UNION_DOCUMENTATION = {
|
|
2948
3053
|
defaultLevel: "warning",
|
|
2949
3054
|
summary: "Keep the covering object contract in a private scalar consumer union.",
|
|
@@ -2953,12 +3058,15 @@ var NO_REDUNDANT_CONSUMER_UNION_DOCUMENTATION = {
|
|
|
2953
3058
|
autofix: "safe",
|
|
2954
3059
|
limitations: [
|
|
2955
3060
|
"Automatic fixes additionally require every existing identifier caller to be natively assignable to the original contract, without Any, unknown, error or unresolved types on the relevant surface. Comments inside the annotation and TypeScript suppression directives keep the finding manual. Removed named types/imports must retain an independent top-level exported type-alias or direct type-export read. Other removable annotations/assertions, the covering annotation and own-definition/self references cannot keep one another live; otherwise simultaneous fixes can introduce unused-type errors. The exact authored covering type and terminator token sequence are retained; edits that would merge distinct CR and LF terminators remain manual; no producer, call or function body is rewritten.",
|
|
2956
|
-
"Only an inline binary parameter union in a strict module's top-level private scalar consumer is supported. Exactly one parameter, an explicit broad primitive return annotation, a single
|
|
3061
|
+
"Only an inline binary parameter union in a strict module's top-level private scalar consumer is supported. Exactly one parameter, an explicit broad primitive return annotation, a single supported returned scalar expression and direct identifier-argument callers are required. Type queries or type-only exports of the callable, public APIs, callbacks, contextual signatures, overloads, generics, decorators, async functions, direct eval and fresh-object callers prevent findings.",
|
|
3062
|
+
"Scalar values may pass through one implemented same-file top-level function or raw const-arrow helper with an explicit scalar return annotation and the exact native resolved signature. Every argument must already satisfy the scalar read view; the containing source must pass the existing native checked-source proof. Imported, ambient, aliased, overloaded, generic or contextually typed helpers, member calls, optional calls, spread arguments and whole-object arguments remain unsupported. Helper permission does not add auxiliary consumer parameters or replace the required object-field read anchor. Helper bodies need not be pure because no call or body is rewritten.",
|
|
2957
3063
|
"Both alternatives must have complete ordinary finite structural surfaces consisting only of explicitly readonly broad string, number, boolean or bigint properties, optionally paired directly with null or undefined in an exact two-part union. Required and optional nullable fields may be read under the same native coverage proof. Every field must have one actual declaration origin throughout each alternative's inheritance/intersection graph. Shared ancestors retain that origin; repeated merged fields, explicit overrides and independently declared overlapping fields abstain, including valid compatible declarations. This excludes recovered conflicting properties without claiming whole-source health. Aliases, imports, re-exports and ordinary inheritance are resolved by the parser-owned TypeScript checker. Any, unknown, missing imports, open/generic/mapped/indexed types, classes, brands, literal discriminants, methods, properties with scalar type aliases, parenthesized or more complex property unions, callbacks and recursive or nested object fields are unsupported.",
|
|
2958
3064
|
"Reports proper native assignability, where covered is assignable to covering and the reverse is false, or mutual native assignability with a strict smaller declared covering surface and only optional covered-only members. Every covering member, including optional members, must exist in the covered type's enumerated declared surface. Otherwise an existing identifier may carry an incompatible extra field and be rejected after simplification; implicit Object members containing Any cannot replace explicit declared coverage or the native Optional requirement. The covering type must declare every read field and a read required field; an all-optional reduced contract can reject existing callers. Identical alternatives and primitive/top/bottom redundancy remain upstream-owned; equal-key and incomparable mutually assignable structures are excluded. The mutual case additionally requires inline contracts or locally bound interfaces/type aliases whose alias and heritage references can be traced through the parser-owned type scope. Merged interface fragments must all resolve to the reference's same native symbol; mixed exported/local recovery abstains. Imported, global and qualified-namespace references in that path abstain; proper one-way coverage retains its existing alias/import support.",
|
|
2959
|
-
"General union simplification can change Extract, conditional types, in-narrowing, fresh-literal checking and public presentation. Those contexts are excluded even when ordinary assignment succeeds. Flat destructuring counts every bound field as read; whole-object escape, mutation,
|
|
3065
|
+
"General union simplification can change Extract, conditional types, in-narrowing, fresh-literal checking and public presentation. Those contexts are excluded even when ordinary assignment succeeds. Flat destructuring counts every bound field as read; whole-object escape, mutation, unproved helper calls, closures, reflection, serialization, dynamic reads, implicit Object capabilities and JSX prevent findings. Imported Python protocol assignability is not approximated by this rule."
|
|
2960
3066
|
],
|
|
2961
3067
|
examples: [
|
|
3068
|
+
{ id: "local-scalar-helper", scenarioId: "local-scalar-helper", title: "A local helper receives only the required name", outcome: "match", files: [{ path: "src/case.ts", source: SCALAR_HELPER_EXAMPLE }, CONFIG], focusPath: "src/case.ts", expectedCount: 1, public: true, fixedFiles: [{ path: "src/case.ts", source: SCALAR_HELPER_EXAMPLE.replace("Dog | Animal", "Animal") }] },
|
|
3069
|
+
{ id: "whole-object-helper", scenarioId: "local-scalar-helper", title: "Passing the whole object remains outside the scalar helper proof", outcome: "no-match", files: [{ path: "src/case.ts", source: WHOLE_OBJECT_HELPER_EXAMPLE }, CONFIG], focusPath: "src/case.ts", expectedCount: 0, public: true },
|
|
2962
3070
|
{ id: "covered-alternative", title: "The private consumer needs the covering Animal contract", outcome: "match", files: [{ path: "src/case.ts", source: EXAMPLE }, CONFIG], focusPath: "src/case.ts", expectedCount: 1, public: true, fixedFiles: [{ path: "src/case.ts", source: EXAMPLE.replace("Dog | Animal", "Animal") }] },
|
|
2963
3071
|
{ id: "public-contract", title: "A public union retains its observable alternatives", outcome: "no-match", files: [{ path: "src/case.ts", source: EXAMPLE.replace("function label", "export function label") }, CONFIG], focusPath: "src/case.ts", expectedCount: 0, public: true },
|
|
2964
3072
|
{ id: "optional-covered-alternative", scenarioId: "optional-readonly-contract", title: "An unread optional breed retains the smaller Animal surface", outcome: "match", files: [{ path: "src/case.ts", source: OPTIONAL_EXAMPLE }, CONFIG], focusPath: "src/case.ts", expectedCount: 1, public: true, fixedFiles: [{ path: "src/case.ts", source: OPTIONAL_EXAMPLE.replace("Dog | Animal", "Animal") }] },
|
|
@@ -2992,13 +3100,13 @@ function localContractBindings(roots, source, services) {
|
|
|
2992
3100
|
}
|
|
2993
3101
|
function localContractReferences(node, source, services) {
|
|
2994
3102
|
switch (node.type) {
|
|
2995
|
-
case
|
|
3103
|
+
case AST_NODE_TYPES25.TSTypeLiteral:
|
|
2996
3104
|
return [];
|
|
2997
|
-
case
|
|
3105
|
+
case AST_NODE_TYPES25.TSIntersectionType:
|
|
2998
3106
|
return node.types;
|
|
2999
|
-
case
|
|
3000
|
-
return !node.typeArguments && node.typeName.type ===
|
|
3001
|
-
case
|
|
3107
|
+
case AST_NODE_TYPES25.TSTypeReference:
|
|
3108
|
+
return !node.typeArguments && node.typeName.type === AST_NODE_TYPES25.Identifier ? [node.typeName] : null;
|
|
3109
|
+
case AST_NODE_TYPES25.Identifier:
|
|
3002
3110
|
return localBindingReferences(node, source, services);
|
|
3003
3111
|
default:
|
|
3004
3112
|
return null;
|
|
@@ -3008,8 +3116,8 @@ function localBindingReferences(identifier, source, services) {
|
|
|
3008
3116
|
const definitions2 = typeBinding(source, identifier)?.defs.filter((definition) => definition.isTypeDefinition).map((definition) => definition.node);
|
|
3009
3117
|
if (!definitions2?.length || !definitions2.every(moduleTypeDeclaration)) return null;
|
|
3010
3118
|
const first = definitions2[0];
|
|
3011
|
-
if (definitions2.length === 1 && first?.type ===
|
|
3012
|
-
const interfaces = definitions2.filter((definition) => definition.type ===
|
|
3119
|
+
if (definitions2.length === 1 && first?.type === AST_NODE_TYPES25.TSTypeAliasDeclaration && !first.typeParameters) return [first.typeAnnotation];
|
|
3120
|
+
const interfaces = definitions2.filter((definition) => definition.type === AST_NODE_TYPES25.TSInterfaceDeclaration);
|
|
3013
3121
|
if (interfaces.length !== definitions2.length || interfaces.some((declaration) => declaration.typeParameters)) return null;
|
|
3014
3122
|
if (interfaces.length > 1) {
|
|
3015
3123
|
const checker = services.program.getTypeChecker();
|
|
@@ -3017,13 +3125,13 @@ function localBindingReferences(identifier, source, services) {
|
|
|
3017
3125
|
if (!symbol || interfaces.some((declaration) => checker.getSymbolAtLocation(services.esTreeNodeToTSNodeMap.get(declaration.id)) !== symbol)) return null;
|
|
3018
3126
|
}
|
|
3019
3127
|
const bases = interfaces.flatMap((declaration) => declaration.extends.map((base) => base.expression));
|
|
3020
|
-
return bases.every((base) => base.type ===
|
|
3128
|
+
return bases.every((base) => base.type === AST_NODE_TYPES25.Identifier) ? bases : null;
|
|
3021
3129
|
}
|
|
3022
3130
|
function moduleTypeDeclaration(node) {
|
|
3023
3131
|
const parent = node.parent;
|
|
3024
|
-
if (parent?.type ===
|
|
3025
|
-
if (parent?.type !==
|
|
3026
|
-
return parent.parent.type ===
|
|
3132
|
+
if (parent?.type === AST_NODE_TYPES25.Program) return true;
|
|
3133
|
+
if (parent?.type !== AST_NODE_TYPES25.ExportNamedDeclaration && parent?.type !== AST_NODE_TYPES25.ExportDefaultDeclaration) return false;
|
|
3134
|
+
return parent.parent.type === AST_NODE_TYPES25.Program;
|
|
3027
3135
|
}
|
|
3028
3136
|
function coveringAlternative(leftNode, rightNode, checker, fieldsOf, reads) {
|
|
3029
3137
|
const left = checker.getTypeFromTypeNode(leftNode);
|
|
@@ -3058,7 +3166,7 @@ var no_redundant_consumer_union_default = createRule({
|
|
|
3058
3166
|
let dynamic = false;
|
|
3059
3167
|
const remember = (node) => {
|
|
3060
3168
|
const annotation = consumerAnnotation(node);
|
|
3061
|
-
if (annotation?.type ===
|
|
3169
|
+
if (annotation?.type === AST_NODE_TYPES25.TSUnionType && annotation.types.length === 2) candidates.push(node);
|
|
3062
3170
|
};
|
|
3063
3171
|
return {
|
|
3064
3172
|
FunctionDeclaration: remember,
|
|
@@ -3083,7 +3191,7 @@ var no_redundant_consumer_union_default = createRule({
|
|
|
3083
3191
|
return surfaces.get(type) ?? null;
|
|
3084
3192
|
};
|
|
3085
3193
|
for (const candidate2 of candidates) {
|
|
3086
|
-
const consumer = privateScalarConsumer(candidate2, context.sourceCode, services, exports);
|
|
3194
|
+
const consumer = privateScalarConsumer(candidate2, context.sourceCode, services, exports, { scalarCalls: true });
|
|
3087
3195
|
const annotation = consumer?.parameter.type;
|
|
3088
3196
|
if (!consumer || !annotation || !ts7.isUnionTypeNode(annotation) || annotation.types.length !== 2) continue;
|
|
3089
3197
|
const leftNode = annotation.types[0];
|
|
@@ -3092,7 +3200,7 @@ var no_redundant_consumer_union_default = createRule({
|
|
|
3092
3200
|
const coverage = coveringAlternative(leftNode, rightNode, checker, fieldsOf, consumer.reads);
|
|
3093
3201
|
if (!coverage) continue;
|
|
3094
3202
|
const reportNode = services.tsNodeToESTreeNodeMap.get(annotation);
|
|
3095
|
-
if (coverage.mutual && (reportNode.type !==
|
|
3203
|
+
if (coverage.mutual && (reportNode.type !== AST_NODE_TYPES25.TSUnionType || !localContractBindings(reportNode.types, context.sourceCode, services))) continue;
|
|
3096
3204
|
const { covered: coveredNode, covering: coveringNode } = coverage;
|
|
3097
3205
|
const fix = privateUnionFix(context.sourceCode, services, {
|
|
3098
3206
|
candidate: candidate2,
|
|
@@ -3110,7 +3218,7 @@ var no_redundant_consumer_union_default = createRule({
|
|
|
3110
3218
|
});
|
|
3111
3219
|
|
|
3112
3220
|
// src/rules/prefer-minimal-parameter-contract.ts
|
|
3113
|
-
import { AST_NODE_TYPES as
|
|
3221
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES26, ESLintUtils as ESLintUtils3 } from "@typescript-eslint/utils";
|
|
3114
3222
|
import ts8 from "typescript";
|
|
3115
3223
|
var CONFIG2 = { path: "tsconfig.json", source: '{"compilerOptions":{"strict":true,"target":"ESNext","module":"ESNext","moduleResolution":"Bundler"}}' };
|
|
3116
3224
|
var EXAMPLE2 = 'export {}; const account = {name: "Ada", email: "a"}; function label(user: {readonly email: string; readonly name: string}): string {return user.name;} label(account);';
|
|
@@ -3167,7 +3275,7 @@ var prefer_minimal_parameter_contract_default = createRule({
|
|
|
3167
3275
|
const candidates = [];
|
|
3168
3276
|
let dynamic = false;
|
|
3169
3277
|
const remember = (node) => {
|
|
3170
|
-
if (consumerAnnotation(node, true)?.type ===
|
|
3278
|
+
if (consumerAnnotation(node, true)?.type === AST_NODE_TYPES26.TSTypeLiteral) candidates.push(node);
|
|
3171
3279
|
};
|
|
3172
3280
|
return {
|
|
3173
3281
|
FunctionDeclaration: remember,
|
|
@@ -3201,7 +3309,7 @@ var prefer_minimal_parameter_contract_default = createRule({
|
|
|
3201
3309
|
});
|
|
3202
3310
|
|
|
3203
3311
|
// src/rules/no-excess-jsx-props.ts
|
|
3204
|
-
import { AST_NODE_TYPES as
|
|
3312
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES27, ESLintUtils as ESLintUtils4 } from "@typescript-eslint/utils";
|
|
3205
3313
|
import ts10 from "typescript";
|
|
3206
3314
|
|
|
3207
3315
|
// src/rules/_ordinary-object-effects.ts
|
|
@@ -3543,11 +3651,11 @@ var PRIMITIVE_OPERATORS = /* @__PURE__ */ new Set([
|
|
|
3543
3651
|
function plainLiteralFields(node) {
|
|
3544
3652
|
const fields2 = /* @__PURE__ */ new Map();
|
|
3545
3653
|
for (const property of node.properties) {
|
|
3546
|
-
if (property.type !==
|
|
3654
|
+
if (property.type !== AST_NODE_TYPES27.Property || property.kind !== "init") return null;
|
|
3547
3655
|
const key = property.key;
|
|
3548
3656
|
let name;
|
|
3549
|
-
if (!property.computed && key.type ===
|
|
3550
|
-
else if (key.type ===
|
|
3657
|
+
if (!property.computed && key.type === AST_NODE_TYPES27.Identifier) name = key.name;
|
|
3658
|
+
else if (key.type === AST_NODE_TYPES27.Literal && (typeof key.value === "string" || typeof key.value === "number")) name = String(key.value);
|
|
3551
3659
|
else return null;
|
|
3552
3660
|
if (name === "__proto__") return null;
|
|
3553
3661
|
fields2.set(name, property);
|
|
@@ -3659,35 +3767,35 @@ function localObjectFields(symbol, source, proof) {
|
|
|
3659
3767
|
if (!native || native.getSourceFile() !== source || !initializer || !ts10.isObjectLiteralExpression(initializer)) return null;
|
|
3660
3768
|
const declaration = proof.services.tsNodeToESTreeNodeMap.get(native);
|
|
3661
3769
|
const literal2 = proof.services.tsNodeToESTreeNodeMap.get(initializer);
|
|
3662
|
-
if (declaration.type !==
|
|
3770
|
+
if (declaration.type !== AST_NODE_TYPES27.VariableDeclarator || declaration.parent.kind !== "const" || declaration.id.type !== AST_NODE_TYPES27.Identifier || literal2.type !== AST_NODE_TYPES27.ObjectExpression || declaration.parent.parent.type === AST_NODE_TYPES27.ExportNamedDeclaration) return null;
|
|
3663
3771
|
const fields2 = plainLiteralFields(literal2);
|
|
3664
3772
|
const binding3 = proof.sourceCode.getDeclaredVariables(declaration).find((variable) => variable.defs.some((definition) => definition.type === "Variable" && definition.node === declaration));
|
|
3665
3773
|
if (!fields2 || !binding3 || binding3.defs.length !== 1 || !stableValueBinding(binding3, (reference) => {
|
|
3666
3774
|
if (!reference.isReadOnly() || reference.isTypeReference) return false;
|
|
3667
3775
|
const member3 = reference.identifier.parent;
|
|
3668
|
-
return member3.type ===
|
|
3776
|
+
return member3.type === AST_NODE_TYPES27.MemberExpression && member3.object === reference.identifier && readonlyFieldValue(member3, fields2);
|
|
3669
3777
|
})) return null;
|
|
3670
3778
|
return fields2;
|
|
3671
3779
|
}
|
|
3672
3780
|
function staticMemberKey(member3) {
|
|
3673
3781
|
const property = member3.property;
|
|
3674
|
-
return !member3.computed && property.type ===
|
|
3782
|
+
return !member3.computed && property.type === AST_NODE_TYPES27.Identifier ? property.name : property.type === AST_NODE_TYPES27.Literal && (typeof property.value === "string" || typeof property.value === "number") ? String(property.value) : void 0;
|
|
3675
3783
|
}
|
|
3676
3784
|
function readonlyFieldValue(member3, fields2) {
|
|
3677
3785
|
const key = staticMemberKey(member3);
|
|
3678
3786
|
if (key === void 0 || !fields2.has(key)) return false;
|
|
3679
3787
|
const parent = member3.parent;
|
|
3680
|
-
if (parent.type ===
|
|
3788
|
+
if (parent.type === AST_NODE_TYPES27.Property && parent.value === member3 && parent.parent.type === AST_NODE_TYPES27.ObjectExpression) {
|
|
3681
3789
|
const object = parent.parent;
|
|
3682
3790
|
const owner = object.parent;
|
|
3683
|
-
return owner.type ===
|
|
3791
|
+
return owner.type === AST_NODE_TYPES27.JSXSpreadAttribute && owner.argument === object || owner.type === AST_NODE_TYPES27.VariableDeclarator && owner.init === object;
|
|
3684
3792
|
}
|
|
3685
|
-
return parent.type ===
|
|
3793
|
+
return parent.type === AST_NODE_TYPES27.JSXExpressionContainer && parent.expression === member3 || parent.type === AST_NODE_TYPES27.VariableDeclarator && parent.init === member3;
|
|
3686
3794
|
}
|
|
3687
3795
|
function privateElementDeclaration(opening) {
|
|
3688
3796
|
const value = outerExpression(opening.parent);
|
|
3689
3797
|
const declaration = value.parent;
|
|
3690
|
-
return declaration.type ===
|
|
3798
|
+
return declaration.type === AST_NODE_TYPES27.VariableDeclarator && declaration.init === value && declaration.id.type === AST_NODE_TYPES27.Identifier && declaration.parent.kind === "const" && declaration.parent.parent.type !== AST_NODE_TYPES27.ExportNamedDeclaration ? declaration : null;
|
|
3691
3799
|
}
|
|
3692
3800
|
function closedElementValue(opening, declaration, fields2, reads, proof) {
|
|
3693
3801
|
if (!closedInvocation(opening, proof) || !constInitializer(proof.services.esTreeNodeToTSNodeMap.get(declaration))) return false;
|
|
@@ -3713,10 +3821,10 @@ function closedInvocation(node, proof) {
|
|
|
3713
3821
|
}
|
|
3714
3822
|
function independentInvocation(scope, proof) {
|
|
3715
3823
|
const block = scope.block;
|
|
3716
|
-
if (block.type !==
|
|
3824
|
+
if (block.type !== AST_NODE_TYPES27.ArrowFunctionExpression && block.type !== AST_NODE_TYPES27.FunctionDeclaration && block.type !== AST_NODE_TYPES27.FunctionExpression) return false;
|
|
3717
3825
|
if (block.async || block.generator || scope.set.get("arguments")?.references.some((reference) => !typeOnlyReference(reference))) return false;
|
|
3718
3826
|
for (const parameter of block.params) {
|
|
3719
|
-
if (parameter.type !==
|
|
3827
|
+
if (parameter.type !== AST_NODE_TYPES27.Identifier || parameter.name === "this") return false;
|
|
3720
3828
|
const binding3 = scope.set.get(parameter.name);
|
|
3721
3829
|
if (!binding3 || binding3.references.some((reference) => !typeOnlyReference(reference))) return false;
|
|
3722
3830
|
}
|
|
@@ -3724,16 +3832,16 @@ function independentInvocation(scope, proof) {
|
|
|
3724
3832
|
if (typeOnlyReference(reference)) return true;
|
|
3725
3833
|
const value = outerExpression(reference.identifier);
|
|
3726
3834
|
const parent = value.parent;
|
|
3727
|
-
const read = parent?.type ===
|
|
3835
|
+
const read = parent?.type === AST_NODE_TYPES27.MemberExpression && parent.object === value ? parent : value;
|
|
3728
3836
|
return primitiveValue(proof.services.esTreeNodeToTSNodeMap.get(read), proof, /* @__PURE__ */ new Set());
|
|
3729
3837
|
});
|
|
3730
3838
|
}
|
|
3731
3839
|
function consumedElementRead(node, fields2, reads) {
|
|
3732
3840
|
const identifier = outerExpression(node);
|
|
3733
3841
|
const props = identifier.parent;
|
|
3734
|
-
if (!props || props.type !==
|
|
3842
|
+
if (!props || props.type !== AST_NODE_TYPES27.MemberExpression || props.object !== identifier || props.optional || staticMemberKey(props) !== "props") return false;
|
|
3735
3843
|
const member3 = props.parent;
|
|
3736
|
-
if (member3.type !==
|
|
3844
|
+
if (member3.type !== AST_NODE_TYPES27.MemberExpression || member3.object !== props || member3.optional) return false;
|
|
3737
3845
|
const key = staticMemberKey(member3);
|
|
3738
3846
|
return key !== void 0 && reads.has(key) && readonlyFieldValue(member3, fields2);
|
|
3739
3847
|
}
|
|
@@ -3793,9 +3901,9 @@ var no_excess_jsx_props_default = createRule({
|
|
|
3793
3901
|
};
|
|
3794
3902
|
return {
|
|
3795
3903
|
JSXSpreadAttribute(node) {
|
|
3796
|
-
if (node.argument.type !==
|
|
3904
|
+
if (node.argument.type !== AST_NODE_TYPES27.ObjectExpression) return;
|
|
3797
3905
|
const opening = node.parent;
|
|
3798
|
-
if (!opening.selfClosing || opening.attributes.length !== 1 || opening.name.type !==
|
|
3906
|
+
if (!opening.selfClosing || opening.attributes.length !== 1 || opening.name.type !== AST_NODE_TYPES27.JSXIdentifier || /^[a-z]/u.test(opening.name.name)) return;
|
|
3799
3907
|
const declaration = privateElementDeclaration(opening);
|
|
3800
3908
|
if (!declaration) return;
|
|
3801
3909
|
const fields2 = literalFields(node.argument);
|
|
@@ -3816,7 +3924,7 @@ var no_excess_jsx_props_default = createRule({
|
|
|
3816
3924
|
});
|
|
3817
3925
|
|
|
3818
3926
|
// src/rules/prefer-native-fetch-in-server-actions.ts
|
|
3819
|
-
import { AST_NODE_TYPES as
|
|
3927
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES28 } from "@typescript-eslint/utils";
|
|
3820
3928
|
var KY_MODULE = /^ky(?:\/.*)?$/u;
|
|
3821
3929
|
var PREFER_NATIVE_FETCH_IN_SERVER_ACTIONS_DOCUMENTATION = {
|
|
3822
3930
|
defaultLevel: "warning",
|
|
@@ -3880,19 +3988,19 @@ var prefer_native_fetch_in_server_actions_default = createRule({
|
|
|
3880
3988
|
});
|
|
3881
3989
|
function hasUseServerDirective(program) {
|
|
3882
3990
|
for (const statement of program.body) {
|
|
3883
|
-
if (statement.type !==
|
|
3991
|
+
if (statement.type !== AST_NODE_TYPES28.ExpressionStatement || statement.directive === void 0) return false;
|
|
3884
3992
|
if (statement.directive === "use server") return true;
|
|
3885
3993
|
}
|
|
3886
3994
|
return false;
|
|
3887
3995
|
}
|
|
3888
3996
|
function isTypeOnly(node) {
|
|
3889
3997
|
return node.importKind === "type" || node.specifiers.length > 0 && node.specifiers.every(
|
|
3890
|
-
(specifier) => specifier.type ===
|
|
3998
|
+
(specifier) => specifier.type === AST_NODE_TYPES28.ImportSpecifier && specifier.importKind === "type"
|
|
3891
3999
|
);
|
|
3892
4000
|
}
|
|
3893
4001
|
|
|
3894
4002
|
// src/rules/no-credential-in-browser-storage.ts
|
|
3895
|
-
import { AST_NODE_TYPES as
|
|
4003
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES29, ASTUtils as ASTUtils17 } from "@typescript-eslint/utils";
|
|
3896
4004
|
|
|
3897
4005
|
// src/rules/_secret-names.ts
|
|
3898
4006
|
var SECRET_WORDS = /* @__PURE__ */ new Set([
|
|
@@ -4097,7 +4205,7 @@ var no_credential_in_browser_storage_default = createRule({
|
|
|
4097
4205
|
return {
|
|
4098
4206
|
CallExpression(node) {
|
|
4099
4207
|
const callee = unwrapExpression(node.callee);
|
|
4100
|
-
if (callee.type !==
|
|
4208
|
+
if (callee.type !== AST_NODE_TYPES29.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES29.Identifier || callee.property.name !== "setItem" || !isStorage(sourceCode, callee.object)) {
|
|
4101
4209
|
return;
|
|
4102
4210
|
}
|
|
4103
4211
|
const [key] = node.arguments;
|
|
@@ -4105,12 +4213,12 @@ var no_credential_in_browser_storage_default = createRule({
|
|
|
4105
4213
|
},
|
|
4106
4214
|
AssignmentExpression(node) {
|
|
4107
4215
|
const target = node.left;
|
|
4108
|
-
if (target.type !==
|
|
4216
|
+
if (target.type !== AST_NODE_TYPES29.MemberExpression) return;
|
|
4109
4217
|
if (isStorage(sourceCode, target.object)) {
|
|
4110
4218
|
report2(node, storedPropertyKey(sourceCode, target));
|
|
4111
4219
|
return;
|
|
4112
4220
|
}
|
|
4113
|
-
if (!target.computed && target.property.type ===
|
|
4221
|
+
if (!target.computed && target.property.type === AST_NODE_TYPES29.Identifier && target.property.name === "cookie" && globalMemberName(sourceCode, target.object) === "document") {
|
|
4114
4222
|
report2(node, cookieName(node.right));
|
|
4115
4223
|
}
|
|
4116
4224
|
}
|
|
@@ -4123,8 +4231,8 @@ function isStorage(sourceCode, node) {
|
|
|
4123
4231
|
}
|
|
4124
4232
|
function globalMemberName(sourceCode, node) {
|
|
4125
4233
|
const value = unwrapExpression(node);
|
|
4126
|
-
if (value.type ===
|
|
4127
|
-
if (value.type ===
|
|
4234
|
+
if (value.type === AST_NODE_TYPES29.Identifier) return isUnshadowed(sourceCode, value) ? value.name : null;
|
|
4235
|
+
if (value.type === AST_NODE_TYPES29.MemberExpression && !value.computed && value.object.type === AST_NODE_TYPES29.Identifier && GLOBAL_OBJECTS2.has(value.object.name) && value.property.type === AST_NODE_TYPES29.Identifier && isUnshadowed(sourceCode, value.object)) {
|
|
4128
4236
|
return value.property.name;
|
|
4129
4237
|
}
|
|
4130
4238
|
return null;
|
|
@@ -4134,24 +4242,24 @@ function isUnshadowed(sourceCode, node) {
|
|
|
4134
4242
|
return variable === null || variable.defs.length === 0;
|
|
4135
4243
|
}
|
|
4136
4244
|
function storedPropertyKey(sourceCode, target) {
|
|
4137
|
-
if (!target.computed) return target.property.type ===
|
|
4245
|
+
if (!target.computed) return target.property.type === AST_NODE_TYPES29.Identifier ? target.property.name : null;
|
|
4138
4246
|
return scopedStaticString(target.property, sourceCode);
|
|
4139
4247
|
}
|
|
4140
4248
|
function cookieName(value) {
|
|
4141
4249
|
let expression = unwrapExpression(value);
|
|
4142
|
-
while (expression.type ===
|
|
4250
|
+
while (expression.type === AST_NODE_TYPES29.BinaryExpression && expression.operator === "+") {
|
|
4143
4251
|
expression = unwrapExpression(expression.left);
|
|
4144
4252
|
}
|
|
4145
4253
|
let text = null;
|
|
4146
|
-
if (expression.type ===
|
|
4147
|
-
if (expression.type ===
|
|
4254
|
+
if (expression.type === AST_NODE_TYPES29.Literal && typeof expression.value === "string") text = expression.value;
|
|
4255
|
+
if (expression.type === AST_NODE_TYPES29.TemplateLiteral) text = expression.quasis[0]?.value.cooked ?? null;
|
|
4148
4256
|
if (text === null || !text.includes("=")) return null;
|
|
4149
4257
|
return text.slice(0, text.indexOf("=")).trim();
|
|
4150
4258
|
}
|
|
4151
4259
|
|
|
4152
4260
|
// src/rules/no-numeric-search-param-coercion.ts
|
|
4153
4261
|
import {
|
|
4154
|
-
AST_NODE_TYPES as
|
|
4262
|
+
AST_NODE_TYPES as AST_NODE_TYPES30,
|
|
4155
4263
|
ASTUtils as ASTUtils18,
|
|
4156
4264
|
ESLintUtils as ESLintUtils5
|
|
4157
4265
|
} from "@typescript-eslint/utils";
|
|
@@ -4233,10 +4341,10 @@ var no_numeric_search_param_coercion_default = createRule({
|
|
|
4233
4341
|
}
|
|
4234
4342
|
});
|
|
4235
4343
|
function isNumericParser(sourceCode, callee) {
|
|
4236
|
-
if (callee.type ===
|
|
4344
|
+
if (callee.type === AST_NODE_TYPES30.Identifier) {
|
|
4237
4345
|
return GLOBAL_PARSERS.has(callee.name) && isUnshadowedGlobal(sourceCode, callee);
|
|
4238
4346
|
}
|
|
4239
|
-
return callee.type ===
|
|
4347
|
+
return callee.type === AST_NODE_TYPES30.MemberExpression && !callee.computed && callee.object.type === AST_NODE_TYPES30.Identifier && callee.object.name === "Number" && callee.property.type === AST_NODE_TYPES30.Identifier && NUMBER_PARSERS.has(callee.property.name) && isUnshadowedGlobal(sourceCode, callee.object);
|
|
4240
4348
|
}
|
|
4241
4349
|
function isUnshadowedGlobal(sourceCode, node) {
|
|
4242
4350
|
const variable = ASTUtils18.findVariable(sourceCode.getScope(node), node.name);
|
|
@@ -4244,16 +4352,16 @@ function isUnshadowedGlobal(sourceCode, node) {
|
|
|
4244
4352
|
}
|
|
4245
4353
|
function searchParamGetCall(argument) {
|
|
4246
4354
|
let value = unwrapExpression(argument);
|
|
4247
|
-
if (value.type ===
|
|
4248
|
-
if (value.type ===
|
|
4249
|
-
if (value.type ===
|
|
4250
|
-
if (value.type !==
|
|
4355
|
+
if (value.type === AST_NODE_TYPES30.AwaitExpression) value = unwrapExpression(value.argument);
|
|
4356
|
+
if (value.type === AST_NODE_TYPES30.LogicalExpression && value.operator === "??") value = unwrapExpression(value.left);
|
|
4357
|
+
if (value.type === AST_NODE_TYPES30.ChainExpression) value = value.expression;
|
|
4358
|
+
if (value.type !== AST_NODE_TYPES30.CallExpression || value.callee.type !== AST_NODE_TYPES30.MemberExpression || value.callee.computed || value.callee.property.type !== AST_NODE_TYPES30.Identifier || value.callee.property.name !== "get") {
|
|
4251
4359
|
return null;
|
|
4252
4360
|
}
|
|
4253
4361
|
return value;
|
|
4254
4362
|
}
|
|
4255
4363
|
function isSearchParamReceiver(call, services) {
|
|
4256
|
-
if (call.callee.type !==
|
|
4364
|
+
if (call.callee.type !== AST_NODE_TYPES30.MemberExpression) return false;
|
|
4257
4365
|
const checker = services.program.getTypeChecker();
|
|
4258
4366
|
const type = checker.getNonNullableType(
|
|
4259
4367
|
checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(call.callee.object))
|
|
@@ -4265,7 +4373,7 @@ function isSearchParamReceiver(call, services) {
|
|
|
4265
4373
|
// package.json
|
|
4266
4374
|
var package_default = {
|
|
4267
4375
|
name: "@sarj/eslint-plugin",
|
|
4268
|
-
version: "16.
|
|
4376
|
+
version: "16.39.1",
|
|
4269
4377
|
packageManager: "npm@12.2.1",
|
|
4270
4378
|
description: "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
|
|
4271
4379
|
type: "module",
|
|
@@ -4353,6 +4461,7 @@ var package_default = {
|
|
|
4353
4461
|
"eslint-plugin-zod": "^5.2.2",
|
|
4354
4462
|
globals: "17.13.0",
|
|
4355
4463
|
jiti: "2.7.0",
|
|
4464
|
+
prettier: "3.9.10",
|
|
4356
4465
|
tsup: "9.0.0",
|
|
4357
4466
|
typescript: "npm:@typescript/typescript6@6.0.2",
|
|
4358
4467
|
"typescript-eslint": "^8.72.0",
|
|
@@ -4388,14 +4497,14 @@ var package_default = {
|
|
|
4388
4497
|
|
|
4389
4498
|
// src/rules/require-explicit-contract-implementation.ts
|
|
4390
4499
|
import {
|
|
4391
|
-
AST_NODE_TYPES as
|
|
4500
|
+
AST_NODE_TYPES as AST_NODE_TYPES32,
|
|
4392
4501
|
ESLintUtils as ESLintUtils6
|
|
4393
4502
|
} from "@typescript-eslint/utils";
|
|
4394
4503
|
import * as ts12 from "typescript";
|
|
4395
4504
|
|
|
4396
4505
|
// src/rules/_closed-nominal-inheritance-fix.ts
|
|
4397
4506
|
import {
|
|
4398
|
-
AST_NODE_TYPES as
|
|
4507
|
+
AST_NODE_TYPES as AST_NODE_TYPES31,
|
|
4399
4508
|
ASTUtils as ASTUtils19
|
|
4400
4509
|
} from "@typescript-eslint/utils";
|
|
4401
4510
|
import ts11 from "typescript";
|
|
@@ -4471,7 +4580,7 @@ function exactRejection(sourceCode, statement) {
|
|
|
4471
4580
|
const identifier = sourceCode.getNodeByRangeIndex(
|
|
4472
4581
|
rejected.expression.expression.getStart()
|
|
4473
4582
|
);
|
|
4474
|
-
return identifier?.type ===
|
|
4583
|
+
return identifier?.type === AST_NODE_TYPES31.Identifier && identifier.name === "TypeError" && (ASTUtils19.findVariable(sourceCode.getScope(identifier), identifier.name)?.defs.length ?? 0) === 0;
|
|
4475
4584
|
}
|
|
4476
4585
|
function exactConstruction(node, consumer, implementation) {
|
|
4477
4586
|
if (!ts11.isIdentifier(node.expression) || node.expression.text !== consumer || node.typeArguments !== void 0 || node.arguments?.length !== 1)
|
|
@@ -4852,7 +4961,7 @@ var require_explicit_contract_implementation_default = createRule({
|
|
|
4852
4961
|
return;
|
|
4853
4962
|
const parameters = signature.getParameters();
|
|
4854
4963
|
for (const [index, argument] of node.arguments.entries()) {
|
|
4855
|
-
if (argument.type !==
|
|
4964
|
+
if (argument.type !== AST_NODE_TYPES32.NewExpression) continue;
|
|
4856
4965
|
const parameter = parameters[index];
|
|
4857
4966
|
if (parameter === void 0) continue;
|
|
4858
4967
|
const tsArgument = services.esTreeNodeToTSNodeMap.get(argument);
|
|
@@ -4903,17 +5012,17 @@ import "@typescript-eslint/utils";
|
|
|
4903
5012
|
|
|
4904
5013
|
// src/rules/_existing-factory-contract-fix.ts
|
|
4905
5014
|
import {
|
|
4906
|
-
AST_NODE_TYPES as
|
|
5015
|
+
AST_NODE_TYPES as AST_NODE_TYPES33,
|
|
4907
5016
|
ASTUtils as ASTUtils20
|
|
4908
5017
|
} from "@typescript-eslint/utils";
|
|
4909
5018
|
function existingFactoryContractFix(sourceCode, candidate2) {
|
|
4910
5019
|
if (sourceCode.ast.body.length !== 4 || sourceCode.getAllComments().length !== 0)
|
|
4911
5020
|
return null;
|
|
4912
5021
|
const [contractStatement, worker, classStatement, factoryStatement] = sourceCode.ast.body;
|
|
4913
|
-
const contract = contractStatement?.type ===
|
|
4914
|
-
const implementation = classStatement?.type ===
|
|
4915
|
-
const factory = factoryStatement?.type ===
|
|
4916
|
-
if (contract?.type !==
|
|
5022
|
+
const contract = contractStatement?.type === AST_NODE_TYPES33.ExportNamedDeclaration ? contractStatement.declaration : null;
|
|
5023
|
+
const implementation = classStatement?.type === AST_NODE_TYPES33.ExportNamedDeclaration ? classStatement.declaration : classStatement;
|
|
5024
|
+
const factory = factoryStatement?.type === AST_NODE_TYPES33.ExportNamedDeclaration ? factoryStatement.declaration : null;
|
|
5025
|
+
if (contract?.type !== AST_NODE_TYPES33.TSTypeAliasDeclaration || worker?.type !== AST_NODE_TYPES33.TSInterfaceDeclaration || implementation?.type !== AST_NODE_TYPES33.ClassDeclaration || implementation !== candidate2 || !ordinaryClass(implementation) || !ordinaryFactory(factory))
|
|
4917
5026
|
return null;
|
|
4918
5027
|
const operation2 = contractOperation(contract);
|
|
4919
5028
|
if (operation2 === null || interfaceOperation(worker) !== operation2)
|
|
@@ -4932,17 +5041,17 @@ function ordinaryClass(node) {
|
|
|
4932
5041
|
return node.id !== null && !node.declare && !node.abstract && node.decorators.length === 0 && node.superClass === null && node.implements.length === 0 && node.typeParameters === void 0 && node.body.body.length === 2;
|
|
4933
5042
|
}
|
|
4934
5043
|
function ordinaryFactory(node) {
|
|
4935
|
-
return node?.type ===
|
|
5044
|
+
return node?.type === AST_NODE_TYPES33.FunctionDeclaration && node.id !== null && !node.declare && !node.async && !node.generator && node.typeParameters === void 0 && node.params.length === 1 && node.body.body.length === 1;
|
|
4936
5045
|
}
|
|
4937
5046
|
function interfaceOperation(node) {
|
|
4938
5047
|
return !node.declare && node.extends.length === 0 && node.typeParameters === void 0 ? singletonOperation(node.body.body) : null;
|
|
4939
5048
|
}
|
|
4940
5049
|
function contractOperation(node) {
|
|
4941
|
-
return !node.declare && node.typeParameters === void 0 && node.typeAnnotation.type ===
|
|
5050
|
+
return !node.declare && node.typeParameters === void 0 && node.typeAnnotation.type === AST_NODE_TYPES33.TSTypeLiteral ? singletonOperation(node.typeAnnotation.members) : null;
|
|
4942
5051
|
}
|
|
4943
5052
|
function singletonOperation(members) {
|
|
4944
5053
|
const member3 = members[0];
|
|
4945
|
-
return members.length === 1 && member3?.type ===
|
|
5054
|
+
return members.length === 1 && member3?.type === AST_NODE_TYPES33.TSMethodSignature && member3.kind === "method" && !member3.computed && !member3.optional && member3.key.type === AST_NODE_TYPES33.Identifier && member3.params.length === 0 && member3.typeParameters === void 0 && member3.returnType?.typeAnnotation.type === AST_NODE_TYPES33.TSVoidKeyword ? member3.key.name : null;
|
|
4946
5055
|
}
|
|
4947
5056
|
function uniqueDeclarations(sourceCode, declarations) {
|
|
4948
5057
|
const names = declarations.flatMap(
|
|
@@ -4961,47 +5070,47 @@ function sameBinding(sourceCode, reference, declaration) {
|
|
|
4961
5070
|
}
|
|
4962
5071
|
function retainedWorker(sourceCode, implementation, worker) {
|
|
4963
5072
|
const constructor = implementation.body.body[0];
|
|
4964
|
-
if (constructor?.type !==
|
|
5073
|
+
if (constructor?.type !== AST_NODE_TYPES33.MethodDefinition || constructor.value.type !== AST_NODE_TYPES33.FunctionExpression || constructor.kind !== "constructor" || constructor.computed || constructor.static || constructor.decorators.length !== 0 || constructor.optional || constructor.accessibility !== void 0 && constructor.accessibility !== "public" || constructor.value.async || constructor.value.generator || constructor.value.typeParameters !== void 0 || constructor.value.returnType !== void 0 || constructor.value.body.body.length !== 0 || constructor.value.params.length !== 1)
|
|
4965
5074
|
return null;
|
|
4966
5075
|
const property = constructor.value.params[0];
|
|
4967
|
-
if (property?.type !==
|
|
5076
|
+
if (property?.type !== AST_NODE_TYPES33.TSParameterProperty || property.accessibility !== "private" || !property.readonly || property.override || property.decorators.length !== 0 || property.parameter.type !== AST_NODE_TYPES33.Identifier || property.parameter.optional || !typeReference(sourceCode, property.parameter.typeAnnotation, worker))
|
|
4968
5077
|
return null;
|
|
4969
5078
|
return property.parameter.name;
|
|
4970
5079
|
}
|
|
4971
5080
|
function typeReference(sourceCode, annotation, declaration) {
|
|
4972
5081
|
const type = annotation?.typeAnnotation;
|
|
4973
|
-
return type?.type ===
|
|
5082
|
+
return type?.type === AST_NODE_TYPES33.TSTypeReference && type.typeArguments === void 0 && type.typeName.type === AST_NODE_TYPES33.Identifier && sameBinding(sourceCode, type.typeName, declaration);
|
|
4974
5083
|
}
|
|
4975
5084
|
function forwardsOperation(implementation, field, operation2) {
|
|
4976
5085
|
const method = implementation.body.body[1];
|
|
4977
|
-
if (method?.type !==
|
|
5086
|
+
if (method?.type !== AST_NODE_TYPES33.MethodDefinition || method.kind !== "method" || method.value.type !== AST_NODE_TYPES33.FunctionExpression || method.computed || method.static || method.optional || method.override || method.decorators.length !== 0 || method.accessibility !== void 0 && method.accessibility !== "public" || method.key.type !== AST_NODE_TYPES33.Identifier || method.key.name !== operation2 || method.value.async || method.value.generator || method.value.typeParameters !== void 0 || method.value.params.length !== 0 || method.value.body.body.length !== 1 || method.value.returnType?.typeAnnotation.type !== AST_NODE_TYPES33.TSVoidKeyword)
|
|
4978
5087
|
return false;
|
|
4979
5088
|
const statement = method.value.body.body[0];
|
|
4980
|
-
const call = statement?.type ===
|
|
4981
|
-
return call?.type ===
|
|
5089
|
+
const call = statement?.type === AST_NODE_TYPES33.ExpressionStatement ? statement.expression : null;
|
|
5090
|
+
return call?.type === AST_NODE_TYPES33.CallExpression && !call.optional && call.typeArguments === void 0 && call.arguments.length === 0 && forwardedMember(call.callee, field, operation2);
|
|
4982
5091
|
}
|
|
4983
5092
|
function forwardedMember(node, field, operation2) {
|
|
4984
|
-
if (node.type !==
|
|
5093
|
+
if (node.type !== AST_NODE_TYPES33.MemberExpression || node.computed || node.optional || node.property.type !== AST_NODE_TYPES33.Identifier || node.property.name !== operation2)
|
|
4985
5094
|
return false;
|
|
4986
5095
|
const receiver = node.object;
|
|
4987
|
-
return receiver.type ===
|
|
5096
|
+
return receiver.type === AST_NODE_TYPES33.MemberExpression && !receiver.computed && !receiver.optional && receiver.object.type === AST_NODE_TYPES33.ThisExpression && receiver.property.type === AST_NODE_TYPES33.Identifier && receiver.property.name === field;
|
|
4988
5097
|
}
|
|
4989
5098
|
function factoryAuthority(sourceCode, factory, contract, worker, implementation) {
|
|
4990
5099
|
const parameter = factory.params[0];
|
|
4991
|
-
if (parameter?.type !==
|
|
5100
|
+
if (parameter?.type !== AST_NODE_TYPES33.Identifier || parameter.optional || !typeReference(sourceCode, parameter.typeAnnotation, worker) || !typeReference(sourceCode, factory.returnType, contract))
|
|
4992
5101
|
return false;
|
|
4993
5102
|
const statement = factory.body.body[0];
|
|
4994
|
-
const constructed = statement?.type ===
|
|
4995
|
-
if (constructed?.type !==
|
|
5103
|
+
const constructed = statement?.type === AST_NODE_TYPES33.ReturnStatement ? statement.argument : null;
|
|
5104
|
+
if (constructed?.type !== AST_NODE_TYPES33.NewExpression || constructed.typeArguments !== void 0 || constructed.callee.type !== AST_NODE_TYPES33.Identifier || !sameBinding(sourceCode, constructed.callee, implementation) || constructed.arguments.length !== 1)
|
|
4996
5105
|
return false;
|
|
4997
5106
|
const argument = constructed.arguments[0];
|
|
4998
|
-
return argument?.type ===
|
|
5107
|
+
return argument?.type === AST_NODE_TYPES33.Identifier && argument.name === parameter.name && sameBinding(sourceCode, argument, factory);
|
|
4999
5108
|
}
|
|
5000
5109
|
|
|
5001
5110
|
// src/rules/require-port-for-service.ts
|
|
5002
5111
|
import {
|
|
5003
5112
|
ASTUtils as ASTUtils21,
|
|
5004
|
-
AST_NODE_TYPES as
|
|
5113
|
+
AST_NODE_TYPES as AST_NODE_TYPES34
|
|
5005
5114
|
} from "@typescript-eslint/utils";
|
|
5006
5115
|
var REQUIRE_PORT_FOR_SERVICE_DOCUMENTATION = {
|
|
5007
5116
|
summary: "Advise when an exported service with injected collaborators has public methods not covered by its declared ports.",
|
|
@@ -5086,50 +5195,50 @@ var STORAGE_ASSIGNMENT_OPERATORS = /* @__PURE__ */ new Set([
|
|
|
5086
5195
|
"||="
|
|
5087
5196
|
]);
|
|
5088
5197
|
var staticMemberName = (member3) => {
|
|
5089
|
-
if (member3.property.type ===
|
|
5198
|
+
if (member3.property.type === AST_NODE_TYPES34.PrivateIdentifier)
|
|
5090
5199
|
return `#${member3.property.name}`;
|
|
5091
5200
|
return ASTUtils21.getPropertyName(member3);
|
|
5092
5201
|
};
|
|
5093
5202
|
var detachedValueExports = (program) => {
|
|
5094
5203
|
const names = /* @__PURE__ */ new Set();
|
|
5095
5204
|
for (const statement of program.body) {
|
|
5096
|
-
if (statement.type ===
|
|
5205
|
+
if (statement.type === AST_NODE_TYPES34.ExportNamedDeclaration && statement.declaration === null && statement.source === null && statement.exportKind !== "type") {
|
|
5097
5206
|
for (const specifier of statement.specifiers) {
|
|
5098
5207
|
if (specifier.exportKind !== "type") names.add(specifier.local.name);
|
|
5099
5208
|
}
|
|
5100
|
-
} else if (statement.type ===
|
|
5209
|
+
} else if (statement.type === AST_NODE_TYPES34.ExportDefaultDeclaration && statement.declaration.type === AST_NODE_TYPES34.Identifier) {
|
|
5101
5210
|
names.add(statement.declaration.name);
|
|
5102
|
-
} else if (statement.type ===
|
|
5211
|
+
} else if (statement.type === AST_NODE_TYPES34.TSExportAssignment && statement.expression.type === AST_NODE_TYPES34.Identifier) {
|
|
5103
5212
|
names.add(statement.expression.name);
|
|
5104
5213
|
}
|
|
5105
5214
|
}
|
|
5106
5215
|
return names;
|
|
5107
5216
|
};
|
|
5108
|
-
var isExportedClass = (node, detached) => node.parent.type ===
|
|
5217
|
+
var isExportedClass = (node, detached) => node.parent.type === AST_NODE_TYPES34.ExportNamedDeclaration || node.parent.type === AST_NODE_TYPES34.ExportDefaultDeclaration || node.id !== null && detached.has(node.id.name);
|
|
5109
5218
|
var createExportedServiceClassResolver = (program) => {
|
|
5110
5219
|
const detached = detachedValueExports(program);
|
|
5111
5220
|
return (node) => isExportedClass(node, detached);
|
|
5112
5221
|
};
|
|
5113
5222
|
var readTypeReference = (annotation) => {
|
|
5114
|
-
if (annotation?.type ===
|
|
5223
|
+
if (annotation?.type === AST_NODE_TYPES34.TSUnionType) {
|
|
5115
5224
|
const members = annotation.types.filter(
|
|
5116
|
-
(member3) => member3.type !==
|
|
5225
|
+
(member3) => member3.type !== AST_NODE_TYPES34.TSUndefinedKeyword && member3.type !== AST_NODE_TYPES34.TSNullKeyword
|
|
5117
5226
|
);
|
|
5118
5227
|
annotation = members.length === 1 ? members[0] : void 0;
|
|
5119
5228
|
}
|
|
5120
|
-
if (annotation === void 0 || annotation.type !==
|
|
5229
|
+
if (annotation === void 0 || annotation.type !== AST_NODE_TYPES34.TSTypeReference)
|
|
5121
5230
|
return null;
|
|
5122
5231
|
const { typeName } = annotation;
|
|
5123
|
-
const rightmost = typeName.type ===
|
|
5232
|
+
const rightmost = typeName.type === AST_NODE_TYPES34.Identifier ? typeName.name : typeName.type === AST_NODE_TYPES34.TSQualifiedName ? typeName.right.name : null;
|
|
5124
5233
|
if (rightmost === null) return null;
|
|
5125
5234
|
return { typeName: rightmost, display: qualifiedName(typeName) };
|
|
5126
5235
|
};
|
|
5127
|
-
var qualifiedName = (name) => name.type ===
|
|
5236
|
+
var qualifiedName = (name) => name.type === AST_NODE_TYPES34.Identifier ? name.name : name.type === AST_NODE_TYPES34.TSQualifiedName ? `${qualifiedName(name.left)}.${name.right.name}` : "";
|
|
5128
5237
|
var propertySignatureTypes = (members) => {
|
|
5129
5238
|
const types = /* @__PURE__ */ new Map();
|
|
5130
5239
|
for (const member3 of members) {
|
|
5131
|
-
if (member3.type !==
|
|
5132
|
-
if (member3.computed || member3.key.type !==
|
|
5240
|
+
if (member3.type !== AST_NODE_TYPES34.TSPropertySignature) continue;
|
|
5241
|
+
if (member3.computed || member3.key.type !== AST_NODE_TYPES34.Identifier)
|
|
5133
5242
|
continue;
|
|
5134
5243
|
const reference = readTypeReference(member3.typeAnnotation?.typeAnnotation);
|
|
5135
5244
|
if (reference === null) continue;
|
|
@@ -5141,18 +5250,18 @@ var fileTypeIndex = (program) => {
|
|
|
5141
5250
|
const objects = /* @__PURE__ */ new Map();
|
|
5142
5251
|
const functionAliases = localFunctionAliases(program);
|
|
5143
5252
|
function collectDeclaredType(statement) {
|
|
5144
|
-
const declaration = statement.type ===
|
|
5145
|
-
if (declaration?.type ===
|
|
5253
|
+
const declaration = statement.type === AST_NODE_TYPES34.ExportNamedDeclaration ? statement.declaration : statement;
|
|
5254
|
+
if (declaration?.type === AST_NODE_TYPES34.TSInterfaceDeclaration) {
|
|
5146
5255
|
objects.set(
|
|
5147
5256
|
declaration.id.name,
|
|
5148
5257
|
propertySignatureTypes(declaration.body.body)
|
|
5149
5258
|
);
|
|
5150
5259
|
return;
|
|
5151
5260
|
}
|
|
5152
|
-
if (declaration?.type !==
|
|
5261
|
+
if (declaration?.type !== AST_NODE_TYPES34.TSTypeAliasDeclaration) return;
|
|
5153
5262
|
const aliased = declaration.typeAnnotation;
|
|
5154
|
-
const literals = aliased.type ===
|
|
5155
|
-
(part) => part.type ===
|
|
5263
|
+
const literals = aliased.type === AST_NODE_TYPES34.TSTypeLiteral ? [aliased] : aliased.type === AST_NODE_TYPES34.TSIntersectionType ? aliased.types.filter(
|
|
5264
|
+
(part) => part.type === AST_NODE_TYPES34.TSTypeLiteral
|
|
5156
5265
|
) : [];
|
|
5157
5266
|
if (literals.length === 0) return;
|
|
5158
5267
|
const merged = /* @__PURE__ */ new Map();
|
|
@@ -5172,12 +5281,12 @@ function localFunctionAliases(program) {
|
|
|
5172
5281
|
const names = /* @__PURE__ */ new Set();
|
|
5173
5282
|
const parents = /* @__PURE__ */ new Map();
|
|
5174
5283
|
for (const statement of program.body) {
|
|
5175
|
-
const declaration = statement.type ===
|
|
5176
|
-
if (declaration?.type !==
|
|
5284
|
+
const declaration = statement.type === AST_NODE_TYPES34.ExportNamedDeclaration ? statement.declaration : statement;
|
|
5285
|
+
if (declaration?.type !== AST_NODE_TYPES34.TSTypeAliasDeclaration) continue;
|
|
5177
5286
|
const annotation = declaration.typeAnnotation;
|
|
5178
|
-
if (annotation.type ===
|
|
5287
|
+
if (annotation.type === AST_NODE_TYPES34.TSFunctionType || annotation.type === AST_NODE_TYPES34.TSConstructorType)
|
|
5179
5288
|
names.add(declaration.id.name);
|
|
5180
|
-
if (annotation.type ===
|
|
5289
|
+
if (annotation.type === AST_NODE_TYPES34.TSTypeReference && annotation.typeName.type === AST_NODE_TYPES34.Identifier)
|
|
5181
5290
|
parents.set(declaration.id.name, annotation.typeName.name);
|
|
5182
5291
|
}
|
|
5183
5292
|
for (let pass = 0; pass < parents.size; pass += 1) {
|
|
@@ -5213,32 +5322,32 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
5213
5322
|
function scanStoredFields(body4) {
|
|
5214
5323
|
const pending = [...body4.body];
|
|
5215
5324
|
function recordStoredField(current) {
|
|
5216
|
-
if (current.type ===
|
|
5325
|
+
if (current.type === AST_NODE_TYPES34.ArrowFunctionExpression || current.type === AST_NODE_TYPES34.FunctionExpression || current.type === AST_NODE_TYPES34.FunctionDeclaration || current.type === AST_NODE_TYPES34.ClassExpression || current.type === AST_NODE_TYPES34.ClassDeclaration)
|
|
5217
5326
|
return;
|
|
5218
|
-
if (current.type ===
|
|
5327
|
+
if (current.type === AST_NODE_TYPES34.VariableDeclarator && current.id.type === AST_NODE_TYPES34.Identifier)
|
|
5219
5328
|
localBindings2.add(current.id.name);
|
|
5220
|
-
const expression = current.type ===
|
|
5329
|
+
const expression = current.type === AST_NODE_TYPES34.AssignmentExpression ? current : null;
|
|
5221
5330
|
const storedField = writtenInstanceField(current);
|
|
5222
5331
|
if (storedField !== null) {
|
|
5223
5332
|
if (writtenFieldNames.has(storedField))
|
|
5224
5333
|
unstableFieldNames.add(storedField);
|
|
5225
5334
|
writtenFieldNames.add(storedField);
|
|
5226
|
-
if (expression?.operator !== "=" || expression.parent.type !==
|
|
5335
|
+
if (expression?.operator !== "=" || expression.parent.type !== AST_NODE_TYPES34.ExpressionStatement || expression.parent.parent !== body4)
|
|
5227
5336
|
unstableFieldNames.add(storedField);
|
|
5228
5337
|
}
|
|
5229
|
-
if (expression?.type !==
|
|
5338
|
+
if (expression?.type !== AST_NODE_TYPES34.AssignmentExpression || !STORAGE_ASSIGNMENT_OPERATORS.has(expression.operator) || expression.left.type !== AST_NODE_TYPES34.MemberExpression || expression.left.object.type !== AST_NODE_TYPES34.ThisExpression || storedField === null) {
|
|
5230
5339
|
enqueueChildren(current);
|
|
5231
5340
|
return;
|
|
5232
5341
|
}
|
|
5233
5342
|
const source = unwrapExpression(expression.right);
|
|
5234
|
-
if (source.type ===
|
|
5343
|
+
if (source.type === AST_NODE_TYPES34.NewExpression) {
|
|
5235
5344
|
constructedFields += 1;
|
|
5236
5345
|
constructedFieldNames.add(storedField);
|
|
5237
|
-
} else if (source.type ===
|
|
5346
|
+
} else if (source.type === AST_NODE_TYPES34.Identifier) {
|
|
5238
5347
|
const fields2 = storedFieldsFrom.get(source.name) ?? /* @__PURE__ */ new Set();
|
|
5239
5348
|
fields2.add(storedField);
|
|
5240
5349
|
storedFieldsFrom.set(source.name, fields2);
|
|
5241
|
-
} else if (source.type ===
|
|
5350
|
+
} else if (source.type === AST_NODE_TYPES34.MemberExpression && source.object.type === AST_NODE_TYPES34.Identifier) {
|
|
5242
5351
|
const fields2 = storedFieldsFrom.get(source.object.name) ?? /* @__PURE__ */ new Set();
|
|
5243
5352
|
fields2.add(storedField);
|
|
5244
5353
|
storedFieldsFrom.set(source.object.name, fields2);
|
|
@@ -5273,7 +5382,7 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
5273
5382
|
)) {
|
|
5274
5383
|
if (localBindings2.has(reference.name)) continue;
|
|
5275
5384
|
let fields2 = reference.fields;
|
|
5276
|
-
if (parameter.type ===
|
|
5385
|
+
if (parameter.type === AST_NODE_TYPES34.TSParameterProperty) {
|
|
5277
5386
|
if (writtenFieldNames.has(reference.name)) continue;
|
|
5278
5387
|
fields2 = [reference.name];
|
|
5279
5388
|
} else if (fields2.length === 0)
|
|
@@ -5296,8 +5405,8 @@ var readConstructor = (ctor, declared, typeParameters) => {
|
|
|
5296
5405
|
};
|
|
5297
5406
|
var parameterCollaborators = (parameter, declared, storedMemberFieldsFrom) => {
|
|
5298
5407
|
let target = parameter;
|
|
5299
|
-
if (target.type ===
|
|
5300
|
-
if (target.type ===
|
|
5408
|
+
if (target.type === AST_NODE_TYPES34.AssignmentPattern) target = target.left;
|
|
5409
|
+
if (target.type === AST_NODE_TYPES34.ObjectPattern) {
|
|
5301
5410
|
return objectPatternCollaborators(target, declared);
|
|
5302
5411
|
}
|
|
5303
5412
|
const named3 = namedParameterCollaborator(parameter);
|
|
@@ -5307,10 +5416,10 @@ var parameterCollaborators = (parameter, declared, storedMemberFieldsFrom) => {
|
|
|
5307
5416
|
};
|
|
5308
5417
|
var namedBagCollaborators = (annotated, declared, storedMemberFieldsFrom) => {
|
|
5309
5418
|
let target = annotated;
|
|
5310
|
-
if (target.type ===
|
|
5419
|
+
if (target.type === AST_NODE_TYPES34.TSParameterProperty)
|
|
5311
5420
|
target = target.parameter;
|
|
5312
|
-
if (target.type ===
|
|
5313
|
-
if (target.type !==
|
|
5421
|
+
if (target.type === AST_NODE_TYPES34.AssignmentPattern) target = target.left;
|
|
5422
|
+
if (target.type !== AST_NODE_TYPES34.Identifier) return [];
|
|
5314
5423
|
const members = bagMemberTypes(
|
|
5315
5424
|
target.typeAnnotation?.typeAnnotation,
|
|
5316
5425
|
declared
|
|
@@ -5329,10 +5438,10 @@ var namedBagCollaborators = (annotated, declared, storedMemberFieldsFrom) => {
|
|
|
5329
5438
|
};
|
|
5330
5439
|
var namedParameterCollaborator = (annotated) => {
|
|
5331
5440
|
let target = annotated;
|
|
5332
|
-
if (target.type ===
|
|
5441
|
+
if (target.type === AST_NODE_TYPES34.TSParameterProperty)
|
|
5333
5442
|
target = target.parameter;
|
|
5334
|
-
if (target.type ===
|
|
5335
|
-
if (target.type !==
|
|
5443
|
+
if (target.type === AST_NODE_TYPES34.AssignmentPattern) target = target.left;
|
|
5444
|
+
if (target.type !== AST_NODE_TYPES34.Identifier) return null;
|
|
5336
5445
|
const reference = readTypeReference(target.typeAnnotation?.typeAnnotation);
|
|
5337
5446
|
if (reference === null) return null;
|
|
5338
5447
|
return { name: target.name, ...reference, fields: [] };
|
|
@@ -5344,12 +5453,12 @@ var objectPatternCollaborators = (pattern, declared) => {
|
|
|
5344
5453
|
if (members === null) return [];
|
|
5345
5454
|
const collaborators = [];
|
|
5346
5455
|
for (const property of pattern.properties) {
|
|
5347
|
-
if (property.type !==
|
|
5456
|
+
if (property.type !== AST_NODE_TYPES34.Property || property.computed)
|
|
5348
5457
|
continue;
|
|
5349
|
-
if (property.key.type !==
|
|
5458
|
+
if (property.key.type !== AST_NODE_TYPES34.Identifier) continue;
|
|
5350
5459
|
const key = property.key.name;
|
|
5351
|
-
const bound = property.value.type ===
|
|
5352
|
-
if (bound.type !==
|
|
5460
|
+
const bound = property.value.type === AST_NODE_TYPES34.AssignmentPattern ? property.value.left : property.value;
|
|
5461
|
+
if (bound.type !== AST_NODE_TYPES34.Identifier) continue;
|
|
5353
5462
|
if (CONFIGISH_NAME_RE.test(key)) continue;
|
|
5354
5463
|
const reference = members.get(key);
|
|
5355
5464
|
if (reference === void 0) continue;
|
|
@@ -5359,22 +5468,22 @@ var objectPatternCollaborators = (pattern, declared) => {
|
|
|
5359
5468
|
};
|
|
5360
5469
|
var bagMemberTypes = (annotation, declared) => {
|
|
5361
5470
|
if (annotation === void 0) return null;
|
|
5362
|
-
if (annotation.type ===
|
|
5471
|
+
if (annotation.type === AST_NODE_TYPES34.TSTypeLiteral) {
|
|
5363
5472
|
return propertySignatureTypes(annotation.members);
|
|
5364
5473
|
}
|
|
5365
|
-
if (annotation.type !==
|
|
5474
|
+
if (annotation.type !== AST_NODE_TYPES34.TSTypeReference || annotation.typeName.type !== AST_NODE_TYPES34.Identifier) {
|
|
5366
5475
|
return null;
|
|
5367
5476
|
}
|
|
5368
5477
|
return declared().objects.get(annotation.typeName.name) ?? null;
|
|
5369
5478
|
};
|
|
5370
5479
|
var isFrameworkWiring = (body3) => subtreeHas(body3, (node) => {
|
|
5371
|
-
if (node.type ===
|
|
5480
|
+
if (node.type === AST_NODE_TYPES34.CallExpression) {
|
|
5372
5481
|
const { callee } = node;
|
|
5373
|
-
if (callee.type ===
|
|
5482
|
+
if (callee.type === AST_NODE_TYPES34.Identifier)
|
|
5374
5483
|
return callee.name === ROUTER_FACTORY_NAME;
|
|
5375
|
-
return callee.type ===
|
|
5484
|
+
return callee.type === AST_NODE_TYPES34.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES34.Identifier && callee.property.name === ROUTER_FACTORY_NAME;
|
|
5376
5485
|
}
|
|
5377
|
-
return node.type ===
|
|
5486
|
+
return node.type === AST_NODE_TYPES34.TSTypeReference && node.typeName.type === AST_NODE_TYPES34.TSQualifiedName && FRAMEWORK_HTTP_TYPES.has(node.typeName.right.name);
|
|
5378
5487
|
});
|
|
5379
5488
|
var subtreeHas = (root, found) => {
|
|
5380
5489
|
let hit = false;
|
|
@@ -5394,26 +5503,26 @@ var subtreeHas = (root, found) => {
|
|
|
5394
5503
|
};
|
|
5395
5504
|
var invokedInstanceField = (call) => {
|
|
5396
5505
|
let callee = unwrapExpression(call.callee);
|
|
5397
|
-
while (callee.type ===
|
|
5506
|
+
while (callee.type === AST_NODE_TYPES34.ChainExpression)
|
|
5398
5507
|
callee = unwrapExpression(callee.expression);
|
|
5399
5508
|
const direct = instanceField(callee);
|
|
5400
5509
|
if (direct !== null) return direct;
|
|
5401
|
-
return callee.type ===
|
|
5510
|
+
return callee.type === AST_NODE_TYPES34.MemberExpression ? instanceField(unwrapExpression(callee.object)) : null;
|
|
5402
5511
|
};
|
|
5403
5512
|
var instanceField = (candidate2) => {
|
|
5404
5513
|
let node = candidate2;
|
|
5405
|
-
while (node.type ===
|
|
5514
|
+
while (node.type === AST_NODE_TYPES34.ChainExpression || node.type === AST_NODE_TYPES34.TSAsExpression || node.type === AST_NODE_TYPES34.TSNonNullExpression || node.type === AST_NODE_TYPES34.TSSatisfiesExpression || node.type === AST_NODE_TYPES34.TSTypeAssertion)
|
|
5406
5515
|
node = node.expression;
|
|
5407
|
-
return node.type ===
|
|
5516
|
+
return node.type === AST_NODE_TYPES34.MemberExpression && node.object.type === AST_NODE_TYPES34.ThisExpression ? staticMemberName(node) : null;
|
|
5408
5517
|
};
|
|
5409
5518
|
function writtenInstanceField(node) {
|
|
5410
|
-
if (node.type ===
|
|
5519
|
+
if (node.type === AST_NODE_TYPES34.AssignmentExpression || node.type === AST_NODE_TYPES34.ForOfStatement || node.type === AST_NODE_TYPES34.ForInStatement)
|
|
5411
5520
|
return instanceField(node.left);
|
|
5412
|
-
if (node.type ===
|
|
5521
|
+
if (node.type === AST_NODE_TYPES34.UpdateExpression)
|
|
5413
5522
|
return instanceField(node.argument);
|
|
5414
|
-
if (node.type ===
|
|
5523
|
+
if (node.type === AST_NODE_TYPES34.UnaryExpression && node.operator === "delete")
|
|
5415
5524
|
return instanceField(node.argument);
|
|
5416
|
-
if (node.type ===
|
|
5525
|
+
if (node.type === AST_NODE_TYPES34.MemberExpression && isDestructuredWriteTarget(node))
|
|
5417
5526
|
return instanceField(node);
|
|
5418
5527
|
return null;
|
|
5419
5528
|
}
|
|
@@ -5422,39 +5531,39 @@ function isDestructuredWriteTarget(node) {
|
|
|
5422
5531
|
let target = access;
|
|
5423
5532
|
for (; ; ) {
|
|
5424
5533
|
const parent = target.parent;
|
|
5425
|
-
if (parent.type ===
|
|
5534
|
+
if (parent.type === AST_NODE_TYPES34.Property && parent.value === target && parent.parent.type === AST_NODE_TYPES34.ObjectPattern) {
|
|
5426
5535
|
target = parent.parent;
|
|
5427
5536
|
continue;
|
|
5428
5537
|
}
|
|
5429
|
-
if (parent.type ===
|
|
5538
|
+
if (parent.type === AST_NODE_TYPES34.ArrayPattern || parent.type === AST_NODE_TYPES34.ObjectPattern || parent.type === AST_NODE_TYPES34.RestElement && parent.argument === target || parent.type === AST_NODE_TYPES34.AssignmentPattern && parent.left === target) {
|
|
5430
5539
|
target = parent;
|
|
5431
5540
|
continue;
|
|
5432
5541
|
}
|
|
5433
|
-
return target !== access && (parent.type ===
|
|
5542
|
+
return target !== access && (parent.type === AST_NODE_TYPES34.AssignmentExpression || parent.type === AST_NODE_TYPES34.ForOfStatement || parent.type === AST_NODE_TYPES34.ForInStatement) && parent.left === target;
|
|
5434
5543
|
}
|
|
5435
5544
|
}
|
|
5436
5545
|
var behaviorallyInvokedFields = (body3) => {
|
|
5437
5546
|
const invoked = /* @__PURE__ */ new Set();
|
|
5438
5547
|
const visit = (current) => {
|
|
5439
|
-
if (current.type ===
|
|
5548
|
+
if (current.type === AST_NODE_TYPES34.ClassDeclaration || current.type === AST_NODE_TYPES34.ClassExpression || current.type === AST_NODE_TYPES34.FunctionDeclaration || current.type === AST_NODE_TYPES34.FunctionExpression)
|
|
5440
5549
|
return;
|
|
5441
|
-
if (current.type ===
|
|
5550
|
+
if (current.type === AST_NODE_TYPES34.CallExpression) {
|
|
5442
5551
|
const field = invokedInstanceField(current);
|
|
5443
5552
|
if (field !== null) invoked.add(field);
|
|
5444
5553
|
}
|
|
5445
5554
|
forEachOwnAstChild(current, visit);
|
|
5446
5555
|
};
|
|
5447
5556
|
for (const member3 of body3.body) {
|
|
5448
|
-
if (member3.type ===
|
|
5449
|
-
if (member3.type ===
|
|
5557
|
+
if (member3.type === AST_NODE_TYPES34.StaticBlock || member3.static) continue;
|
|
5558
|
+
if (member3.type === AST_NODE_TYPES34.MethodDefinition) {
|
|
5450
5559
|
if (member3.value.body !== null && member3.value.body !== void 0)
|
|
5451
5560
|
visit(member3.value.body);
|
|
5452
5561
|
continue;
|
|
5453
5562
|
}
|
|
5454
|
-
if (member3.type !==
|
|
5563
|
+
if (member3.type !== AST_NODE_TYPES34.PropertyDefinition || member3.value === null)
|
|
5455
5564
|
continue;
|
|
5456
5565
|
visit(
|
|
5457
|
-
member3.value.type ===
|
|
5566
|
+
member3.value.type === AST_NODE_TYPES34.ArrowFunctionExpression ? member3.value.body : member3.value
|
|
5458
5567
|
);
|
|
5459
5568
|
}
|
|
5460
5569
|
return invoked;
|
|
@@ -5474,8 +5583,8 @@ var isTransportWrapper = (className, collaborators, program) => {
|
|
|
5474
5583
|
var fileInterfaceNames = (program) => {
|
|
5475
5584
|
const names = [];
|
|
5476
5585
|
for (const statement of program.body) {
|
|
5477
|
-
const declaration = statement.type ===
|
|
5478
|
-
if (declaration?.type ===
|
|
5586
|
+
const declaration = statement.type === AST_NODE_TYPES34.ExportNamedDeclaration ? statement.declaration : statement;
|
|
5587
|
+
if (declaration?.type === AST_NODE_TYPES34.TSInterfaceDeclaration)
|
|
5479
5588
|
names.push(declaration.id.name);
|
|
5480
5589
|
}
|
|
5481
5590
|
return names;
|
|
@@ -5483,22 +5592,22 @@ var fileInterfaceNames = (program) => {
|
|
|
5483
5592
|
var publicMethodNames = (body3, functionAliases) => {
|
|
5484
5593
|
const names = [];
|
|
5485
5594
|
function collectPublicCallable(member3) {
|
|
5486
|
-
if (member3.type ===
|
|
5595
|
+
if (member3.type === AST_NODE_TYPES34.PropertyDefinition) {
|
|
5487
5596
|
if (member3.static || member3.accessibility === "private" || member3.accessibility === "protected")
|
|
5488
5597
|
return;
|
|
5489
|
-
if (member3.key.type ===
|
|
5490
|
-
if (member3.value?.type !==
|
|
5598
|
+
if (member3.key.type === AST_NODE_TYPES34.PrivateIdentifier) return;
|
|
5599
|
+
if (member3.value?.type !== AST_NODE_TYPES34.ArrowFunctionExpression && member3.value?.type !== AST_NODE_TYPES34.FunctionExpression && member3.typeAnnotation?.typeAnnotation.type !== AST_NODE_TYPES34.TSFunctionType && !(member3.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES34.TSTypeReference && member3.typeAnnotation.typeAnnotation.typeName.type === AST_NODE_TYPES34.Identifier && functionAliases.has(
|
|
5491
5600
|
member3.typeAnnotation.typeAnnotation.typeName.name
|
|
5492
5601
|
)))
|
|
5493
5602
|
return;
|
|
5494
5603
|
names.push(declaredMemberName(member3) ?? "\u2026");
|
|
5495
5604
|
return;
|
|
5496
5605
|
}
|
|
5497
|
-
if (member3.type !==
|
|
5606
|
+
if (member3.type !== AST_NODE_TYPES34.MethodDefinition) return;
|
|
5498
5607
|
if (member3.kind !== "method" || member3.static) return;
|
|
5499
5608
|
if (member3.accessibility === "private" || member3.accessibility === "protected")
|
|
5500
5609
|
return;
|
|
5501
|
-
if (member3.key.type ===
|
|
5610
|
+
if (member3.key.type === AST_NODE_TYPES34.PrivateIdentifier) return;
|
|
5502
5611
|
names.push(declaredMemberName(member3) ?? "\u2026");
|
|
5503
5612
|
}
|
|
5504
5613
|
for (const member3 of body3.body) {
|
|
@@ -5509,13 +5618,13 @@ var publicMethodNames = (body3, functionAliases) => {
|
|
|
5509
5618
|
var isFluentConstructionObject = (node, getText) => {
|
|
5510
5619
|
if (node.id === null) return false;
|
|
5511
5620
|
const methods = node.body.body.filter(
|
|
5512
|
-
(member3) => member3.type ===
|
|
5621
|
+
(member3) => member3.type === AST_NODE_TYPES34.MethodDefinition && member3.kind === "method" && !member3.static && member3.accessibility !== "private" && member3.accessibility !== "protected" && member3.value.body !== null
|
|
5513
5622
|
);
|
|
5514
5623
|
if (methods.length === 0) return false;
|
|
5515
5624
|
return methods.every((member3) => {
|
|
5516
5625
|
const result = member3.value.returnType?.typeAnnotation;
|
|
5517
5626
|
if (result === void 0) return false;
|
|
5518
|
-
const returnsOwnType = result.type ===
|
|
5627
|
+
const returnsOwnType = result.type === AST_NODE_TYPES34.TSTypeReference && result.typeName.type === AST_NODE_TYPES34.Identifier && result.typeName.name === node.id?.name;
|
|
5519
5628
|
return returnsOwnType || FLUENT_BUILDER_NAME_RE.test(node.id?.name ?? "") && FLUENT_RESULT_TYPE_RE.test(getText(result));
|
|
5520
5629
|
});
|
|
5521
5630
|
};
|
|
@@ -5523,10 +5632,10 @@ function localClassAbstractness(program) {
|
|
|
5523
5632
|
const classes = /* @__PURE__ */ new Map();
|
|
5524
5633
|
const parents = /* @__PURE__ */ new Map();
|
|
5525
5634
|
for (const statement of program.body) {
|
|
5526
|
-
const declaration = statement.type ===
|
|
5527
|
-
if (declaration?.type ===
|
|
5635
|
+
const declaration = statement.type === AST_NODE_TYPES34.ExportNamedDeclaration || statement.type === AST_NODE_TYPES34.ExportDefaultDeclaration ? statement.declaration : statement;
|
|
5636
|
+
if (declaration?.type === AST_NODE_TYPES34.ClassDeclaration && declaration.id !== null) {
|
|
5528
5637
|
classes.set(declaration.id.name, declaration.abstract === true);
|
|
5529
|
-
if (declaration.superClass?.type ===
|
|
5638
|
+
if (declaration.superClass?.type === AST_NODE_TYPES34.Identifier) {
|
|
5530
5639
|
parents.set(declaration.id.name, declaration.superClass.name);
|
|
5531
5640
|
}
|
|
5532
5641
|
}
|
|
@@ -5544,9 +5653,9 @@ function localClassAbstractness(program) {
|
|
|
5544
5653
|
return classes;
|
|
5545
5654
|
}
|
|
5546
5655
|
function declaredMemberName(member3) {
|
|
5547
|
-
if (!member3.computed && member3.key.type ===
|
|
5656
|
+
if (!member3.computed && member3.key.type === AST_NODE_TYPES34.Identifier)
|
|
5548
5657
|
return member3.key.name;
|
|
5549
|
-
if (member3.key.type ===
|
|
5658
|
+
if (member3.key.type === AST_NODE_TYPES34.Literal && typeof member3.key.value === "string")
|
|
5550
5659
|
return member3.key.value;
|
|
5551
5660
|
return null;
|
|
5552
5661
|
}
|
|
@@ -5555,35 +5664,35 @@ function localInterfaceSurfaces(program) {
|
|
|
5555
5664
|
const parents = /* @__PURE__ */ new Map();
|
|
5556
5665
|
const functionAliases = localFunctionAliases(program);
|
|
5557
5666
|
function collectInterfaceSurface(statement) {
|
|
5558
|
-
const declaration = statement.type ===
|
|
5559
|
-
if (declaration?.type ===
|
|
5667
|
+
const declaration = statement.type === AST_NODE_TYPES34.ExportNamedDeclaration ? statement.declaration : statement;
|
|
5668
|
+
if (declaration?.type === AST_NODE_TYPES34.TSTypeAliasDeclaration) {
|
|
5560
5669
|
const callables2 = interfaces.get(declaration.id.name) ?? /* @__PURE__ */ new Set();
|
|
5561
|
-
const parts = declaration.typeAnnotation.type ===
|
|
5670
|
+
const parts = declaration.typeAnnotation.type === AST_NODE_TYPES34.TSIntersectionType ? declaration.typeAnnotation.types : [declaration.typeAnnotation];
|
|
5562
5671
|
const inherited = parents.get(declaration.id.name) ?? [];
|
|
5563
5672
|
for (const part of parts) {
|
|
5564
|
-
if (part.type ===
|
|
5673
|
+
if (part.type === AST_NODE_TYPES34.TSTypeReference && part.typeName.type === AST_NODE_TYPES34.Identifier) {
|
|
5565
5674
|
inherited.push(part.typeName.name);
|
|
5566
5675
|
continue;
|
|
5567
5676
|
}
|
|
5568
|
-
if (part.type ===
|
|
5677
|
+
if (part.type === AST_NODE_TYPES34.TSTypeReference) {
|
|
5569
5678
|
inherited.push("*");
|
|
5570
5679
|
continue;
|
|
5571
5680
|
}
|
|
5572
|
-
if (part.type !==
|
|
5681
|
+
if (part.type !== AST_NODE_TYPES34.TSTypeLiteral) continue;
|
|
5573
5682
|
addCallableMembers(part.members, callables2);
|
|
5574
5683
|
}
|
|
5575
5684
|
interfaces.set(declaration.id.name, callables2);
|
|
5576
5685
|
parents.set(declaration.id.name, inherited);
|
|
5577
5686
|
return;
|
|
5578
5687
|
}
|
|
5579
|
-
if (declaration?.type !==
|
|
5688
|
+
if (declaration?.type !== AST_NODE_TYPES34.TSInterfaceDeclaration) return;
|
|
5580
5689
|
const callables = interfaces.get(declaration.id.name) ?? /* @__PURE__ */ new Set();
|
|
5581
5690
|
addCallableMembers(declaration.body.body, callables);
|
|
5582
5691
|
interfaces.set(declaration.id.name, callables);
|
|
5583
5692
|
parents.set(declaration.id.name, [
|
|
5584
5693
|
...parents.get(declaration.id.name) ?? [],
|
|
5585
5694
|
...declaration.extends.flatMap(
|
|
5586
|
-
(heritage) => heritage.expression.type ===
|
|
5695
|
+
(heritage) => heritage.expression.type === AST_NODE_TYPES34.Identifier ? [heritage.expression.name] : ["*"]
|
|
5587
5696
|
)
|
|
5588
5697
|
]);
|
|
5589
5698
|
}
|
|
@@ -5592,17 +5701,17 @@ function localInterfaceSurfaces(program) {
|
|
|
5592
5701
|
}
|
|
5593
5702
|
function addCallableMembers(members, callables) {
|
|
5594
5703
|
for (const member3 of members) {
|
|
5595
|
-
if (member3.type !==
|
|
5704
|
+
if (member3.type !== AST_NODE_TYPES34.TSMethodSignature && member3.type !== AST_NODE_TYPES34.TSPropertySignature)
|
|
5596
5705
|
continue;
|
|
5597
5706
|
const name = declaredMemberName(member3);
|
|
5598
5707
|
if (name === null) continue;
|
|
5599
|
-
if (member3.type ===
|
|
5708
|
+
if (member3.type === AST_NODE_TYPES34.TSMethodSignature) {
|
|
5600
5709
|
callables.add(name);
|
|
5601
5710
|
continue;
|
|
5602
5711
|
}
|
|
5603
|
-
if (member3.type !==
|
|
5712
|
+
if (member3.type !== AST_NODE_TYPES34.TSPropertySignature) continue;
|
|
5604
5713
|
const annotation = member3.typeAnnotation?.typeAnnotation;
|
|
5605
|
-
if (annotation?.type ===
|
|
5714
|
+
if (annotation?.type === AST_NODE_TYPES34.TSFunctionType || annotation?.type === AST_NODE_TYPES34.TSTypeReference && annotation.typeName.type === AST_NODE_TYPES34.Identifier && functionAliases.has(annotation.typeName.name))
|
|
5606
5715
|
callables.add(name);
|
|
5607
5716
|
}
|
|
5608
5717
|
}
|
|
@@ -5632,7 +5741,7 @@ function localInterfaceSurfaces(program) {
|
|
|
5632
5741
|
}
|
|
5633
5742
|
function hasServicePort(node, methods, classes, interfaces) {
|
|
5634
5743
|
if (node.superClass !== null) {
|
|
5635
|
-
if (node.superClass.type !==
|
|
5744
|
+
if (node.superClass.type !== AST_NODE_TYPES34.Identifier) return true;
|
|
5636
5745
|
const localAbstract = classes.get(node.superClass.name);
|
|
5637
5746
|
if (localAbstract === void 0 || localAbstract) return true;
|
|
5638
5747
|
}
|
|
@@ -5671,7 +5780,7 @@ var require_port_for_service_default = createRule({
|
|
|
5671
5780
|
if (node.abstract === true) return;
|
|
5672
5781
|
if (node.decorators.length > 0) return;
|
|
5673
5782
|
const ctor = node.body.body.find(
|
|
5674
|
-
(member3) => member3.type ===
|
|
5783
|
+
(member3) => member3.type === AST_NODE_TYPES34.MethodDefinition && member3.kind === "constructor" && member3.value.body !== null && member3.value.body !== void 0
|
|
5675
5784
|
);
|
|
5676
5785
|
if (ctor === void 0) return;
|
|
5677
5786
|
const constructorFacts = readConstructor(
|
|
@@ -5721,7 +5830,7 @@ var require_port_for_service_default = createRule({
|
|
|
5721
5830
|
function implementedSurfaceCovers(node, methods, classes, interfaces) {
|
|
5722
5831
|
const combined = /* @__PURE__ */ new Set();
|
|
5723
5832
|
for (const implementation of node.implements) {
|
|
5724
|
-
if (implementation.expression.type !==
|
|
5833
|
+
if (implementation.expression.type !== AST_NODE_TYPES34.Identifier)
|
|
5725
5834
|
return true;
|
|
5726
5835
|
const name = implementation.expression.name;
|
|
5727
5836
|
const localAbstract = classes.get(name);
|
|
@@ -5738,7 +5847,7 @@ function createServiceOperationResolver(program) {
|
|
|
5738
5847
|
let declaredTypes = null;
|
|
5739
5848
|
return (node) => {
|
|
5740
5849
|
const ctor = node.body.body.find(
|
|
5741
|
-
(member3) => member3.type ===
|
|
5850
|
+
(member3) => member3.type === AST_NODE_TYPES34.MethodDefinition && member3.kind === "constructor" && member3.value.body !== null
|
|
5742
5851
|
);
|
|
5743
5852
|
if (ctor === void 0) return [];
|
|
5744
5853
|
const declared = () => declaredTypes ??= fileTypeIndex(program);
|
|
@@ -5756,7 +5865,7 @@ function createServiceOperationResolver(program) {
|
|
|
5756
5865
|
for (const [name, body3] of serviceOperationBodies(node)) {
|
|
5757
5866
|
forEachServiceCall(body3, (call) => {
|
|
5758
5867
|
if (retained.has(invokedInstanceField(call) ?? "")) active.add(name);
|
|
5759
|
-
if (call.callee.type ===
|
|
5868
|
+
if (call.callee.type === AST_NODE_TYPES34.MemberExpression && call.callee.object.type === AST_NODE_TYPES34.ThisExpression) {
|
|
5760
5869
|
const callee = staticMemberName(call.callee);
|
|
5761
5870
|
if (callee !== null) {
|
|
5762
5871
|
const linked = callers.get(callee) ?? /* @__PURE__ */ new Set();
|
|
@@ -5795,11 +5904,11 @@ function serviceOperationBodies(node) {
|
|
|
5795
5904
|
});
|
|
5796
5905
|
}
|
|
5797
5906
|
for (const member3 of node.body.body) {
|
|
5798
|
-
if (member3.type !==
|
|
5907
|
+
if (member3.type !== AST_NODE_TYPES34.MethodDefinition && member3.type !== AST_NODE_TYPES34.PropertyDefinition)
|
|
5799
5908
|
continue;
|
|
5800
|
-
if (member3.static || member3.decorators.length > 0 || member3.type ===
|
|
5909
|
+
if (member3.static || member3.decorators.length > 0 || member3.type === AST_NODE_TYPES34.MethodDefinition && member3.kind !== "method")
|
|
5801
5910
|
continue;
|
|
5802
|
-
if (member3.value?.type !==
|
|
5911
|
+
if (member3.value?.type !== AST_NODE_TYPES34.FunctionExpression && member3.value?.type !== AST_NODE_TYPES34.ArrowFunctionExpression)
|
|
5803
5912
|
continue;
|
|
5804
5913
|
const name = declaredMemberName(member3);
|
|
5805
5914
|
if (name !== null && !written.has(name) && member3.value.body !== null)
|
|
@@ -5808,9 +5917,9 @@ function serviceOperationBodies(node) {
|
|
|
5808
5917
|
return bodies;
|
|
5809
5918
|
}
|
|
5810
5919
|
function forEachServiceCall(node, onCall) {
|
|
5811
|
-
if (node.type ===
|
|
5920
|
+
if (node.type === AST_NODE_TYPES34.FunctionDeclaration || node.type === AST_NODE_TYPES34.FunctionExpression || node.type === AST_NODE_TYPES34.ArrowFunctionExpression || node.type === AST_NODE_TYPES34.ClassDeclaration || node.type === AST_NODE_TYPES34.ClassExpression)
|
|
5812
5921
|
return;
|
|
5813
|
-
if (node.type ===
|
|
5922
|
+
if (node.type === AST_NODE_TYPES34.BlockStatement) {
|
|
5814
5923
|
for (const statement of node.body) {
|
|
5815
5924
|
forEachServiceCall(statement, onCall);
|
|
5816
5925
|
if (terminatesOperation(statement)) break;
|
|
@@ -5822,29 +5931,29 @@ function forEachServiceCall(node, onCall) {
|
|
|
5822
5931
|
forEachServiceCall(branch, onCall);
|
|
5823
5932
|
return;
|
|
5824
5933
|
}
|
|
5825
|
-
if (node.type ===
|
|
5934
|
+
if (node.type === AST_NODE_TYPES34.CallExpression) onCall(node);
|
|
5826
5935
|
forEachOwnAstChild(node, (child) => {
|
|
5827
5936
|
forEachServiceCall(child, onCall);
|
|
5828
5937
|
});
|
|
5829
5938
|
}
|
|
5830
5939
|
function literalExecutionBranch(node) {
|
|
5831
|
-
if (node.type ===
|
|
5940
|
+
if (node.type === AST_NODE_TYPES34.WhileStatement && node.test.type === AST_NODE_TYPES34.Literal && node.test.value === false)
|
|
5832
5941
|
return node.test;
|
|
5833
|
-
if ((node.type ===
|
|
5942
|
+
if ((node.type === AST_NODE_TYPES34.IfStatement || node.type === AST_NODE_TYPES34.ConditionalExpression) && node.test.type === AST_NODE_TYPES34.Literal && typeof node.test.value === "boolean") {
|
|
5834
5943
|
return node.test.value ? node.consequent : node.alternate ?? node.test;
|
|
5835
5944
|
}
|
|
5836
|
-
if (node.type !==
|
|
5945
|
+
if (node.type !== AST_NODE_TYPES34.LogicalExpression || node.left.type !== AST_NODE_TYPES34.Literal || typeof node.left.value !== "boolean")
|
|
5837
5946
|
return null;
|
|
5838
5947
|
if (node.operator === "&&") return node.left.value ? node.right : node.left;
|
|
5839
5948
|
if (node.operator === "||") return node.left.value ? node.left : node.right;
|
|
5840
5949
|
return node.left;
|
|
5841
5950
|
}
|
|
5842
5951
|
function terminatesOperation(node) {
|
|
5843
|
-
if (node.type ===
|
|
5952
|
+
if (node.type === AST_NODE_TYPES34.ReturnStatement || node.type === AST_NODE_TYPES34.ThrowStatement)
|
|
5844
5953
|
return true;
|
|
5845
|
-
if (node.type ===
|
|
5954
|
+
if (node.type === AST_NODE_TYPES34.BlockStatement)
|
|
5846
5955
|
return node.body.some(terminatesOperation);
|
|
5847
|
-
if (node.type !==
|
|
5956
|
+
if (node.type !== AST_NODE_TYPES34.IfStatement) return false;
|
|
5848
5957
|
const branch = literalExecutionBranch(node);
|
|
5849
5958
|
if (branch !== null) return terminatesOperation(branch);
|
|
5850
5959
|
return node.alternate !== null && terminatesOperation(node.consequent) && terminatesOperation(node.alternate);
|
|
@@ -5858,7 +5967,7 @@ function hasDeclaredServiceContract(node, operations, program) {
|
|
|
5858
5967
|
const seen = /* @__PURE__ */ new Set();
|
|
5859
5968
|
function addImplementedContracts(current) {
|
|
5860
5969
|
for (const implementation of current.implements) {
|
|
5861
|
-
if (implementation.expression.type !==
|
|
5970
|
+
if (implementation.expression.type !== AST_NODE_TYPES34.Identifier)
|
|
5862
5971
|
return false;
|
|
5863
5972
|
const name = implementation.expression.name;
|
|
5864
5973
|
const surface = interfaces.get(name);
|
|
@@ -5881,7 +5990,7 @@ function hasDeclaredServiceContract(node, operations, program) {
|
|
|
5881
5990
|
}
|
|
5882
5991
|
if (!addImplementedContracts(current)) return null;
|
|
5883
5992
|
if (current.superClass === null) continue;
|
|
5884
|
-
if (current.superClass.type !==
|
|
5993
|
+
if (current.superClass.type !== AST_NODE_TYPES34.Identifier) return null;
|
|
5885
5994
|
const base = classes.get(current.superClass.name);
|
|
5886
5995
|
if (base === void 0) return null;
|
|
5887
5996
|
pending.push(base);
|
|
@@ -5891,8 +6000,8 @@ function hasDeclaredServiceContract(node, operations, program) {
|
|
|
5891
6000
|
function localClassDeclarations(program) {
|
|
5892
6001
|
const classes = /* @__PURE__ */ new Map();
|
|
5893
6002
|
for (const statement of program.body) {
|
|
5894
|
-
const declaration = statement.type ===
|
|
5895
|
-
if (declaration?.type ===
|
|
6003
|
+
const declaration = statement.type === AST_NODE_TYPES34.ExportNamedDeclaration || statement.type === AST_NODE_TYPES34.ExportDefaultDeclaration ? statement.declaration : statement;
|
|
6004
|
+
if (declaration?.type === AST_NODE_TYPES34.ClassDeclaration && declaration.id !== null)
|
|
5896
6005
|
classes.set(declaration.id.name, declaration);
|
|
5897
6006
|
}
|
|
5898
6007
|
return classes;
|
|
@@ -5900,13 +6009,13 @@ function localClassDeclarations(program) {
|
|
|
5900
6009
|
function abstractContractOperations(node, functionAliases) {
|
|
5901
6010
|
const methods = new Set(publicMethodNames(node.body, functionAliases));
|
|
5902
6011
|
for (const member3 of node.body.body) {
|
|
5903
|
-
if (member3.type !==
|
|
6012
|
+
if (member3.type !== AST_NODE_TYPES34.TSAbstractMethodDefinition && member3.type !== AST_NODE_TYPES34.TSAbstractPropertyDefinition)
|
|
5904
6013
|
continue;
|
|
5905
6014
|
if (member3.static || member3.accessibility === "private" || member3.accessibility === "protected")
|
|
5906
6015
|
continue;
|
|
5907
|
-
if (member3.type ===
|
|
6016
|
+
if (member3.type === AST_NODE_TYPES34.TSAbstractPropertyDefinition) {
|
|
5908
6017
|
const annotation = member3.typeAnnotation?.typeAnnotation;
|
|
5909
|
-
if (annotation?.type !==
|
|
6018
|
+
if (annotation?.type !== AST_NODE_TYPES34.TSFunctionType && !(annotation?.type === AST_NODE_TYPES34.TSTypeReference && annotation.typeName.type === AST_NODE_TYPES34.Identifier && functionAliases.has(annotation.typeName.name)))
|
|
5910
6019
|
continue;
|
|
5911
6020
|
}
|
|
5912
6021
|
const name = declaredMemberName(member3);
|
|
@@ -6042,7 +6151,7 @@ function isServiceRole(name, filename) {
|
|
|
6042
6151
|
}
|
|
6043
6152
|
|
|
6044
6153
|
// src/rules/no-conditional-empty-object-spread.ts
|
|
6045
|
-
import { AST_NODE_TYPES as
|
|
6154
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES35 } from "@typescript-eslint/utils";
|
|
6046
6155
|
var NO_CONDITIONAL_EMPTY_OBJECT_SPREAD_DOCUMENTATION = {
|
|
6047
6156
|
summary: "Build conditional properties explicitly instead of spreading an empty-object branch.",
|
|
6048
6157
|
rationale: "An empty-object conditional spread hides whether a property is omitted, which differs from assigning undefined.",
|
|
@@ -6094,7 +6203,7 @@ var NO_CONDITIONAL_EMPTY_OBJECT_SPREAD_DOCUMENTATION = {
|
|
|
6094
6203
|
]
|
|
6095
6204
|
};
|
|
6096
6205
|
function isEmptyObject(node) {
|
|
6097
|
-
return node.type ===
|
|
6206
|
+
return node.type === AST_NODE_TYPES35.ObjectExpression && node.properties.length === 0;
|
|
6098
6207
|
}
|
|
6099
6208
|
var no_conditional_empty_object_spread_default = createRule({
|
|
6100
6209
|
name: "no-conditional-empty-object-spread",
|
|
@@ -6115,13 +6224,13 @@ var no_conditional_empty_object_spread_default = createRule({
|
|
|
6115
6224
|
if (isGeneratedFile(context, context.sourceCode.text)) return {};
|
|
6116
6225
|
return {
|
|
6117
6226
|
SpreadElement(node) {
|
|
6118
|
-
if (node.parent.type !==
|
|
6227
|
+
if (node.parent.type !== AST_NODE_TYPES35.ObjectExpression || node.argument.type !== AST_NODE_TYPES35.ConditionalExpression)
|
|
6119
6228
|
return;
|
|
6120
6229
|
if (isEmptyObject(node.argument.consequent) || isEmptyObject(node.argument.alternate)) {
|
|
6121
6230
|
const conditional = node.argument;
|
|
6122
6231
|
const emptyConsequent = isEmptyObject(conditional.consequent);
|
|
6123
6232
|
const populated = emptyConsequent ? conditional.alternate : conditional.consequent;
|
|
6124
|
-
const canFix = populated.type ===
|
|
6233
|
+
const canFix = populated.type === AST_NODE_TYPES35.ObjectExpression && populated.properties.length > 0 && context.sourceCode.getCommentsInside(conditional).length === 0;
|
|
6125
6234
|
context.report({
|
|
6126
6235
|
node,
|
|
6127
6236
|
messageId: "avoid",
|
|
@@ -6138,7 +6247,7 @@ var no_conditional_empty_object_spread_default = createRule({
|
|
|
6138
6247
|
|
|
6139
6248
|
// src/rules/prefer-typed-reflection.ts
|
|
6140
6249
|
import {
|
|
6141
|
-
AST_NODE_TYPES as
|
|
6250
|
+
AST_NODE_TYPES as AST_NODE_TYPES36,
|
|
6142
6251
|
ASTUtils as ASTUtils22,
|
|
6143
6252
|
ESLintUtils as ESLintUtils7
|
|
6144
6253
|
} from "@typescript-eslint/utils";
|
|
@@ -6217,17 +6326,17 @@ var prefer_typed_reflection_default = createRule({
|
|
|
6217
6326
|
const services = ESLintUtils7.getParserServices(context);
|
|
6218
6327
|
if (!services.program) return {};
|
|
6219
6328
|
const checker = services.program.getTypeChecker();
|
|
6220
|
-
const isReflect = (node) => globalName(node, "Reflect") || node.type ===
|
|
6221
|
-
const globalName = (node, name) => node.type ===
|
|
6329
|
+
const isReflect = (node) => globalName(node, "Reflect") || node.type === AST_NODE_TYPES36.MemberExpression && ASTUtils22.getPropertyName(node) === "Reflect" && globalName(node.object, "globalThis");
|
|
6330
|
+
const globalName = (node, name) => node.type === AST_NODE_TYPES36.Identifier && node.name === name && !ASTUtils22.findVariable(context.sourceCode.getScope(node), name)?.defs.length;
|
|
6222
6331
|
const closedObject = (type) => {
|
|
6223
6332
|
if (type.isUnion()) return type.types.every(closedObject);
|
|
6224
6333
|
return knownType(type) && type.getProperties().length > 0 && checker.getIndexInfosOfType(type).length === 0;
|
|
6225
6334
|
};
|
|
6226
6335
|
const inspectGet = (node, type) => {
|
|
6227
6336
|
const key = node.arguments[1] === void 0 ? void 0 : unwrapExpression(node.arguments[1]);
|
|
6228
|
-
return node.arguments.length === 2 && (staticString(key) !== null || key?.type ===
|
|
6337
|
+
return node.arguments.length === 2 && (staticString(key) !== null || key?.type === AST_NODE_TYPES36.Literal && typeof key.value === "number") && closedObject(type);
|
|
6229
6338
|
};
|
|
6230
|
-
const inspectApply = (node, type) => node.arguments.length === 3 && node.arguments[2]?.type ===
|
|
6339
|
+
const inspectApply = (node, type) => node.arguments.length === 3 && node.arguments[2]?.type === AST_NODE_TYPES36.ArrayExpression && knownType(type) && type.getCallSignatures().some(
|
|
6231
6340
|
(signature) => signature.typeParameters === void 0 && signature.parameters.every(
|
|
6232
6341
|
(parameter) => knownType(
|
|
6233
6342
|
checker.getTypeOfSymbolAtLocation(
|
|
@@ -6238,25 +6347,25 @@ var prefer_typed_reflection_default = createRule({
|
|
|
6238
6347
|
)
|
|
6239
6348
|
);
|
|
6240
6349
|
const getReplacement = (node, type, target) => {
|
|
6241
|
-
if (node.optional || node.callee.type !==
|
|
6350
|
+
if (node.optional || node.callee.type !== AST_NODE_TYPES36.MemberExpression || node.callee.optional || context.sourceCode.getCommentsInside(node).length > 0) return null;
|
|
6242
6351
|
let outer = node;
|
|
6243
|
-
while (outer.parent.type ===
|
|
6244
|
-
if (outer.parent.type ===
|
|
6352
|
+
while (outer.parent.type === AST_NODE_TYPES36.TSAsExpression || outer.parent.type === AST_NODE_TYPES36.TSTypeAssertion || outer.parent.type === AST_NODE_TYPES36.TSSatisfiesExpression || outer.parent.type === AST_NODE_TYPES36.TSNonNullExpression || outer.parent.type === AST_NODE_TYPES36.ChainExpression) outer = outer.parent;
|
|
6353
|
+
if (outer.parent.type === AST_NODE_TYPES36.UnaryExpression && outer.parent.operator === "delete" || outer.parent.type === AST_NODE_TYPES36.CallExpression && outer.parent.callee === outer || outer.parent.type === AST_NODE_TYPES36.TaggedTemplateExpression && outer.parent.tag === outer) return null;
|
|
6245
6354
|
const writtenKey = node.arguments[1];
|
|
6246
|
-
if (writtenKey === void 0 || writtenKey.type ===
|
|
6355
|
+
if (writtenKey === void 0 || writtenKey.type === AST_NODE_TYPES36.SpreadElement) return null;
|
|
6247
6356
|
const key = unwrapExpression(writtenKey);
|
|
6248
|
-
const name = staticString(key) ?? (key.type ===
|
|
6357
|
+
const name = staticString(key) ?? (key.type === AST_NODE_TYPES36.Literal && typeof key.value === "number" ? String(key.value) : null);
|
|
6249
6358
|
const members = type.isUnion() ? type.types : [type];
|
|
6250
6359
|
if (name === null || !members.every((member3) => (member3.flags & ts13.TypeFlags.Object) !== 0 && checker.getPropertyOfType(member3, name) !== void 0)) return null;
|
|
6251
6360
|
return `(${context.sourceCode.getText(target)})[${context.sourceCode.getText(writtenKey)}]`;
|
|
6252
6361
|
};
|
|
6253
6362
|
return {
|
|
6254
6363
|
CallExpression(node) {
|
|
6255
|
-
if (node.callee.type !==
|
|
6364
|
+
if (node.callee.type !== AST_NODE_TYPES36.MemberExpression || !isReflect(node.callee.object))
|
|
6256
6365
|
return;
|
|
6257
6366
|
const method = ASTUtils22.getPropertyName(node.callee);
|
|
6258
6367
|
const target = node.arguments[0];
|
|
6259
|
-
if (!target || target.type ===
|
|
6368
|
+
if (!target || target.type === AST_NODE_TYPES36.SpreadElement || method !== "get" && method !== "apply")
|
|
6260
6369
|
return;
|
|
6261
6370
|
const type = checker.getTypeAtLocation(
|
|
6262
6371
|
services.esTreeNodeToTSNodeMap.get(target)
|
|
@@ -6276,55 +6385,6 @@ import {
|
|
|
6276
6385
|
ESLintUtils as ESLintUtils8
|
|
6277
6386
|
} from "@typescript-eslint/utils";
|
|
6278
6387
|
import ts14 from "typescript";
|
|
6279
|
-
|
|
6280
|
-
// src/rules/_unused-private-binding.ts
|
|
6281
|
-
import { AST_NODE_TYPES as AST_NODE_TYPES36 } from "@typescript-eslint/utils";
|
|
6282
|
-
function isUnusedPrivateBinding(sourceCode, declaration, identifier, filename, allowedDeclarations = [declaration]) {
|
|
6283
|
-
if (/\.d\.[cm]?ts$/u.test(filename)) return false;
|
|
6284
|
-
const bindings = sourceCode.getDeclaredVariables(declaration).filter((binding3) => binding3.name === identifier.name);
|
|
6285
|
-
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;
|
|
6286
|
-
if (hasIdentifierNamed(sourceCode.ast, "eval")) return false;
|
|
6287
|
-
const statement = declaration.type === AST_NODE_TYPES36.VariableDeclarator ? declaration.parent : declaration;
|
|
6288
|
-
if (statement.parent.type === AST_NODE_TYPES36.ExportNamedDeclaration || statement.parent.type === AST_NODE_TYPES36.ExportDefaultDeclaration) return false;
|
|
6289
|
-
if (statement.parent.type !== AST_NODE_TYPES36.Program) return statement.parent.type === AST_NODE_TYPES36.BlockStatement;
|
|
6290
|
-
return sourceCode.ast.body.some((node) => node.type === AST_NODE_TYPES36.ImportDeclaration || node.type === AST_NODE_TYPES36.ExportNamedDeclaration || node.type === AST_NODE_TYPES36.ExportDefaultDeclaration || node.type === AST_NODE_TYPES36.ExportAllDeclaration);
|
|
6291
|
-
}
|
|
6292
|
-
function hasOnlyDirectFactoryUses(variable) {
|
|
6293
|
-
return variable.references.every((reference) => {
|
|
6294
|
-
if (reference.isTypeReference && !reference.isValueReference) return true;
|
|
6295
|
-
const identifier = reference.identifier;
|
|
6296
|
-
const parent = identifier.parent;
|
|
6297
|
-
if (parent.type === AST_NODE_TYPES36.CallExpression && parent.callee === identifier) return true;
|
|
6298
|
-
return parent.type === AST_NODE_TYPES36.MemberExpression && parent.object === identifier && !parent.computed && parent.parent.type === AST_NODE_TYPES36.CallExpression && parent.parent.callee === parent;
|
|
6299
|
-
});
|
|
6300
|
-
}
|
|
6301
|
-
var IDENTIFIER_NAMES = /* @__PURE__ */ new WeakMap();
|
|
6302
|
-
function hasIdentifierNamed(node, name) {
|
|
6303
|
-
let names = IDENTIFIER_NAMES.get(node);
|
|
6304
|
-
if (names === void 0) {
|
|
6305
|
-
const collected = /* @__PURE__ */ new Set();
|
|
6306
|
-
const pending = [node];
|
|
6307
|
-
const seen = /* @__PURE__ */ new WeakSet();
|
|
6308
|
-
while (pending.length > 0) {
|
|
6309
|
-
const current = pending.pop();
|
|
6310
|
-
if (current === void 0 || seen.has(current)) continue;
|
|
6311
|
-
seen.add(current);
|
|
6312
|
-
if (current.type === AST_NODE_TYPES36.Identifier || current.type === AST_NODE_TYPES36.JSXIdentifier) collected.add(current.name);
|
|
6313
|
-
forEachOwnAstChild(current, (child) => {
|
|
6314
|
-
pending.push(child);
|
|
6315
|
-
}, (key) => key !== "tokens" && key !== "comments");
|
|
6316
|
-
}
|
|
6317
|
-
names = collected;
|
|
6318
|
-
IDENTIFIER_NAMES.set(node, names);
|
|
6319
|
-
}
|
|
6320
|
-
return names.has(name);
|
|
6321
|
-
}
|
|
6322
|
-
function privatePredicateBooleanFix(sourceCode, node, annotation, filename) {
|
|
6323
|
-
if (!annotation.typeAnnotation || !retainsNamedTypeUses(sourceCode, annotation.typeAnnotation) || node.type !== AST_NODE_TYPES36.FunctionDeclaration || node.id === null || !isUnusedPrivateBinding(sourceCode, node, node.id, filename) || sourceCode.getCommentsInside(annotation).length > 0) return null;
|
|
6324
|
-
return (fixer) => fixer.replaceText(annotation, `boolean${sourceCode.getText(annotation).replace(/[^\r\n]/gu, "")}`);
|
|
6325
|
-
}
|
|
6326
|
-
|
|
6327
|
-
// src/rules/no-broad-return-type.ts
|
|
6328
6388
|
var NO_BROAD_RETURN_TYPE_DOCUMENTATION = {
|
|
6329
6389
|
summary: "Report explicit broad return annotations that erase a known return value.",
|
|
6330
6390
|
rationale: "An unknown, object, or unknown-valued dictionary return hides fields that the implementation already knows.",
|
|
@@ -7175,7 +7235,7 @@ var NO_CONTRADICTORY_TYPE_PREDICATE_DOCUMENTATION = {
|
|
|
7175
7235
|
"For the intrinsic object target, typeof-object also admits null only when the declared input admits null and strictNullChecks is enabled. This narrow check does not infer structural property validation or classify other object/function relationships. Overloaded implementations, contextually typed callbacks and methods with class heritage or contextual object contracts retain their separate callable domain.",
|
|
7176
7236
|
"Compiler-invalid predicate target/input relations and typeof comparisons impossible for the input remain with existing compiler and unnecessary-condition controls. This rule does not validate arbitrary predicates or runtime refinements. Generated files are excluded; tests remain checked.",
|
|
7177
7237
|
"A sole native Array.isArray call on unknown cannot establish a plain primitive-element array target. Standard-library call signatures and an unshadowed Array binding are required. Element validators, any/unknown elements, tuples, enums, branded or opaque elements and independent callable contracts abstain. Visible Array or host-global aliases, mutation, escapes, extracted methods, any value constructor or unresolved computed-property access and unrelated Array namespace uses disable this proof: structural receiver types cannot establish runtime constructor identity. Native Reflect value uses and Object prototype/descriptor reflection or namespace aliases also withdraw authority. Indirect opaque runtime replacements are not inferred.",
|
|
7178
|
-
"For a same-file nongeneric named record with a required data property, a sole typeof-object check, optionally conjoined with a null exclusion, cannot establish that property from unknown or object input. Optional-only records, dictionaries, classes, imported/generic contracts and implementations with field checks are excluded. A non-null object without the required own property supplies the contradiction;
|
|
7238
|
+
"For a same-file nongeneric named record with a required data property, a sole typeof-object check, optionally conjoined with a null exclusion, cannot establish that property from unknown or object input. Optional-only records, dictionaries, classes, imported/generic contracts and implementations with field checks are excluded. A non-null object without the required own property supplies the contradiction. The same unused-private predicate proof may remove its unobserved narrowing contract; observed callable contracts and sole named-type uses remain manual."
|
|
7179
7239
|
],
|
|
7180
7240
|
references: ["https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html#inferred-type-predicates"],
|
|
7181
7241
|
examples: [
|
|
@@ -7239,7 +7299,7 @@ var no_contradictory_type_predicate_default = createRule({
|
|
|
7239
7299
|
const target = checker.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(annotation.typeAnnotation.typeAnnotation));
|
|
7240
7300
|
if (!checker.isTypeAssignableTo(target, input)) return;
|
|
7241
7301
|
if (shallowRecordCheck(expression, parameter, input, target, context.sourceCode, checker, services.esTreeNodeToTSNodeMap.get(node).getSourceFile())) {
|
|
7242
|
-
context.report({ node: annotation, messageId: "uncheckedRecordFields", data: { promised: checker.typeToString(target) } });
|
|
7302
|
+
context.report({ node: annotation, messageId: "uncheckedRecordFields", fix: privatePredicateBooleanFix(context.sourceCode, node, annotation, context.filename), data: { promised: checker.typeToString(target) } });
|
|
7243
7303
|
return;
|
|
7244
7304
|
}
|
|
7245
7305
|
if (check === void 0) {
|
|
@@ -7465,7 +7525,7 @@ var NO_PARTIAL_TYPE_PREDICATE_DOCUMENTATION = {
|
|
|
7465
7525
|
"Automatic fixes replace the unsound predicate with boolean only for an unused private function declaration without overloads, exports, eval, comments in the predicate, or declaration-file ownership. Runtime checks are preserved; observed callable contracts remain manual.",
|
|
7466
7526
|
"Requires type information and a non-generic, non-async function with one directly annotated parameter, an explicit broad string/number/bigint/boolean predicate and a single return. Literal, branded, structural, multi-primitive union, assertion, method and overloaded contracts are excluded; contextually typed callbacks are preserved.",
|
|
7467
7527
|
"Recognizes double-negation truthiness, a boolean parameter return or one same-kind literal comparison, optionally after a matching typeof equality. Without a typeof check, the input must already belong to the target primitive, except for double negation. String length comparisons use only concrete witnesses up to 256 characters. Arithmetic, dynamic bounds and complex boolean conditions are not inferred.",
|
|
7468
|
-
"A broad string predicate returning local Schema.safeParse(parameter).success is also checked for a locally unchanged official z.uuid() or z.string().uuid() schema. The checker must resolve the namespace to installed node_modules/zod declaration files; local path aliases and opaque module resolution abstain. The const schema permits local parse/type/direct-export reads; every safeParse call must have exactly one direct argument, without options or spreads. Local aliases, method writes and opaque consumers abstain. Direct export alone is not mutation, but external consumer monkey-patching is not proved absent. Other value uses of its imported Zod namespace cause abstention. Transforms, brands, custom schemas, imported schemas and dynamic parse calls are excluded. Visible RegExp capabilities, regex literals or dynamic evaluation invalidate this initial native-pattern proof; external runtime monkeypatches are not inferred.
|
|
7528
|
+
"A broad string predicate returning local Schema.safeParse(parameter).success is also checked for a locally unchanged official z.uuid() or z.string().uuid() schema. The checker must resolve the namespace to installed node_modules/zod declaration files; local path aliases and opaque module resolution abstain. The const schema permits local parse/type/direct-export reads; every safeParse call must have exactly one direct argument, without options or spreads. Local aliases, method writes and opaque consumers abstain. Direct export alone is not mutation, but external consumer monkey-patching is not proved absent. Other value uses of its imported Zod namespace cause abstention. Transforms, brands, custom schemas, imported schemas and dynamic parse calls are excluded. Visible RegExp capabilities, regex literals or dynamic evaluation invalidate this initial native-pattern proof; external runtime monkeypatches are not inferred. The same unused-private-declaration fix boundary applies; observed or exported predicates remain manual.",
|
|
7469
7529
|
"A concrete member of the promised broad primitive must demonstrably return false. Numeric witnesses must also be assignable as literals to the declared input: broad number assignability alone does not prove membership in a numeric enum. Compiler-invalid target/input relations, any/never/generic inputs and opaque implementations abstain. This rule does not discourage total boundary guards or infer branded refinements. Generated files are excluded; tests remain checked."
|
|
7470
7530
|
],
|
|
7471
7531
|
references: ["https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html#inferred-type-predicates"],
|
|
@@ -7504,7 +7564,7 @@ var no_partial_type_predicate_default = createRule({
|
|
|
7504
7564
|
if (predicate === void 0) return;
|
|
7505
7565
|
const uuidWitness = predicate.kind === "string" ? uuidPredicateWitness(predicate.expression, predicate.parameter, context.sourceCode, services) : void 0;
|
|
7506
7566
|
if (uuidWitness !== void 0) {
|
|
7507
|
-
context.report({ node: predicate.annotation, messageId: "partialPredicate", data: { witness: showWitness(uuidWitness), target: "string" } });
|
|
7567
|
+
context.report({ node: predicate.annotation, messageId: "partialPredicate", fix: privatePredicateBooleanFix(context.sourceCode, node, predicate.annotation, context.filename), data: { witness: showWitness(uuidWitness), target: "string" } });
|
|
7508
7568
|
return;
|
|
7509
7569
|
}
|
|
7510
7570
|
const refinement = refinementExpression(predicate, context.sourceCode);
|
|
@@ -10992,7 +11052,16 @@ var no_comment_cruft_default = createRule({
|
|
|
10992
11052
|
while (end + 1 < comments.length && areAdjacentLineComments(comments[end], comments[end + 1])) end += 1;
|
|
10993
11053
|
const removals = comments.slice(start, end + 1).filter(pure).map((candidate2) => ownLineCommentRemovalRange(sourceCode.text, candidate2));
|
|
10994
11054
|
if (removals.some((removal) => removal === null)) return null;
|
|
10995
|
-
return (fixer) =>
|
|
11055
|
+
return (fixer) => {
|
|
11056
|
+
const fixes = [];
|
|
11057
|
+
for (const removal of removals) {
|
|
11058
|
+
if (removal === null) return null;
|
|
11059
|
+
const endings = commentLineEndings(sourceCode.text, removal);
|
|
11060
|
+
if (endings === null) return null;
|
|
11061
|
+
fixes.push(fixer.replaceTextRange(removal.range, endings));
|
|
11062
|
+
}
|
|
11063
|
+
return fixes;
|
|
11064
|
+
};
|
|
10996
11065
|
}
|
|
10997
11066
|
function isSectionJsDoc(comment) {
|
|
10998
11067
|
const texts = comment.value.split("\n").map(stripCommentMarker).filter((line) => line.length > 0 && !isDirective(line));
|
|
@@ -18915,7 +18984,10 @@ var no_restated_comment_default = createRule({
|
|
|
18915
18984
|
context.report({
|
|
18916
18985
|
node: comment,
|
|
18917
18986
|
messageId: "restatesLineBelow",
|
|
18918
|
-
fix: removal === null ? null : (fixer) =>
|
|
18987
|
+
fix: removal === null ? null : (fixer) => {
|
|
18988
|
+
const endings = commentLineEndings(sourceCode.text, removal);
|
|
18989
|
+
return endings === null ? null : fixer.replaceTextRange(removal.range, endings);
|
|
18990
|
+
},
|
|
18919
18991
|
suggest: removal === null ? null : [
|
|
18920
18992
|
{
|
|
18921
18993
|
messageId: "deleteComment",
|
|
@@ -19074,7 +19146,10 @@ var no_restated_jsdoc_default = createRule({
|
|
|
19074
19146
|
context.report({
|
|
19075
19147
|
node: comment,
|
|
19076
19148
|
messageId: "restatesSignature",
|
|
19077
|
-
fix: removal === null ? null : (fixer) =>
|
|
19149
|
+
fix: removal === null ? null : (fixer) => {
|
|
19150
|
+
const endings = commentLineEndings(sourceCode.text, removal);
|
|
19151
|
+
return endings === null ? null : fixer.replaceTextRange(removal.range, endings);
|
|
19152
|
+
},
|
|
19078
19153
|
suggest: removal === null ? [] : [
|
|
19079
19154
|
{
|
|
19080
19155
|
messageId: "deleteBlock",
|
|
@@ -21898,7 +21973,10 @@ function typedTagEdit(comment, signature, sourceCode) {
|
|
|
21898
21973
|
if (!removed) return null;
|
|
21899
21974
|
while (retained[0]?.trim() === "") retained.shift();
|
|
21900
21975
|
while (retained.at(-1)?.trim() === "") retained.pop();
|
|
21901
|
-
if (retained.length === 0)
|
|
21976
|
+
if (retained.length === 0) {
|
|
21977
|
+
const endings = commentLineEndings(sourceCode.text, removal);
|
|
21978
|
+
return endings === null ? null : { range: removal.range, text: endings };
|
|
21979
|
+
}
|
|
21902
21980
|
const eol = sourceCode.text.includes("\r\n") ? "\r\n" : "\n";
|
|
21903
21981
|
const indent = " ".repeat(comment.loc.start.column);
|
|
21904
21982
|
return {
|
|
@@ -22501,7 +22579,15 @@ var no_declaration_comment_wall_default = createRule({
|
|
|
22501
22579
|
},
|
|
22502
22580
|
messageId: "commentWall",
|
|
22503
22581
|
data: { restated: String(restated), commented: String(commented) },
|
|
22504
|
-
fix: removals.length === 0 ? null : (fixer) =>
|
|
22582
|
+
fix: removals.length === 0 ? null : (fixer) => {
|
|
22583
|
+
const fixes = [];
|
|
22584
|
+
for (const removal of removals) {
|
|
22585
|
+
const endings = commentLineEndings(sourceCode.text, removal);
|
|
22586
|
+
if (endings === null) return null;
|
|
22587
|
+
fixes.push(fixer.replaceTextRange(removal.range, endings));
|
|
22588
|
+
}
|
|
22589
|
+
return fixes;
|
|
22590
|
+
}
|
|
22505
22591
|
});
|
|
22506
22592
|
}
|
|
22507
22593
|
function isGroupLabel(comment, member3, headsRun) {
|
|
@@ -22852,7 +22938,15 @@ var no_type_member_comment_wall_default = createRule({
|
|
|
22852
22938
|
},
|
|
22853
22939
|
messageId: "commentWall",
|
|
22854
22940
|
data: { restated: String(restated), commented: String(commented) },
|
|
22855
|
-
fix: removals.length === 0 ? null : (fixer) =>
|
|
22941
|
+
fix: removals.length === 0 ? null : (fixer) => {
|
|
22942
|
+
const fixes = [];
|
|
22943
|
+
for (const removal of removals) {
|
|
22944
|
+
const endings = commentLineEndings(sourceCode.text, removal);
|
|
22945
|
+
if (endings === null) return null;
|
|
22946
|
+
fixes.push(fixer.replaceTextRange(removal.range, endings));
|
|
22947
|
+
}
|
|
22948
|
+
return fixes;
|
|
22949
|
+
}
|
|
22856
22950
|
});
|
|
22857
22951
|
}
|
|
22858
22952
|
function isGroupLabel(comment, member3, headsRun) {
|
|
@@ -23867,7 +23961,10 @@ var test_phase_label_comment_default = createRule({
|
|
|
23867
23961
|
context.report({
|
|
23868
23962
|
node: comment,
|
|
23869
23963
|
messageId: "removeLabel",
|
|
23870
|
-
fix: (fixer) =>
|
|
23964
|
+
fix: (fixer) => {
|
|
23965
|
+
const endings = commentLineEndings(context.sourceCode.text, removal);
|
|
23966
|
+
return endings === null ? null : fixer.replaceTextRange(removal.range, endings);
|
|
23967
|
+
}
|
|
23871
23968
|
});
|
|
23872
23969
|
}
|
|
23873
23970
|
}
|
|
@@ -36600,8 +36697,10 @@ var RULE_POLICY = {
|
|
|
36600
36697
|
"@sarj/require-pascal-case-zod-schema-name": ["error", "both"]
|
|
36601
36698
|
};
|
|
36602
36699
|
var ADVISORY_RULES = Object.keys(RULE_POLICY).filter(isAdvisoryRuleName).toSorted();
|
|
36603
|
-
var
|
|
36604
|
-
var
|
|
36700
|
+
var FLAT_RECOMMENDED_RULES = presetRules("recommended");
|
|
36701
|
+
var FLAT_STRICT_RULES = presetRules("strict");
|
|
36702
|
+
var RECOMMENDED_RULES = FLAT_RECOMMENDED_RULES;
|
|
36703
|
+
var STRICT_RULES = FLAT_STRICT_RULES;
|
|
36605
36704
|
function isAdvisoryRuleName(name) {
|
|
36606
36705
|
return isPolicyName(name) && RULE_POLICY[name][0] === "warn";
|
|
36607
36706
|
}
|
|
@@ -36636,12 +36735,12 @@ var PLUGIN = {
|
|
|
36636
36735
|
recommended: {
|
|
36637
36736
|
name: "@sarj/recommended",
|
|
36638
36737
|
plugins: { "@sarj": PLUGIN },
|
|
36639
|
-
rules:
|
|
36738
|
+
rules: FLAT_RECOMMENDED_RULES
|
|
36640
36739
|
},
|
|
36641
36740
|
strict: {
|
|
36642
36741
|
name: "@sarj/strict",
|
|
36643
36742
|
plugins: { "@sarj": PLUGIN },
|
|
36644
|
-
rules:
|
|
36743
|
+
rules: FLAT_STRICT_RULES
|
|
36645
36744
|
}
|
|
36646
36745
|
};
|
|
36647
36746
|
}
|