oxlint-plugin-arch 0.11.0 → 0.12.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.
Files changed (221) hide show
  1. package/CHANGELOG.md +241 -0
  2. package/README.md +52 -218
  3. package/dist/index.js +5205 -4073
  4. package/dist/preset/groups/backend.d.ts +2 -0
  5. package/dist/preset/groups/basics.d.ts +2 -0
  6. package/dist/preset/groups/comments.d.ts +2 -0
  7. package/dist/preset/groups/console.d.ts +2 -0
  8. package/dist/preset/groups/deny.d.ts +2 -0
  9. package/dist/preset/groups/expo.d.ts +2 -0
  10. package/dist/preset/groups/externals.d.ts +2 -0
  11. package/dist/preset/groups/forms.d.ts +2 -0
  12. package/dist/preset/groups/imports.d.ts +2 -0
  13. package/dist/preset/groups/layout.d.ts +2 -0
  14. package/dist/preset/groups/limits.d.ts +2 -0
  15. package/dist/preset/groups/naming.d.ts +2 -0
  16. package/dist/preset/groups/next.d.ts +2 -0
  17. package/dist/preset/groups/orpc.d.ts +2 -0
  18. package/dist/preset/groups/react.d.ts +2 -0
  19. package/dist/preset/groups/schemas.d.ts +2 -0
  20. package/dist/preset/groups/shadcn.d.ts +2 -0
  21. package/dist/preset/groups/sql.d.ts +2 -0
  22. package/dist/preset/groups/style.d.ts +2 -0
  23. package/dist/preset/groups/tailwind.d.ts +2 -0
  24. package/dist/preset/groups/tanstack.d.ts +2 -0
  25. package/dist/preset/groups/tests.d.ts +2 -0
  26. package/dist/preset/groups/types.d.ts +2 -0
  27. package/dist/preset/preset-detect.d.ts +3 -0
  28. package/dist/preset/preset-folders.d.ts +2 -0
  29. package/dist/preset/preset-recipes.d.ts +82 -0
  30. package/dist/preset/preset-stylesheet.d.ts +1 -0
  31. package/dist/preset/preset-units.d.ts +2 -0
  32. package/dist/preset/preset.constants.d.ts +79 -0
  33. package/dist/preset/preset.d.ts +89 -0
  34. package/dist/preset/preset.js +2299 -0
  35. package/dist/preset/preset.utils.d.ts +14 -0
  36. package/dist/rules/backend/backend-orpc-output.d.ts +1 -0
  37. package/dist/rules/backend/backend-registry.d.ts +1 -0
  38. package/dist/rules/backend/backend-service-functions.d.ts +1 -0
  39. package/dist/rules/backend/backend-sql-like.d.ts +1 -0
  40. package/dist/rules/boundaries/boundaries-deny.d.ts +1 -0
  41. package/dist/rules/boundaries/boundaries-imports.d.ts +1 -0
  42. package/dist/rules/boundaries/boundaries-next.d.ts +1 -0
  43. package/dist/rules/boundaries/boundaries-rpc-database.d.ts +1 -0
  44. package/dist/rules/boundaries/boundaries-tanstack.d.ts +1 -0
  45. package/dist/rules/boundaries/boundaries-token-owner.d.ts +1 -0
  46. package/dist/rules/code/code-constructor.d.ts +1 -0
  47. package/dist/rules/code/code-double-negation.d.ts +1 -0
  48. package/dist/rules/code/code-literal-in.d.ts +1 -0
  49. package/dist/rules/code/code-mutable-state.d.ts +1 -0
  50. package/dist/rules/code/code-object-params.d.ts +1 -0
  51. package/dist/rules/code/code-paired-call.d.ts +1 -0
  52. package/dist/rules/code/code-promise-mutation.d.ts +1 -0
  53. package/dist/rules/code/code-switch.d.ts +1 -0
  54. package/dist/rules/code/code-trivial-functions.d.ts +1 -0
  55. package/dist/rules/comments/comments-code.d.ts +1 -0
  56. package/dist/rules/comments/comments-directives.d.ts +1 -0
  57. package/dist/rules/copy/copy-dashes.d.ts +1 -0
  58. package/dist/rules/files/files-components-only.d.ts +1 -0
  59. package/dist/rules/files/files-constants-only.d.ts +1 -0
  60. package/dist/rules/files/files-domain-constants.d.ts +1 -0
  61. package/dist/rules/files/files-exports.d.ts +1 -0
  62. package/dist/rules/files/files-externals.d.ts +1 -0
  63. package/dist/rules/files/files-factory-keys.d.ts +1 -0
  64. package/dist/rules/files/files-helpers.d.ts +1 -0
  65. package/dist/rules/files/files-no-functions.d.ts +1 -0
  66. package/dist/rules/files/files-restricted.d.ts +1 -0
  67. package/dist/rules/files/files-route.d.ts +1 -0
  68. package/dist/rules/files/files-types-only.d.ts +1 -0
  69. package/dist/rules/layout/layout-call-arguments.d.ts +1 -0
  70. package/dist/rules/layout/layout-call-array.d.ts +1 -0
  71. package/dist/rules/layout/layout-chain.d.ts +1 -0
  72. package/dist/rules/layout/layout-jsx-attributes.d.ts +1 -0
  73. package/dist/rules/layout/layout-key-value.d.ts +1 -0
  74. package/dist/rules/layout/layout-object.d.ts +1 -0
  75. package/dist/rules/layout/layout-padding.d.ts +1 -0
  76. package/dist/rules/layout/layout-ternary.d.ts +1 -0
  77. package/dist/rules/naming/naming-declarations.d.ts +1 -0
  78. package/dist/rules/naming/naming-exports.d.ts +1 -0
  79. package/dist/rules/naming/naming-file.d.ts +1 -0
  80. package/dist/rules/naming/naming-folder.d.ts +1 -0
  81. package/dist/rules/naming/naming-types.d.ts +1 -0
  82. package/dist/rules/react/react-dynamic-classes.d.ts +1 -0
  83. package/dist/rules/react/react-empty-effect.d.ts +1 -0
  84. package/dist/rules/react/react-memo.d.ts +1 -0
  85. package/dist/rules/react/react-props.d.ts +1 -0
  86. package/dist/rules/schemas/schemas-inline.d.ts +1 -0
  87. package/dist/rules/schemas/schemas-local.d.ts +1 -0
  88. package/dist/rules/schemas/schemas-rederive.d.ts +1 -0
  89. package/dist/rules/schemas/schemas-single-use.d.ts +1 -0
  90. package/dist/rules/tests/tests-assertions.d.ts +1 -0
  91. package/dist/rules/tests/tests-concurrent-db.d.ts +1 -0
  92. package/dist/rules/tests/tests-modifiers.d.ts +1 -0
  93. package/dist/rules/tests/tests-titles.d.ts +1 -0
  94. package/dist/rules/types/types-declarations.d.ts +1 -0
  95. package/dist/rules/types/types-imported-alias.d.ts +1 -0
  96. package/dist/rules/types/types-inline.d.ts +1 -0
  97. package/dist/rules/types/types-local-alias.d.ts +1 -0
  98. package/dist/rules/types/types-namespace-import.d.ts +1 -0
  99. package/dist/rules/types/types-service.d.ts +1 -0
  100. package/dist/rules/types/types-unknown.d.ts +1 -0
  101. package/dist/types/ast.types.d.ts +2 -0
  102. package/dist/types/backend.types.d.ts +24 -0
  103. package/dist/types/boundaries.types.d.ts +72 -0
  104. package/dist/types/code.types.d.ts +59 -0
  105. package/dist/types/comments.types.d.ts +12 -0
  106. package/dist/types/copy.types.d.ts +4 -0
  107. package/dist/types/declarations.types.d.ts +20 -0
  108. package/dist/types/dillon-anti-slop.types.d.ts +55 -0
  109. package/dist/types/exports.types.d.ts +11 -0
  110. package/dist/types/files.types.d.ts +85 -0
  111. package/dist/types/layout.types.d.ts +55 -0
  112. package/dist/types/naming.types.d.ts +52 -0
  113. package/dist/types/options.types.d.ts +4 -0
  114. package/dist/types/preset.types.d.ts +248 -129
  115. package/dist/types/react.types.d.ts +14 -0
  116. package/dist/types/schemas.types.d.ts +20 -0
  117. package/dist/types/source.types.d.ts +1 -0
  118. package/dist/types/tests.types.d.ts +39 -0
  119. package/dist/types/types.types.d.ts +20 -0
  120. package/dist/utils/ast.utils.d.ts +19 -0
  121. package/dist/utils/boundaries.utils.d.ts +85 -0
  122. package/dist/utils/declarations.utils.d.ts +21 -0
  123. package/dist/utils/exports.utils.d.ts +6 -0
  124. package/dist/utils/naming.utils.d.ts +11 -0
  125. package/dist/utils/options.utils.d.ts +11 -0
  126. package/dist/utils/react.utils.d.ts +3 -0
  127. package/dist/utils/schemas.utils.d.ts +36 -0
  128. package/dist/utils/source.utils.d.ts +18 -0
  129. package/dist/vendor/dillon-anti-slop/index.js +1770 -0
  130. package/dist/vendor/dillon-anti-slop/rules/no-known-value-widening.d.ts +2 -0
  131. package/dist/vendor/dillon-anti-slop/rules/no-module-mocking.d.ts +2 -0
  132. package/dist/vendor/dillon-anti-slop/shared/dictionary-types.d.ts +5 -0
  133. package/dist/vendor/dillon-anti-slop/shared/expressions.d.ts +5 -0
  134. package/dist/vendor/dillon-anti-slop/shared/lexical-type-parameters.d.ts +2 -0
  135. package/dist/vendor/dillon-anti-slop/shared/reflect-method.d.ts +1 -0
  136. package/dist/vendor/dillon-anti-slop/shared/resolve-variable.d.ts +2 -0
  137. package/dist/vendor/dillon-anti-slop/shared/signatures.d.ts +15 -0
  138. package/dist/vendor/dillon-anti-slop/shared/type-aliases.d.ts +4 -0
  139. package/dist/vendor/dillon-anti-slop/shared/type-environment.d.ts +9 -0
  140. package/dist/vendor/dillon-anti-slop/shared/type-reference-name.d.ts +2 -0
  141. package/dist/vendor/dillon-anti-slop/shared/widening-targets.d.ts +3 -0
  142. package/package.json +51 -43
  143. package/src/{rules → vendor}/dillon-anti-slop/UPSTREAM.md +9 -6
  144. package/dist/configs/boundaries.d.ts +0 -2
  145. package/dist/configs/modules.d.ts +0 -2
  146. package/dist/configs/plugins.d.ts +0 -3
  147. package/dist/configs/react.d.ts +0 -2
  148. package/dist/configs/source.d.ts +0 -2
  149. package/dist/configs/tests.d.ts +0 -2
  150. package/dist/configs/types.d.ts +0 -2
  151. package/dist/constants/preset.constants.d.ts +0 -38
  152. package/dist/constants/test.constants.d.ts +0 -1
  153. package/dist/presets/index.d.ts +0 -4
  154. package/dist/presets/index.js +0 -1736
  155. package/dist/presets/next-react-modules-preset.d.ts +0 -4
  156. package/dist/presets/next-react-modules-preset.js +0 -1729
  157. package/dist/presets/react-modules-preset.d.ts +0 -4
  158. package/dist/presets/react-modules-preset.js +0 -1724
  159. package/dist/presets/tanstack-start-react-modules-preset.d.ts +0 -4
  160. package/dist/presets/tanstack-start-react-modules-preset.js +0 -1729
  161. package/dist/rules/dillon-anti-slop/index.js +0 -2719
  162. package/dist/rules/dillon-anti-slop/rules/no-known-value-widening.d.ts +0 -1
  163. package/dist/rules/dillon-anti-slop/rules/no-module-mocking.d.ts +0 -8
  164. package/dist/rules/dillon-anti-slop/shared/dictionary-types.d.ts +0 -19
  165. package/dist/rules/dillon-anti-slop/shared/lexical-type-parameters.d.ts +0 -4
  166. package/dist/rules/dillon-anti-slop/shared/reflect-method.d.ts +0 -2
  167. package/dist/rules/module-policy/domain-constants.d.ts +0 -2
  168. package/dist/rules/module-policy/import-boundaries.d.ts +0 -2
  169. package/dist/rules/module-policy/index.js +0 -2266
  170. package/dist/rules/module-policy/memoization.d.ts +0 -2
  171. package/dist/rules/module-policy/next-runtime.d.ts +0 -7
  172. package/dist/rules/module-policy/no-unknown.d.ts +0 -6
  173. package/dist/rules/module-policy/reasoned-directives.d.ts +0 -2
  174. package/dist/rules/module-policy/service-functions.d.ts +0 -2
  175. package/dist/rules/module-policy/service-types.d.ts +0 -2
  176. package/dist/rules/module-policy/tanstack-runtime.d.ts +0 -2
  177. package/dist/rules/module-policy/test-assertions.d.ts +0 -2
  178. package/dist/rules/module-policy/test-modifiers.d.ts +0 -2
  179. package/dist/services/preset-compose.d.ts +0 -3
  180. package/dist/services/preset-context.d.ts +0 -2
  181. package/dist/types/module-policy.types.d.ts +0 -39
  182. package/dist/types/test-analysis.types.d.ts +0 -11
  183. package/dist/utils/helpers/ast.d.ts +0 -12
  184. package/dist/utils/helpers/boundaries.d.ts +0 -3
  185. package/dist/utils/helpers/comments.d.ts +0 -6
  186. package/dist/utils/helpers/declarations.d.ts +0 -35
  187. package/dist/utils/helpers/exports.d.ts +0 -18
  188. package/dist/utils/helpers/factories.d.ts +0 -9
  189. package/dist/utils/helpers/guards.d.ts +0 -11
  190. package/dist/utils/helpers/index.d.ts +0 -18
  191. package/dist/utils/helpers/layout.d.ts +0 -15
  192. package/dist/utils/helpers/mocking.d.ts +0 -2
  193. package/dist/utils/helpers/naming.d.ts +0 -13
  194. package/dist/utils/helpers/options.d.ts +0 -22
  195. package/dist/utils/helpers/orpc.d.ts +0 -3
  196. package/dist/utils/helpers/preset.d.ts +0 -9
  197. package/dist/utils/helpers/react-components.d.ts +0 -13
  198. package/dist/utils/helpers/routes.d.ts +0 -5
  199. package/dist/utils/helpers/runtime.d.ts +0 -14
  200. package/dist/utils/helpers/sanitizers.d.ts +0 -3
  201. package/dist/utils/helpers/schemas.d.ts +0 -10
  202. package/dist/utils/helpers/syntax.d.ts +0 -1
  203. package/dist/utils/helpers/test-tables.d.ts +0 -8
  204. package/dist/utils/helpers/trivial.d.ts +0 -6
  205. package/dist/utils/index.d.ts +0 -1
  206. /package/dist/{rules/module-policy/index.d.ts → index.d.ts} +0 -0
  207. /package/dist/{rules → vendor}/dillon-anti-slop/index.d.ts +0 -0
  208. /package/dist/{rules → vendor}/dillon-anti-slop/rules/no-chained-type-assertions.d.ts +0 -0
  209. /package/dist/{rules → vendor}/dillon-anti-slop/rules/no-conditional-empty-object-spread.d.ts +0 -0
  210. /package/dist/{rules → vendor}/dillon-anti-slop/rules/no-object-parameters.d.ts +0 -0
  211. /package/dist/{rules → vendor}/dillon-anti-slop/rules/no-reflect-apply.d.ts +0 -0
  212. /package/dist/{rules → vendor}/dillon-anti-slop/rules/no-reflect-get.d.ts +0 -0
  213. /package/dist/{rules → vendor}/dillon-anti-slop/rules/no-runtime-typeof.d.ts +0 -0
  214. /package/dist/{rules → vendor}/dillon-anti-slop/rules/no-shape-in-symbol-names.d.ts +0 -0
  215. /package/dist/{rules → vendor}/dillon-anti-slop/rules/no-unknown-parameters.d.ts +0 -0
  216. /package/dist/{rules → vendor}/dillon-anti-slop/rules/no-unknown-returns.d.ts +0 -0
  217. /package/dist/{rules → vendor}/dillon-anti-slop/rules/no-unknown-type-aliases.d.ts +0 -0
  218. /package/dist/{rules → vendor}/dillon-anti-slop/rules/no-unsafe-dictionary-type.d.ts +0 -0
  219. /package/dist/{rules → vendor}/dillon-anti-slop/rules/no-widen-then-assert.d.ts +0 -0
  220. /package/dist/{rules → vendor}/dillon-anti-slop/rules/require-safety-comment-for-type-assertion.d.ts +0 -0
  221. /package/src/{rules → vendor}/dillon-anti-slop/LICENSE +0 -0
@@ -0,0 +1,1770 @@
1
+ // src/vendor/dillon-anti-slop/index.ts
2
+ import { eslintCompatPlugin } from "@oxlint/plugins";
3
+
4
+ // src/vendor/dillon-anti-slop/rules/no-chained-type-assertions.ts
5
+ import { defineRule } from "@oxlint/plugins";
6
+
7
+ // src/vendor/dillon-anti-slop/shared/expressions.ts
8
+ function expressionsUnwrapParentheses(expression) {
9
+ let current = expression;
10
+ while (current.type === "ParenthesizedExpression") {
11
+ current = current.expression;
12
+ }
13
+ return current;
14
+ }
15
+ function expressionsIsAssertion(node) {
16
+ return node.type === "TSAsExpression" || node.type === "TSTypeAssertion";
17
+ }
18
+ function expressionsIsConstAssertion(node) {
19
+ return node.typeAnnotation.type === "TSTypeReference" && node.typeAnnotation.typeName.type === "Identifier" && node.typeAnnotation.typeName.name === "const";
20
+ }
21
+
22
+ // src/vendor/dillon-anti-slop/rules/no-chained-type-assertions.ts
23
+ var noChainedTypeAssertionsRule = defineRule({
24
+ meta: {
25
+ type: "problem",
26
+ docs: {
27
+ description: "Disallow chained TypeScript as and angle-bracket assertions, including parenthesized chains."
28
+ },
29
+ messages: {
30
+ chained: "This assertion chain discards type evidence. Keep the original precise type, or parse untrusted input at its boundary before narrowing it."
31
+ }
32
+ },
33
+ createOnce(context) {
34
+ const checkTypeAssertion = (node) => {
35
+ let outer = node;
36
+ let parent = node.parent;
37
+ while (parent.type === "ParenthesizedExpression" && parent.expression === outer) {
38
+ outer = parent;
39
+ parent = parent.parent;
40
+ }
41
+ if (expressionsIsAssertion(parent) && parent.expression === outer) {
42
+ return;
43
+ }
44
+ let assertionCount = 0;
45
+ let hasNonConstAssertion = false;
46
+ let current = node;
47
+ while (expressionsIsAssertion(current)) {
48
+ assertionCount += 1;
49
+ hasNonConstAssertion ||= !expressionsIsConstAssertion(current);
50
+ current = expressionsUnwrapParentheses(current.expression);
51
+ }
52
+ if (assertionCount > 1 && hasNonConstAssertion) {
53
+ context.report({ node, messageId: "chained" });
54
+ }
55
+ };
56
+ return {
57
+ TSAsExpression: checkTypeAssertion,
58
+ TSTypeAssertion: checkTypeAssertion
59
+ };
60
+ }
61
+ });
62
+
63
+ // src/vendor/dillon-anti-slop/rules/no-conditional-empty-object-spread.ts
64
+ import { defineRule as defineRule2 } from "@oxlint/plugins";
65
+ function isEmptyObjectExpression(node) {
66
+ return node.type === "ObjectExpression" && node.properties.length === 0;
67
+ }
68
+ var noConditionalEmptyObjectSpreadRule = defineRule2({
69
+ meta: {
70
+ type: "suggestion",
71
+ docs: {
72
+ description: "Disallow object spreads that conditionally spread an empty object to omit fields."
73
+ },
74
+ messages: {
75
+ avoid: "This conditional spread hides property omission behind an empty object. Build the object in separate statements and add the property only when present."
76
+ }
77
+ },
78
+ createOnce(context) {
79
+ return {
80
+ SpreadElement(node) {
81
+ if (node.parent.type !== "ObjectExpression") {
82
+ return;
83
+ }
84
+ const conditional = expressionsUnwrapParentheses(node.argument);
85
+ if (conditional.type === "ConditionalExpression" && (isEmptyObjectExpression(conditional.consequent) || isEmptyObjectExpression(conditional.alternate))) {
86
+ context.report({ node, messageId: "avoid" });
87
+ }
88
+ }
89
+ };
90
+ }
91
+ });
92
+
93
+ // src/vendor/dillon-anti-slop/rules/no-known-value-widening.ts
94
+ import { defineRule as defineRule4 } from "@oxlint/plugins";
95
+
96
+ // src/vendor/dillon-anti-slop/shared/resolve-variable.ts
97
+ function resolveVariable(sourceCode, identifier) {
98
+ let scope = sourceCode.getScope(identifier);
99
+ while (scope !== null) {
100
+ const variable = scope.set.get(identifier.name);
101
+ if (variable !== undefined) {
102
+ return variable;
103
+ }
104
+ scope = scope.upper;
105
+ }
106
+ return null;
107
+ }
108
+
109
+ // src/utils/ast.utils.ts
110
+ import { defineRule as defineRule3 } from "@oxlint/plugins";
111
+
112
+ // src/utils/options.utils.ts
113
+ class OptionsError extends Error {
114
+ }
115
+ var optionsPatternSchema = {
116
+ anyOf: [{ type: "string" }, { type: "array", items: { type: "string" }, minItems: 1 }]
117
+ };
118
+ function optionsFirst(context, fallback) {
119
+ return context.options[0] ?? fallback;
120
+ }
121
+ function optionsAll(context) {
122
+ return context.options;
123
+ }
124
+ function optionsPatterns(pattern, flags) {
125
+ return optionsPatternsWithEmpty(pattern === undefined ? undefined : [pattern].flat().filter((source) => source !== ""), flags);
126
+ }
127
+ function optionsPatternsWithEmpty(pattern, flags) {
128
+ return pattern === undefined ? [] : [pattern].flat().map((source) => new RegExp(source, flags));
129
+ }
130
+ function optionsPatternsTest(patterns, value) {
131
+ return patterns.some((pattern) => {
132
+ pattern.lastIndex = 0;
133
+ return pattern.test(value);
134
+ });
135
+ }
136
+ function optionsGlob(pattern) {
137
+ const negated = [];
138
+ const source = pattern.replaceAll(/!\(([^()]*)\)/g, (_, options) => {
139
+ negated.push(options.split("|").map((option) => option.replaceAll(/[.+^$()|[\]\\*?{}]/g, "\\$&")).join("|"));
140
+ return `\x02${negated.length - 1}\x03`;
141
+ }).replaceAll(/[.+^$()|[\]\\]/g, "\\$&").replaceAll("?", "[^/]").replaceAll("**/", "\x00").replaceAll("**", "\x01").replaceAll("*", "[^/]*").replaceAll("\x00", "(?:.*/)?").replaceAll("\x01", ".*").replaceAll(/\{([^}]*)\}/g, (_, options) => `(?:${options.split(",").join("|")})`);
142
+ return new RegExp(`^${negated.reduce((text, names, index) => text.replace(`\x02${index}\x03`, `(?!(?:${names})(?:/|$))[^/]*`), source)}$`);
143
+ }
144
+ function optionsPatternLabel(pattern) {
145
+ return pattern === undefined ? "" : [pattern].flat().filter((source) => source !== "").join(" | ");
146
+ }
147
+ function optionsAssertMockingApis(patterns) {
148
+ if (patterns.some((pattern) => !/^(?:\*|(?:vi|jest|\*)\.(?:[A-Za-z_$][\w$]*|\*))$/.test(pattern))) {
149
+ throw new OptionsError("Test mocking APIs must be `*` or `<vi|jest|*>.<method|*>`.");
150
+ }
151
+ }
152
+
153
+ // src/utils/ast.utils.ts
154
+ var astSkippedKeys = new Set(["parent", "type", "start", "end", "range", "loc", "tokens", "comments"]);
155
+ function astIsNode(value) {
156
+ return value !== null && typeof value === "object" && typeof Reflect.get(value, "type") === "string";
157
+ }
158
+ function astVisit(node, ancestors, callback) {
159
+ if (Array.isArray(node)) {
160
+ for (const child of node) {
161
+ astVisit(child, ancestors, callback);
162
+ }
163
+ return;
164
+ }
165
+ if (!astIsNode(node)) {
166
+ return;
167
+ }
168
+ callback(node, ancestors);
169
+ ancestors.push(node);
170
+ for (const key in node) {
171
+ if (Object.hasOwn(node, key) && !astSkippedKeys.has(key)) {
172
+ astVisit(Reflect.get(node, key), ancestors, callback);
173
+ }
174
+ }
175
+ ancestors.pop();
176
+ }
177
+ function astMatchesCallee(name, callees, modifiers) {
178
+ return name !== undefined && callees.some((callee) => name === callee || name.startsWith(`${callee}.`) && name.slice(callee.length + 1).split(".").every((part) => modifiers.has(part)));
179
+ }
180
+ function astIsTypeOnlyImport(node) {
181
+ return node.importKind === "type" || node.specifiers.length > 0 && node.specifiers.every((specifier) => specifier.type === "ImportSpecifier" && specifier.importKind === "type");
182
+ }
183
+ function astStaticString(node) {
184
+ if (node.type === "Literal" && typeof node.value === "string") {
185
+ return node.value;
186
+ }
187
+ if (node.type === "TemplateLiteral" && node.expressions.length === 0) {
188
+ return node.quasis[0]?.value.cooked ?? node.quasis[0]?.value.raw;
189
+ }
190
+ }
191
+ function astContainsJsx(node) {
192
+ let found = false;
193
+ astVisit(node, [], (candidate) => {
194
+ if (candidate.type === "JSXElement" || candidate.type === "JSXFragment") {
195
+ found = true;
196
+ }
197
+ });
198
+ return found;
199
+ }
200
+ function astNearestFunction(ancestors) {
201
+ return ancestors.findLast((node) => node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression");
202
+ }
203
+ function astReturnExpressions(node) {
204
+ if (node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement") {
205
+ return [node.body];
206
+ }
207
+ const expressions = [];
208
+ astVisit(node.body, [node], (candidate, ancestors) => {
209
+ if (candidate.type === "ReturnStatement" && candidate.argument && astNearestFunction(ancestors) === node) {
210
+ expressions.push(candidate.argument);
211
+ }
212
+ });
213
+ return expressions;
214
+ }
215
+ function astSingleExpression(node) {
216
+ if (node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement") {
217
+ return node.body;
218
+ }
219
+ if (node.body?.type !== "BlockStatement") {
220
+ return null;
221
+ }
222
+ const statements = node.body.body.filter((statement2) => statement2.type !== "EmptyStatement" && !(statement2.type === "ExpressionStatement" && statement2.directive));
223
+ if (statements.length !== 1) {
224
+ return null;
225
+ }
226
+ const [statement] = statements;
227
+ if (statement.type === "ReturnStatement") {
228
+ return statement.argument;
229
+ }
230
+ return statement.type === "ExpressionStatement" ? statement.expression : null;
231
+ }
232
+ function astUnwrap(expression) {
233
+ if (expression.type === "AwaitExpression") {
234
+ return astUnwrap(expression.argument);
235
+ }
236
+ if (expression.type === "ParenthesizedExpression" || expression.type === "TSAsExpression" || expression.type === "TSSatisfiesExpression" || expression.type === "TSTypeAssertion" || expression.type === "TSNonNullExpression" || expression.type === "ChainExpression") {
237
+ return astUnwrap(expression.expression);
238
+ }
239
+ return expression;
240
+ }
241
+ function astCallRoot(expression) {
242
+ if (expression.type === "Identifier") {
243
+ return expression.name;
244
+ }
245
+ return expression.type === "MemberExpression" && !expression.computed && !expression.optional ? astCallRoot(expression.object) : undefined;
246
+ }
247
+ function astIsForwarder(node, expression) {
248
+ const value = astUnwrap(expression);
249
+ if (value.type === "Literal") {
250
+ return !("regex" in value);
251
+ }
252
+ if (value.type === "TemplateLiteral") {
253
+ return value.expressions.length === 0;
254
+ }
255
+ if (value.type === "Identifier") {
256
+ return true;
257
+ }
258
+ if (value.type !== "CallExpression" || value.optional) {
259
+ return false;
260
+ }
261
+ const root = astCallRoot(value.callee);
262
+ if (!root || node.params.some((param) => param.type !== "Identifier")) {
263
+ return false;
264
+ }
265
+ const receiver = value.callee.type === "MemberExpression" ? root : undefined;
266
+ const forwarded = node.params.flatMap((param) => param.type === "Identifier" && param.name !== receiver ? [param.name] : []);
267
+ return value.arguments.length === forwarded.length && value.arguments.every((argument, index) => argument.type === "Identifier" && argument.name === forwarded[index]);
268
+ }
269
+ function astModuleName(node) {
270
+ return node.type === "Identifier" ? node.name : node.value;
271
+ }
272
+ function astBindings(pattern) {
273
+ switch (pattern.type) {
274
+ case "Identifier":
275
+ return [pattern];
276
+ case "AssignmentPattern":
277
+ return astBindings(pattern.left);
278
+ case "RestElement":
279
+ return astBindings(pattern.argument);
280
+ case "ObjectPattern":
281
+ return pattern.properties.flatMap((property) => astBindings(property.type === "RestElement" ? property : property.value));
282
+ case "ArrayPattern":
283
+ return pattern.elements.flatMap((element) => element ? astBindings(element) : []);
284
+ }
285
+ }
286
+ function astDeclaration(statement) {
287
+ return statement.type === "ExportNamedDeclaration" || statement.type === "ExportDefaultDeclaration" ? statement.declaration : statement;
288
+ }
289
+ function astMemberName(node) {
290
+ return !node.computed && node.property.type === "Identifier" ? node.property.name : undefined;
291
+ }
292
+ function astDottedName(node) {
293
+ if (node.type === "Identifier") {
294
+ return node.name;
295
+ }
296
+ if (node.type !== "MemberExpression") {
297
+ return;
298
+ }
299
+ const object = astDottedName(node.object);
300
+ const property = astMemberName(node);
301
+ return object && property ? `${object}.${property}` : undefined;
302
+ }
303
+ function astCallName(node) {
304
+ if (node.callee.type === "Identifier") {
305
+ return node.callee.name;
306
+ }
307
+ return node.callee.type === "MemberExpression" ? astMemberName(node.callee) : undefined;
308
+ }
309
+ function astSelectorRule(selector, message) {
310
+ return defineRule3({
311
+ meta: {
312
+ type: "problem",
313
+ schema: [{ type: "object", properties: { message: { type: "string" } }, additionalProperties: false }],
314
+ messages: { forbidden: "{{message}}" }
315
+ },
316
+ createOnce(context) {
317
+ return {
318
+ [selector]: (node) => {
319
+ const options = optionsFirst(context, {});
320
+ context.report({
321
+ node,
322
+ messageId: "forbidden",
323
+ data: { message: options.message ?? message }
324
+ });
325
+ }
326
+ };
327
+ }
328
+ });
329
+ }
330
+
331
+ // src/vendor/dillon-anti-slop/shared/type-reference-name.ts
332
+ function typeReferenceName(type) {
333
+ return type.typeName.type === "Identifier" ? type.typeName.name : null;
334
+ }
335
+
336
+ // src/vendor/dillon-anti-slop/shared/type-environment.ts
337
+ var BUILT_INS = new Set(["Record", "Readonly", "Partial", "Required", "Pick", "Omit", "PropertyKey", "NonNullable"]);
338
+ var TRANSPARENT_WRAPPERS = new Set(["Readonly", "Partial", "Required", "NonNullable"]);
339
+ function typeEnvironmentCreate(program) {
340
+ const aliases = new Map;
341
+ const interfaces = new Map;
342
+ const shadowedBuiltIns = new Set;
343
+ for (const statement of program.body) {
344
+ const declaration = astDeclaration(statement);
345
+ if (declaration?.type === "ImportDeclaration") {
346
+ for (const specifier of declaration.specifiers) {
347
+ if (BUILT_INS.has(specifier.local.name)) {
348
+ shadowedBuiltIns.add(specifier.local.name);
349
+ }
350
+ }
351
+ continue;
352
+ }
353
+ if (declaration?.type === "TSTypeAliasDeclaration") {
354
+ const existing = aliases.get(declaration.id.name);
355
+ if (existing === undefined) {
356
+ aliases.set(declaration.id.name, declaration);
357
+ } else {
358
+ shadowedBuiltIns.add(declaration.id.name);
359
+ }
360
+ if (BUILT_INS.has(declaration.id.name)) {
361
+ shadowedBuiltIns.add(declaration.id.name);
362
+ }
363
+ continue;
364
+ }
365
+ if (declaration?.type === "TSInterfaceDeclaration") {
366
+ const declarations = interfaces.get(declaration.id.name) ?? [];
367
+ declarations.push(declaration);
368
+ interfaces.set(declaration.id.name, declarations);
369
+ if (BUILT_INS.has(declaration.id.name)) {
370
+ shadowedBuiltIns.add(declaration.id.name);
371
+ }
372
+ continue;
373
+ }
374
+ if (declaration?.type === "TSEnumDeclaration") {
375
+ if (BUILT_INS.has(declaration.id.name)) {
376
+ shadowedBuiltIns.add(declaration.id.name);
377
+ }
378
+ continue;
379
+ }
380
+ if ((declaration?.type === "ClassDeclaration" || declaration?.type === "FunctionDeclaration") && declaration.id !== null && BUILT_INS.has(declaration.id.name)) {
381
+ shadowedBuiltIns.add(declaration.id.name);
382
+ }
383
+ }
384
+ return { aliases, interfaces, shadowedBuiltIns };
385
+ }
386
+ function typeEnvironmentIsBuiltIn(name, environment) {
387
+ return BUILT_INS.has(name) && !environment.shadowedBuiltIns.has(name);
388
+ }
389
+ function typeEnvironmentUnwrap(type) {
390
+ let current = type;
391
+ while (current.type === "TSParenthesizedType" || current.type === "TSTypeOperator" && current.operator === "readonly") {
392
+ current = current.typeAnnotation;
393
+ }
394
+ return current;
395
+ }
396
+ function typeEnvironmentReference(type, environment) {
397
+ if (type.type !== "TSTypeReference") {
398
+ return null;
399
+ }
400
+ const name = typeReferenceName(type);
401
+ if (name === null) {
402
+ return null;
403
+ }
404
+ return {
405
+ reference: type,
406
+ name,
407
+ transparent: TRANSPARENT_WRAPPERS.has(name) && typeEnvironmentIsBuiltIn(name, environment),
408
+ argument: type.typeArguments?.params.at(0)
409
+ };
410
+ }
411
+ function typeEnvironmentIsUnappliedReference(type, name) {
412
+ const unwrapped = typeEnvironmentUnwrap(type);
413
+ return unwrapped.type === "TSTypeReference" && typeReferenceName(unwrapped) === name && (unwrapped.typeArguments?.params.length ?? 0) === 0;
414
+ }
415
+ function resolvedSubstitutionArgument(type, base, resolving = new Set) {
416
+ const unwrapped = typeEnvironmentUnwrap(type);
417
+ if (unwrapped.type !== "TSTypeReference") {
418
+ return type;
419
+ }
420
+ const name = typeReferenceName(unwrapped);
421
+ if (name === null || resolving.has(name)) {
422
+ return type;
423
+ }
424
+ const substitution = base.get(name);
425
+ if (substitution === undefined) {
426
+ return type;
427
+ }
428
+ const nextResolving = new Set(resolving);
429
+ nextResolving.add(name);
430
+ return resolvedSubstitutionArgument(substitution, base, nextResolving);
431
+ }
432
+ function typeEnvironmentSubstitution(alias, type, base) {
433
+ const parameters = alias.typeParameters?.params ?? [];
434
+ const arguments_ = type.typeArguments?.params ?? [];
435
+ const next = new Map(base);
436
+ for (const [index, parameter] of parameters.entries()) {
437
+ const argument = arguments_.at(index) ?? parameter.default;
438
+ if (!argument) {
439
+ return null;
440
+ }
441
+ next.set(parameter.name.name, resolvedSubstitutionArgument(argument, next));
442
+ }
443
+ return next;
444
+ }
445
+ function typeEnvironmentResolveAlias(name, reference, environment, substitutions, resolving) {
446
+ const alias = environment.aliases.get(name);
447
+ if (alias === undefined || resolving.has(name)) {
448
+ return null;
449
+ }
450
+ const nextSubstitutions = typeEnvironmentSubstitution(alias, reference, substitutions);
451
+ if (nextSubstitutions === null) {
452
+ return null;
453
+ }
454
+ const nextResolving = new Set(resolving);
455
+ nextResolving.add(name);
456
+ return { type: alias.typeAnnotation, substitutions: nextSubstitutions, resolving: nextResolving };
457
+ }
458
+
459
+ // src/vendor/dillon-anti-slop/shared/dictionary-types.ts
460
+ function isEffectivelyEmptyMember(member) {
461
+ return member.type === "TSPropertySignature" && member.optional && member.typeAnnotation !== null && typeEnvironmentUnwrap(member.typeAnnotation.typeAnnotation).type === "TSNeverKeyword";
462
+ }
463
+ function dictionaryTypesUnsafeValue(type, environment, substitutions, resolvingAliases) {
464
+ const unwrapped = typeEnvironmentUnwrap(type);
465
+ if (unwrapped.type === "TSUnknownKeyword") {
466
+ return "unknown";
467
+ }
468
+ if (unwrapped.type === "TSAnyKeyword") {
469
+ return "any";
470
+ }
471
+ if (unwrapped.type === "TSObjectKeyword") {
472
+ return "object";
473
+ }
474
+ if (unwrapped.type === "TSTypeLiteral" && unwrapped.members.every(isEffectivelyEmptyMember)) {
475
+ return "empty-object";
476
+ }
477
+ if (unwrapped.type === "TSUnionType") {
478
+ return unwrapped.types.some((member) => dictionaryTypesUnsafeValue(member, environment, substitutions, resolvingAliases) !== null) ? "union" : null;
479
+ }
480
+ if (unwrapped.type === "TSIntersectionType") {
481
+ const unsafeMembers = unwrapped.types.map((member) => dictionaryTypesUnsafeValue(member, environment, substitutions, resolvingAliases));
482
+ if (unsafeMembers.includes("any")) {
483
+ return "any";
484
+ }
485
+ return unsafeMembers.length > 0 && unsafeMembers.every((member) => member !== null) ? unsafeMembers[0] : null;
486
+ }
487
+ const named = typeEnvironmentReference(unwrapped, environment);
488
+ if (named === null) {
489
+ return null;
490
+ }
491
+ const { reference, name } = named;
492
+ if (named.transparent) {
493
+ return named.argument === undefined ? null : dictionaryTypesUnsafeValue(named.argument, environment, substitutions, resolvingAliases);
494
+ }
495
+ const substitution = substitutions.get(name);
496
+ if (substitution !== undefined) {
497
+ return typeEnvironmentIsUnappliedReference(substitution, name) ? null : dictionaryTypesUnsafeValue(substitution, environment, substitutions, resolvingAliases);
498
+ }
499
+ const interfaceDeclarations = environment.interfaces.get(name);
500
+ if (interfaceDeclarations !== undefined) {
501
+ const [declaration] = interfaceDeclarations;
502
+ return interfaceDeclarations.length === 1 && declaration.extends.length === 0 && declaration.body.body.every(isEffectivelyEmptyMember) ? "empty-object" : null;
503
+ }
504
+ const step = typeEnvironmentResolveAlias(name, reference, environment, substitutions, resolvingAliases);
505
+ return step === null ? null : dictionaryTypesUnsafeValue(step.type, environment, step.substitutions, step.resolving);
506
+ }
507
+ function dictionaryTypesValueTypes(type, environment, substitutions, resolvingAliases) {
508
+ const unwrapped = typeEnvironmentUnwrap(type);
509
+ if (unwrapped.type === "TSTypeLiteral") {
510
+ return unwrapped.members.flatMap((member) => member.type === "TSIndexSignature" ? [{ type: member.typeAnnotation.typeAnnotation, substitutions }] : []);
511
+ }
512
+ if (unwrapped.type === "TSMappedType") {
513
+ return unwrapped.typeAnnotation === null ? [] : [{ type: unwrapped.typeAnnotation, substitutions }];
514
+ }
515
+ const named = typeEnvironmentReference(unwrapped, environment);
516
+ if (named === null) {
517
+ return [];
518
+ }
519
+ const { reference, name } = named;
520
+ const substitution = substitutions.get(name);
521
+ if (substitution !== undefined) {
522
+ return typeEnvironmentIsUnappliedReference(substitution, name) ? [] : dictionaryTypesValueTypes(substitution, environment, substitutions, resolvingAliases);
523
+ }
524
+ if (named.transparent) {
525
+ return named.argument === undefined ? [] : dictionaryTypesValueTypes(named.argument, environment, substitutions, resolvingAliases);
526
+ }
527
+ if (name === "Record" && typeEnvironmentIsBuiltIn(name, environment)) {
528
+ const value = reference.typeArguments?.params[1] ?? null;
529
+ return value === null ? [] : [{ type: value, substitutions }];
530
+ }
531
+ if ((name === "Pick" || name === "Omit") && typeEnvironmentIsBuiltIn(name, environment)) {
532
+ const source = reference.typeArguments?.params[0];
533
+ return source === undefined ? [] : dictionaryTypesValueTypes(source, environment, substitutions, resolvingAliases);
534
+ }
535
+ const step = typeEnvironmentResolveAlias(name, reference, environment, substitutions, resolvingAliases);
536
+ return step === null ? [] : dictionaryTypesValueTypes(step.type, environment, step.substitutions, step.resolving);
537
+ }
538
+ function dictionaryTypesClassify(type, environment) {
539
+ for (const valueType of dictionaryTypesValueTypes(type, environment, new Map, new Set)) {
540
+ const unsafeValue = dictionaryTypesUnsafeValue(valueType.type, environment, valueType.substitutions, new Set);
541
+ if (unsafeValue !== null) {
542
+ return unsafeValue;
543
+ }
544
+ }
545
+ return null;
546
+ }
547
+
548
+ // src/vendor/dillon-anti-slop/shared/widening-targets.ts
549
+ function keywordTarget(type) {
550
+ if (type.type === "TSUnknownKeyword") {
551
+ return { kind: "unknown" };
552
+ }
553
+ return type.type === "TSObjectKeyword" ? { kind: "object" } : null;
554
+ }
555
+ function isBroadMappedKey(type, environment, substitutions) {
556
+ const unwrapped = typeEnvironmentUnwrap(type);
557
+ if (unwrapped.type === "TSStringKeyword" || unwrapped.type === "TSNumberKeyword" || unwrapped.type === "TSSymbolKeyword") {
558
+ return true;
559
+ }
560
+ if (unwrapped.type === "TSUnionType") {
561
+ return unwrapped.types.every((member) => isBroadMappedKey(member, environment, substitutions));
562
+ }
563
+ const named = typeEnvironmentReference(unwrapped, environment);
564
+ if (named === null) {
565
+ return false;
566
+ }
567
+ const { name } = named;
568
+ const substitution = substitutions.get(name);
569
+ if (substitution !== undefined && !typeEnvironmentIsUnappliedReference(substitution, name)) {
570
+ return isBroadMappedKey(substitution, environment, substitutions);
571
+ }
572
+ return name === "PropertyKey" && typeEnvironmentIsBuiltIn(name, environment);
573
+ }
574
+ function classifyAliasBroadTarget(type, environment, substitutions, resolvingAliases) {
575
+ const unwrapped = typeEnvironmentUnwrap(type);
576
+ const keyword = keywordTarget(unwrapped);
577
+ if (keyword !== null) {
578
+ return keyword;
579
+ }
580
+ if (unwrapped.type === "TSTypeLiteral") {
581
+ return unwrapped.members.some((member) => member.type === "TSIndexSignature") ? { kind: "open dictionary" } : null;
582
+ }
583
+ if (unwrapped.type === "TSMappedType") {
584
+ return isBroadMappedKey(unwrapped.constraint, environment, substitutions) ? { kind: "open dictionary" } : null;
585
+ }
586
+ const named = typeEnvironmentReference(unwrapped, environment);
587
+ if (named === null) {
588
+ return null;
589
+ }
590
+ const { reference, name } = named;
591
+ const substitution = substitutions.get(name);
592
+ if (substitution !== undefined) {
593
+ return typeEnvironmentIsUnappliedReference(substitution, name) ? null : classifyAliasBroadTarget(substitution, environment, substitutions, resolvingAliases);
594
+ }
595
+ if (named.transparent) {
596
+ return named.argument === undefined ? null : classifyAliasBroadTarget(named.argument, environment, substitutions, resolvingAliases);
597
+ }
598
+ if (name === "Record" && typeEnvironmentIsBuiltIn(name, environment)) {
599
+ return { kind: "open dictionary" };
600
+ }
601
+ const step = typeEnvironmentResolveAlias(name, reference, environment, substitutions, resolvingAliases);
602
+ return step === null ? null : classifyAliasBroadTarget(step.type, environment, step.substitutions, step.resolving);
603
+ }
604
+ function wideningTargetsClassify(type, environment) {
605
+ const unwrapped = typeEnvironmentUnwrap(type);
606
+ const keyword = keywordTarget(unwrapped);
607
+ if (keyword !== null) {
608
+ return keyword;
609
+ }
610
+ if (unwrapped.type === "TSTypeLiteral") {
611
+ if (unwrapped.members.some((member) => member.type === "TSIndexSignature")) {
612
+ return { kind: "open dictionary" };
613
+ }
614
+ return unwrapped.members.length > 0 ? { kind: "anonymous object" } : null;
615
+ }
616
+ if (unwrapped.type === "TSMappedType") {
617
+ return { kind: "open dictionary" };
618
+ }
619
+ const named = typeEnvironmentReference(unwrapped, environment);
620
+ if (named === null) {
621
+ return null;
622
+ }
623
+ const { reference, name } = named;
624
+ if (named.transparent) {
625
+ return named.argument === undefined ? null : wideningTargetsClassify(named.argument, environment);
626
+ }
627
+ if (name === "Record" && typeEnvironmentIsBuiltIn(name, environment)) {
628
+ return { kind: "open dictionary" };
629
+ }
630
+ const alias = environment.aliases.get(name);
631
+ if (alias === undefined) {
632
+ return null;
633
+ }
634
+ const substitutions = typeEnvironmentSubstitution(alias, reference, new Map);
635
+ if ((alias.typeParameters?.params.length ?? 0) > 0) {
636
+ return substitutions !== null && dictionaryTypesValueTypes(alias.typeAnnotation, environment, substitutions, new Set([name])).length > 0 ? { kind: "generic container" } : null;
637
+ }
638
+ return substitutions === null ? null : classifyAliasBroadTarget(alias.typeAnnotation, environment, substitutions, new Set([name]));
639
+ }
640
+
641
+ // src/vendor/dillon-anti-slop/rules/no-known-value-widening.ts
642
+ function unwrapExpression(expression) {
643
+ let current = expression;
644
+ while (current.type === "ParenthesizedExpression" || current.type === "TSAsExpression" || current.type === "TSSatisfiesExpression" || current.type === "TSTypeAssertion" || current.type === "TSNonNullExpression") {
645
+ current = current.expression;
646
+ }
647
+ return current;
648
+ }
649
+ function variableDeclarator(variable) {
650
+ if (variable.defs.length !== 1) {
651
+ return null;
652
+ }
653
+ const [definition] = variable.defs;
654
+ return definition.type === "Variable" && definition.node.type === "VariableDeclarator" ? definition.node : null;
655
+ }
656
+ function hasKnownEvidence(sourceCode, expression, visitedVariables = new Set) {
657
+ const unwrapped = unwrapExpression(expression);
658
+ if (unwrapped.type === "ObjectExpression" || unwrapped.type === "ArrayExpression" || unwrapped.type === "ArrowFunctionExpression" || unwrapped.type === "ClassExpression" || unwrapped.type === "FunctionExpression" || unwrapped.type === "NewExpression" || unwrapped.type === "Literal" || unwrapped.type === "TemplateLiteral" || unwrapped.type === "UnaryExpression") {
659
+ return true;
660
+ }
661
+ if (unwrapped.type !== "Identifier") {
662
+ return false;
663
+ }
664
+ const variable = resolveVariable(sourceCode, unwrapped);
665
+ if (variable === null || visitedVariables.has(variable)) {
666
+ return false;
667
+ }
668
+ const declarator = variableDeclarator(variable);
669
+ if (declarator === null) {
670
+ return false;
671
+ }
672
+ if (declarator.init === null || declarator.parent.type !== "VariableDeclaration" || declarator.parent.kind !== "const" || !variable.references.every((reference) => reference.init || !reference.isWrite())) {
673
+ return false;
674
+ }
675
+ visitedVariables.add(variable);
676
+ return hasKnownEvidence(sourceCode, declarator.init, visitedVariables);
677
+ }
678
+ function sourceKeyName(sourceCode, key) {
679
+ if (key.type === "Identifier" || key.type === "PrivateIdentifier") {
680
+ return key.name;
681
+ }
682
+ if (key.type === "Literal") {
683
+ return String(key.value);
684
+ }
685
+ return sourceCode.getText(key);
686
+ }
687
+ function functionName(sourceCode, owner) {
688
+ if (owner === null) {
689
+ return "anonymous function";
690
+ }
691
+ if (owner.id !== null) {
692
+ return owner.id.name;
693
+ }
694
+ const parent = owner.parent;
695
+ if (parent.type === "VariableDeclarator" && parent.id.type === "Identifier") {
696
+ return parent.id.name;
697
+ }
698
+ if (parent.type === "MethodDefinition") {
699
+ return sourceKeyName(sourceCode, parent.key);
700
+ }
701
+ return "anonymous function";
702
+ }
703
+ function hasParentAssertion(node) {
704
+ return node.parent?.type === "TSAsExpression" || node.parent?.type === "TSTypeAssertion";
705
+ }
706
+ var noKnownValueWideningRule = defineRule4({
707
+ meta: {
708
+ type: "problem",
709
+ docs: {
710
+ description: "Disallow syntactically established values from flowing into explicitly broad or anonymous target types that discard useful evidence."
711
+ },
712
+ messages: {
713
+ widening: "The explicit {{target}} type on {{subject}} discards known type evidence. Keep inference, validate with `satisfies`, or use a named owner contract."
714
+ }
715
+ },
716
+ createOnce(context) {
717
+ let environment = null;
718
+ const reportFlow = (expression, destination, subject) => {
719
+ if (destination === null) {
720
+ return;
721
+ }
722
+ const unwrapped = unwrapExpression(expression);
723
+ if ((destination.kind === "open dictionary" || destination.kind === "generic container") && unwrapped.type === "ObjectExpression" && unwrapped.properties.length === 0) {
724
+ return;
725
+ }
726
+ if (!hasKnownEvidence(context.sourceCode, expression)) {
727
+ return;
728
+ }
729
+ context.report({
730
+ node: expression,
731
+ messageId: "widening",
732
+ data: { subject, target: destination.kind }
733
+ });
734
+ };
735
+ const targetFromAnnotation = (annotation) => environment === null || annotation === null || annotation === undefined ? null : wideningTargetsClassify(annotation.typeAnnotation, environment);
736
+ return {
737
+ Program(node) {
738
+ environment = typeEnvironmentCreate(node);
739
+ },
740
+ VariableDeclarator(node) {
741
+ if (node.init === null || node.id.type !== "Identifier") {
742
+ return;
743
+ }
744
+ reportFlow(node.init, targetFromAnnotation(node.id.typeAnnotation), `binding \`${node.id.name}\``);
745
+ },
746
+ PropertyDefinition(node) {
747
+ if (node.value === null) {
748
+ return;
749
+ }
750
+ reportFlow(node.value, targetFromAnnotation(node.typeAnnotation), `property \`${sourceKeyName(context.sourceCode, node.key)}\``);
751
+ },
752
+ AccessorProperty(node) {
753
+ if (node.value === null) {
754
+ return;
755
+ }
756
+ reportFlow(node.value, targetFromAnnotation(node.typeAnnotation), `property \`${sourceKeyName(context.sourceCode, node.key)}\``);
757
+ },
758
+ AssignmentExpression(node) {
759
+ if (node.operator !== "=" || node.left.type !== "Identifier") {
760
+ return;
761
+ }
762
+ const variable = resolveVariable(context.sourceCode, node.left);
763
+ const declarator = variable === null ? null : variableDeclarator(variable);
764
+ if (declarator?.id.type !== "Identifier") {
765
+ return;
766
+ }
767
+ reportFlow(node.right, targetFromAnnotation(declarator.id.typeAnnotation), `binding \`${declarator.id.name}\``);
768
+ },
769
+ ReturnStatement(node) {
770
+ if (node.argument === null) {
771
+ return;
772
+ }
773
+ let owner = null;
774
+ let current = node.parent;
775
+ while (owner === null && current.type !== "Program") {
776
+ if (current.type === "ArrowFunctionExpression" || current.type === "FunctionDeclaration" || current.type === "FunctionExpression") {
777
+ owner = current;
778
+ }
779
+ current = current.parent;
780
+ }
781
+ reportFlow(node.argument, targetFromAnnotation(owner?.returnType), `return value of \`${functionName(context.sourceCode, owner)}\``);
782
+ },
783
+ ArrowFunctionExpression(node) {
784
+ if (node.body.type === "BlockStatement") {
785
+ return;
786
+ }
787
+ reportFlow(node.body, targetFromAnnotation(node.returnType), `return value of \`${functionName(context.sourceCode, node)}\``);
788
+ },
789
+ TSAsExpression(node) {
790
+ if (environment === null || hasParentAssertion(node)) {
791
+ return;
792
+ }
793
+ reportFlow(node.expression, wideningTargetsClassify(node.typeAnnotation, environment), "assertion");
794
+ },
795
+ TSTypeAssertion(node) {
796
+ if (environment === null || hasParentAssertion(node)) {
797
+ return;
798
+ }
799
+ reportFlow(node.expression, wideningTargetsClassify(node.typeAnnotation, environment), "assertion");
800
+ }
801
+ };
802
+ }
803
+ });
804
+
805
+ // src/vendor/dillon-anti-slop/rules/no-module-mocking.ts
806
+ import { defineRule as defineRule5 } from "@oxlint/plugins";
807
+ var moduleMockMethods = new Set(["doMock", "mock", "unstable_mockModule"]);
808
+ var defaultDeny = [
809
+ { api: "*.mock" },
810
+ { api: "*.doMock" },
811
+ { api: "*.unstable_mockModule" }
812
+ ];
813
+ function testFramework(sourceCode, expression) {
814
+ if (expression.type !== "Identifier") {
815
+ return null;
816
+ }
817
+ const name = expression.name === "vi" || expression.name === "jest" ? expression.name : null;
818
+ if (name !== null && sourceCode.isGlobalReference(expression)) {
819
+ return name;
820
+ }
821
+ const variable = resolveVariable(sourceCode, expression);
822
+ if (variable === null || variable.defs.length === 0) {
823
+ return name;
824
+ }
825
+ for (const definition of variable.defs) {
826
+ if (definition.type !== "ImportBinding" || definition.parent?.type !== "ImportDeclaration") {
827
+ continue;
828
+ }
829
+ const source = definition.parent.source.value;
830
+ const specifier = definition.node;
831
+ let imported = null;
832
+ if (specifier.type === "ImportSpecifier") {
833
+ imported = astModuleName(specifier.imported);
834
+ }
835
+ if (source === "vitest" && imported === "vi") {
836
+ return "vi";
837
+ }
838
+ if (source === "@jest/globals" && imported === "jest") {
839
+ return "jest";
840
+ }
841
+ }
842
+ return null;
843
+ }
844
+ function propertyName(key, computed) {
845
+ if (key.type === "Literal" && typeof key.value === "string") {
846
+ return key.value;
847
+ }
848
+ return !computed && key.type === "Identifier" ? key.name : null;
849
+ }
850
+ function apiParts(api) {
851
+ const dot = api.indexOf(".");
852
+ return [api.slice(0, dot), api.slice(dot + 1)];
853
+ }
854
+ function apiMatches(pattern, api) {
855
+ if (pattern === "*") {
856
+ return true;
857
+ }
858
+ const [patternFramework, patternMethod] = apiParts(pattern);
859
+ const [framework, method] = apiParts(api);
860
+ return (patternFramework === "*" || patternFramework === framework) && (patternMethod === "*" || patternMethod === method);
861
+ }
862
+ var noModuleMockingRule = defineRule5({
863
+ meta: {
864
+ type: "problem",
865
+ docs: {
866
+ description: "Disallow Vitest and Jest module mocking; tests must replace dependencies through real interfaces."
867
+ },
868
+ schema: [
869
+ {
870
+ type: "object",
871
+ additionalProperties: false,
872
+ properties: {
873
+ deny: {
874
+ type: "array",
875
+ items: {
876
+ anyOf: [
877
+ { type: "string" },
878
+ {
879
+ type: "object",
880
+ additionalProperties: false,
881
+ properties: {
882
+ api: { type: "string" },
883
+ message: { type: "string" }
884
+ },
885
+ required: ["api"]
886
+ }
887
+ ]
888
+ }
889
+ },
890
+ allow: { type: "array", items: { type: "string" } },
891
+ checkDestructured: { type: "boolean" }
892
+ }
893
+ }
894
+ ],
895
+ messages: {
896
+ moduleMock: "Replace module mocking with dependency injection through a real interface, service layer, or faithful test implementation.",
897
+ testDouble: "Replace {{api}} with dependency injection through a real interface, service layer, or faithful test implementation.",
898
+ custom: "{{message}}"
899
+ }
900
+ },
901
+ createOnce(context) {
902
+ let deny = [];
903
+ let allow = [];
904
+ let checkDestructured = false;
905
+ return {
906
+ before() {
907
+ const options = optionsFirst(context, {});
908
+ deny = (options.deny ?? defaultDeny).map((entry) => typeof entry === "string" ? { api: entry } : entry);
909
+ allow = options.allow ?? [];
910
+ checkDestructured = options.checkDestructured ?? false;
911
+ optionsAssertMockingApis([...deny.map((entry) => entry.api), ...allow]);
912
+ },
913
+ CallExpression(node) {
914
+ const { callee } = node;
915
+ let framework = null;
916
+ let method = null;
917
+ if (callee.type === "MemberExpression") {
918
+ framework = testFramework(context.sourceCode, callee.object);
919
+ method = framework === null ? null : propertyName(callee.property, callee.computed);
920
+ } else if (checkDestructured && callee.type === "Identifier") {
921
+ const definition = resolveVariable(context.sourceCode, callee)?.defs[0];
922
+ const declarator = definition?.parent?.type === "VariableDeclaration" && definition.parent.kind === "const" ? definition.node : null;
923
+ if (declarator?.type === "VariableDeclarator" && declarator.id.type === "ObjectPattern" && declarator.init !== null) {
924
+ framework = testFramework(context.sourceCode, declarator.init);
925
+ const property = framework === null ? undefined : declarator.id.properties.find((candidate) => {
926
+ if (candidate.type !== "Property") {
927
+ return false;
928
+ }
929
+ const binding = candidate.value.type === "AssignmentPattern" ? candidate.value.left : candidate.value;
930
+ return binding.type === "Identifier" && binding.name === callee.name;
931
+ });
932
+ method = property === undefined ? null : propertyName(property.key, property.computed);
933
+ }
934
+ }
935
+ if (framework === null || method === null) {
936
+ return;
937
+ }
938
+ const api = `${framework}.${method}`;
939
+ if (allow.some((pattern) => apiMatches(pattern, api))) {
940
+ return;
941
+ }
942
+ const denied = deny.find((entry) => apiMatches(entry.api, api));
943
+ if (denied === undefined) {
944
+ return;
945
+ }
946
+ if (denied.message !== undefined) {
947
+ context.report({
948
+ node,
949
+ messageId: "custom",
950
+ data: { message: denied.message }
951
+ });
952
+ return;
953
+ }
954
+ context.report({
955
+ node,
956
+ messageId: moduleMockMethods.has(apiParts(api)[1]) ? "moduleMock" : "testDouble",
957
+ data: { api }
958
+ });
959
+ }
960
+ };
961
+ }
962
+ });
963
+
964
+ // src/vendor/dillon-anti-slop/rules/no-object-parameters.ts
965
+ import { defineRule as defineRule6 } from "@oxlint/plugins";
966
+
967
+ // src/vendor/dillon-anti-slop/shared/lexical-type-parameters.ts
968
+ function isNode(value) {
969
+ return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
970
+ }
971
+ function collectInferTypeParameterNames(node, visitorKeys, names) {
972
+ if (node.type === "TSInferType") {
973
+ names.add(node.typeParameter.name.name);
974
+ }
975
+ for (const key of visitorKeys[node.type] ?? []) {
976
+ const value = Reflect.get(node, key);
977
+ if (isNode(value)) {
978
+ collectInferTypeParameterNames(value, visitorKeys, names);
979
+ continue;
980
+ }
981
+ if (!Array.isArray(value)) {
982
+ continue;
983
+ }
984
+ for (const child of value) {
985
+ if (isNode(child)) {
986
+ collectInferTypeParameterNames(child, visitorKeys, names);
987
+ }
988
+ }
989
+ }
990
+ }
991
+ function lexicalTypeParametersNames(node, visitorKeys) {
992
+ const names = new Set;
993
+ let descendant = node;
994
+ let current = node;
995
+ while (current.type !== "Program") {
996
+ if ("typeParameters" in current) {
997
+ for (const parameter of current.typeParameters?.params ?? []) {
998
+ names.add(parameter.name.name);
999
+ }
1000
+ }
1001
+ if (current.type === "TSMappedType" && (descendant === current.nameType || descendant === current.typeAnnotation)) {
1002
+ names.add(current.key.name);
1003
+ }
1004
+ if (current.type === "TSConditionalType" && descendant === current.trueType) {
1005
+ collectInferTypeParameterNames(current.extendsType, visitorKeys, names);
1006
+ }
1007
+ descendant = current;
1008
+ current = current.parent;
1009
+ }
1010
+ return names;
1011
+ }
1012
+
1013
+ // src/vendor/dillon-anti-slop/shared/signatures.ts
1014
+ function signaturesParameterAnnotation(parameter) {
1015
+ if (parameter.type === "TSParameterProperty") {
1016
+ return signaturesParameterAnnotation(parameter.parameter);
1017
+ }
1018
+ if (parameter.type === "RestElement") {
1019
+ return parameter.typeAnnotation ?? signaturesParameterAnnotation(parameter.argument);
1020
+ }
1021
+ if (parameter.type === "AssignmentPattern") {
1022
+ return parameter.typeAnnotation ?? parameter.left.typeAnnotation;
1023
+ }
1024
+ return parameter.typeAnnotation;
1025
+ }
1026
+ function signaturesListeners(listener) {
1027
+ return {
1028
+ ArrowFunctionExpression: listener,
1029
+ FunctionDeclaration: listener,
1030
+ FunctionExpression: listener,
1031
+ TSCallSignatureDeclaration: listener,
1032
+ TSConstructSignatureDeclaration: listener,
1033
+ TSConstructorType: listener,
1034
+ TSDeclareFunction: listener,
1035
+ TSEmptyBodyFunctionExpression: listener,
1036
+ TSFunctionType: listener,
1037
+ TSMethodSignature: listener
1038
+ };
1039
+ }
1040
+
1041
+ // src/vendor/dillon-anti-slop/shared/type-aliases.ts
1042
+ function typeAliasesCollect(program, includeGeneric) {
1043
+ const aliases = new Map;
1044
+ for (const statement of program.body) {
1045
+ const declaration = statement.type === "ExportNamedDeclaration" ? statement.declaration : statement;
1046
+ if (declaration?.type === "TSTypeAliasDeclaration" && (includeGeneric || !declaration.typeParameters)) {
1047
+ aliases.set(declaration.id.name, declaration);
1048
+ }
1049
+ }
1050
+ return aliases;
1051
+ }
1052
+ function typeAliasesResolvesTo(type, resolution, visited = new Set) {
1053
+ if (type.type === resolution.keyword) {
1054
+ return true;
1055
+ }
1056
+ if (type.type === "TSParenthesizedType") {
1057
+ return typeAliasesResolvesTo(type.typeAnnotation, resolution, visited);
1058
+ }
1059
+ if (resolution.unions && type.type === "TSUnionType") {
1060
+ return type.types.some((member) => typeAliasesResolvesTo(member, resolution, visited));
1061
+ }
1062
+ if (type.type !== "TSTypeReference" || type.typeName.type !== "Identifier") {
1063
+ return false;
1064
+ }
1065
+ const name = type.typeName.name;
1066
+ if (resolution.promises && (name === "Promise" || name === "PromiseLike")) {
1067
+ const value = type.typeArguments?.params[0];
1068
+ return value !== undefined && typeAliasesResolvesTo(value, resolution, visited);
1069
+ }
1070
+ if ((type.typeArguments?.params.length ?? 0) > 0 || visited.has(name) || resolution.shadowed.has(name)) {
1071
+ return false;
1072
+ }
1073
+ const alias = resolution.aliases.get(name);
1074
+ if (alias === undefined || alias.typeParameters) {
1075
+ return false;
1076
+ }
1077
+ const nextVisited = new Set(visited);
1078
+ nextVisited.add(name);
1079
+ return typeAliasesResolvesTo(alias.typeAnnotation, resolution, nextVisited);
1080
+ }
1081
+
1082
+ // src/vendor/dillon-anti-slop/rules/no-object-parameters.ts
1083
+ var noObjectParametersRule = defineRule6({
1084
+ meta: {
1085
+ type: "problem",
1086
+ docs: {
1087
+ description: "Disallow object function parameters; inputs must use an owner-provided type and be parsed at their boundary."
1088
+ },
1089
+ messages: {
1090
+ objectParameter: "Parameter `{{parameter}}` uses the broad `object` type. Accept a named owner type; parse external input at its boundary before calling this function."
1091
+ }
1092
+ },
1093
+ createOnce(context) {
1094
+ let aliases = new Map;
1095
+ return {
1096
+ Program(node) {
1097
+ aliases = typeAliasesCollect(node, false);
1098
+ },
1099
+ ...signaturesListeners((node) => {
1100
+ const shadowed = lexicalTypeParametersNames(node, context.sourceCode.visitorKeys);
1101
+ for (const parameter of node.params) {
1102
+ const annotation = signaturesParameterAnnotation(parameter);
1103
+ if (annotation === null || annotation === undefined || !typeAliasesResolvesTo(annotation.typeAnnotation, {
1104
+ aliases,
1105
+ keyword: "TSObjectKeyword",
1106
+ shadowed,
1107
+ unions: true,
1108
+ promises: false
1109
+ })) {
1110
+ continue;
1111
+ }
1112
+ context.report({
1113
+ node: annotation.typeAnnotation,
1114
+ messageId: "objectParameter",
1115
+ data: {
1116
+ parameter: parameter.type === "Identifier" ? parameter.name : context.sourceCode.getText(parameter).replace(/\s*:\s*object\s*$/u, "")
1117
+ }
1118
+ });
1119
+ }
1120
+ })
1121
+ };
1122
+ }
1123
+ });
1124
+
1125
+ // src/vendor/dillon-anti-slop/shared/reflect-method.ts
1126
+ import { defineRule as defineRule7 } from "@oxlint/plugins";
1127
+ function reflectMethodRule(methodName, messageId, description, message) {
1128
+ return defineRule7({
1129
+ meta: {
1130
+ type: "problem",
1131
+ docs: { description },
1132
+ messages: { [messageId]: message }
1133
+ },
1134
+ createOnce(context) {
1135
+ return {
1136
+ CallExpression(node) {
1137
+ const { callee } = node;
1138
+ if (callee.type === "Super" || callee.type === "V8IntrinsicExpression" || !("property" in callee) || !("object" in callee) || !("computed" in callee)) {
1139
+ return;
1140
+ }
1141
+ const { object, property } = callee;
1142
+ if (object.type !== "Identifier" || object.name !== "Reflect") {
1143
+ return;
1144
+ }
1145
+ if (!context.sourceCode.isGlobalReference(object)) {
1146
+ const variable = resolveVariable(context.sourceCode, object);
1147
+ if (variable !== null && variable.defs.length > 0) {
1148
+ return;
1149
+ }
1150
+ }
1151
+ if (callee.computed ? property.type === "Literal" && property.value === methodName : property.type === "Identifier" && property.name === methodName) {
1152
+ context.report({ node, messageId });
1153
+ }
1154
+ }
1155
+ };
1156
+ }
1157
+ });
1158
+ }
1159
+
1160
+ // src/vendor/dillon-anti-slop/rules/no-reflect-apply.ts
1161
+ var noReflectApplyRule = reflectMethodRule("apply", "reflectApply", "Disallow Reflect.apply; call typed functions directly or model dynamic dispatch behind an interface.", "Replace `Reflect.apply` with a typed function call. Model dynamic dispatch behind a named interface.");
1162
+
1163
+ // src/vendor/dillon-anti-slop/rules/no-reflect-get.ts
1164
+ var noReflectGetRule = reflectMethodRule("get", "reflectGet", "Disallow Reflect.get; use typed property access or parse dynamic input into a domain type.", "Replace `Reflect.get` with typed property access. Parse dynamic input into a named domain type before reading it.");
1165
+
1166
+ // src/vendor/dillon-anti-slop/rules/no-runtime-typeof.ts
1167
+ import { defineRule as defineRule8 } from "@oxlint/plugins";
1168
+ var noRuntimeTypeofRule = defineRule8({
1169
+ meta: {
1170
+ type: "problem",
1171
+ docs: {
1172
+ description: "Disallow runtime typeof checks; external values must be decoded into meaningful types at their I/O boundary."
1173
+ },
1174
+ messages: {
1175
+ runtimeTypeof: "A `typeof` check narrows a representation without establishing its contract. Parse input at its I/O boundary, then branch on the domain value."
1176
+ },
1177
+ schema: [
1178
+ {
1179
+ type: "object",
1180
+ properties: {
1181
+ allowInTypeGuards: { type: "boolean" }
1182
+ },
1183
+ additionalProperties: false
1184
+ }
1185
+ ],
1186
+ defaultOptions: [{ allowInTypeGuards: false }]
1187
+ },
1188
+ createOnce(context) {
1189
+ return {
1190
+ UnaryExpression(node) {
1191
+ if (node.operator !== "typeof") {
1192
+ return;
1193
+ }
1194
+ if (optionsFirst(context, {}).allowInTypeGuards === true) {
1195
+ let current = node.parent;
1196
+ while (current.type !== "Program") {
1197
+ if (current.type === "ArrowFunctionExpression" || current.type === "FunctionDeclaration" || current.type === "FunctionExpression") {
1198
+ if (current.returnType?.typeAnnotation.type === "TSTypePredicate") {
1199
+ return;
1200
+ }
1201
+ break;
1202
+ }
1203
+ current = current.parent;
1204
+ }
1205
+ }
1206
+ context.report({ node, messageId: "runtimeTypeof" });
1207
+ }
1208
+ };
1209
+ }
1210
+ });
1211
+
1212
+ // src/vendor/dillon-anti-slop/rules/no-shape-in-symbol-names.ts
1213
+ import { defineRule as defineRule9 } from "@oxlint/plugins";
1214
+ var FORBIDDEN_SYMBOL_NAME = "shape";
1215
+ function namesForeignApi(node) {
1216
+ const parent = node.parent;
1217
+ if (!parent) {
1218
+ return false;
1219
+ }
1220
+ if (parent.type === "MemberExpression") {
1221
+ return parent.property === node && !parent.computed;
1222
+ }
1223
+ if (parent.type === "TSQualifiedName") {
1224
+ return parent.right === node;
1225
+ }
1226
+ if (parent.type === "ImportSpecifier") {
1227
+ return parent.imported === node && parent.local !== node && "name" in node && parent.local.name !== node.name;
1228
+ }
1229
+ if (parent.type === "ExportSpecifier") {
1230
+ return parent.local === node && parent.exported !== node && parent.parent.type === "ExportNamedDeclaration" && parent.parent.source !== null;
1231
+ }
1232
+ if (parent.type === "JSXMemberExpression") {
1233
+ return parent.property === node;
1234
+ }
1235
+ if (parent.type === "JSXAttribute") {
1236
+ return parent.name === node;
1237
+ }
1238
+ return parent.type === "Property" && parent.key === node && !parent.computed && (parent.shorthand || parent.parent.type === "ObjectPattern");
1239
+ }
1240
+ var noForbiddenTermInSymbolNamesRule = defineRule9({
1241
+ meta: {
1242
+ type: "problem",
1243
+ docs: {
1244
+ description: 'Disallow the case-insensitive substring "shape" in JavaScript, TypeScript, private, and JSX symbol names.'
1245
+ },
1246
+ messages: {
1247
+ forbiddenSymbolName: 'Rename symbol "{{name}}" for its domain role; "shape" describes structure rather than ownership.'
1248
+ }
1249
+ },
1250
+ createOnce(context) {
1251
+ const reportForbiddenSymbolName = (node) => {
1252
+ if (!node.name.toLowerCase().includes(FORBIDDEN_SYMBOL_NAME) || namesForeignApi(node)) {
1253
+ return;
1254
+ }
1255
+ context.report({
1256
+ node,
1257
+ messageId: "forbiddenSymbolName",
1258
+ data: { name: node.name }
1259
+ });
1260
+ };
1261
+ return {
1262
+ Identifier: reportForbiddenSymbolName,
1263
+ PrivateIdentifier: reportForbiddenSymbolName,
1264
+ JSXIdentifier: reportForbiddenSymbolName
1265
+ };
1266
+ }
1267
+ });
1268
+
1269
+ // src/vendor/dillon-anti-slop/rules/no-unknown-parameters.ts
1270
+ import { defineRule as defineRule10 } from "@oxlint/plugins";
1271
+ function parameterName(parameter, sourceText) {
1272
+ if (parameter.type === "TSParameterProperty") {
1273
+ return parameterName(parameter.parameter, sourceText);
1274
+ }
1275
+ if (parameter.type === "AssignmentPattern") {
1276
+ return parameterName(parameter.left, sourceText);
1277
+ }
1278
+ if (parameter.type === "RestElement") {
1279
+ return parameterName(parameter.argument, sourceText);
1280
+ }
1281
+ return parameter.type === "Identifier" ? parameter.name : sourceText.replace(/\s*:\s*unknown\s*$/u, "");
1282
+ }
1283
+ var noUnknownParametersRule = defineRule10({
1284
+ meta: {
1285
+ type: "problem",
1286
+ docs: {
1287
+ description: "Disallow explicitly unknown function parameters except `error` and `cause`; decode unknown input at its I/O boundary instead."
1288
+ },
1289
+ messages: {
1290
+ unknownParameter: "Parameter `{{parameter}}` leaves input unparsed. Accept a named domain type; run the expected schema or parser at the I/O boundary before calling this function."
1291
+ }
1292
+ },
1293
+ createOnce(context) {
1294
+ return signaturesListeners((node) => {
1295
+ for (const parameter of node.params) {
1296
+ const annotation = signaturesParameterAnnotation(parameter);
1297
+ if (annotation?.typeAnnotation.type !== "TSUnknownKeyword") {
1298
+ continue;
1299
+ }
1300
+ const name = parameterName(parameter, context.sourceCode.getText(parameter));
1301
+ if (name === "cause" || name === "error") {
1302
+ continue;
1303
+ }
1304
+ context.report({
1305
+ node: annotation.typeAnnotation,
1306
+ messageId: "unknownParameter",
1307
+ data: { parameter: name }
1308
+ });
1309
+ }
1310
+ });
1311
+ }
1312
+ });
1313
+
1314
+ // src/vendor/dillon-anti-slop/rules/no-unknown-returns.ts
1315
+ import { defineRule as defineRule11 } from "@oxlint/plugins";
1316
+ var noUnknownReturnsRule = defineRule11({
1317
+ meta: {
1318
+ type: "problem",
1319
+ docs: {
1320
+ description: "Disallow functions whose explicit return contract is unknown or Promise<unknown>."
1321
+ },
1322
+ messages: {
1323
+ unknownReturn: "This function exposes `unknown` to its caller. Parse the value at its boundary and return a named domain type."
1324
+ }
1325
+ },
1326
+ createOnce(context) {
1327
+ let aliases = new Map;
1328
+ return {
1329
+ Program(node) {
1330
+ aliases = typeAliasesCollect(node, true);
1331
+ },
1332
+ ...signaturesListeners((node) => {
1333
+ const annotation = node.returnType;
1334
+ if (annotation === null || annotation === undefined || !typeAliasesResolvesTo(annotation.typeAnnotation, {
1335
+ aliases,
1336
+ keyword: "TSUnknownKeyword",
1337
+ shadowed: lexicalTypeParametersNames(node, context.sourceCode.visitorKeys),
1338
+ unions: true,
1339
+ promises: true
1340
+ })) {
1341
+ return;
1342
+ }
1343
+ context.report({ node: annotation.typeAnnotation, messageId: "unknownReturn" });
1344
+ })
1345
+ };
1346
+ }
1347
+ });
1348
+
1349
+ // src/vendor/dillon-anti-slop/rules/no-unknown-type-aliases.ts
1350
+ import { defineRule as defineRule12 } from "@oxlint/plugins";
1351
+ var noUnknownTypeAliasesRule = defineRule12({
1352
+ meta: {
1353
+ type: "problem",
1354
+ docs: {
1355
+ description: "Disallow type aliases whose resolved type is unknown; unknown must remain visible at an allowed boundary."
1356
+ },
1357
+ messages: {
1358
+ unknownAlias: "Type alias `{{alias}}` hides `unknown`. Keep `unknown` explicit at the parsing boundary or on an allowed `cause` field; otherwise use the parsed owner type."
1359
+ }
1360
+ },
1361
+ createOnce(context) {
1362
+ return {
1363
+ Program(node) {
1364
+ const aliases = typeAliasesCollect(node, true);
1365
+ const resolution = {
1366
+ aliases,
1367
+ keyword: "TSUnknownKeyword",
1368
+ shadowed: new Set,
1369
+ unions: false,
1370
+ promises: false
1371
+ };
1372
+ for (const alias of aliases.values()) {
1373
+ if (!typeAliasesResolvesTo(alias.typeAnnotation, resolution, new Set([alias.id.name]))) {
1374
+ continue;
1375
+ }
1376
+ context.report({
1377
+ node: alias.id,
1378
+ messageId: "unknownAlias",
1379
+ data: { alias: alias.id.name }
1380
+ });
1381
+ }
1382
+ }
1383
+ };
1384
+ }
1385
+ });
1386
+
1387
+ // src/vendor/dillon-anti-slop/rules/no-unsafe-dictionary-type.ts
1388
+ import { defineRule as defineRule13 } from "@oxlint/plugins";
1389
+ var typeNodeKinds = new Set([
1390
+ "JSDocNonNullableType",
1391
+ "JSDocNullableType",
1392
+ "JSDocUnknownType",
1393
+ "TSAnyKeyword",
1394
+ "TSArrayType",
1395
+ "TSBigIntKeyword",
1396
+ "TSBooleanKeyword",
1397
+ "TSConditionalType",
1398
+ "TSConstructorType",
1399
+ "TSFunctionType",
1400
+ "TSImportType",
1401
+ "TSIndexedAccessType",
1402
+ "TSInferType",
1403
+ "TSIntersectionType",
1404
+ "TSIntrinsicKeyword",
1405
+ "TSLiteralType",
1406
+ "TSMappedType",
1407
+ "TSNamedTupleMember",
1408
+ "TSNeverKeyword",
1409
+ "TSNullKeyword",
1410
+ "TSNumberKeyword",
1411
+ "TSObjectKeyword",
1412
+ "TSParenthesizedType",
1413
+ "TSStringKeyword",
1414
+ "TSSymbolKeyword",
1415
+ "TSTemplateLiteralType",
1416
+ "TSThisType",
1417
+ "TSTupleType",
1418
+ "TSTypeLiteral",
1419
+ "TSTypeOperator",
1420
+ "TSTypePredicate",
1421
+ "TSTypeQuery",
1422
+ "TSTypeReference",
1423
+ "TSUndefinedKeyword",
1424
+ "TSUnionType",
1425
+ "TSUnknownKeyword",
1426
+ "TSVoidKeyword"
1427
+ ]);
1428
+ function isTypeNode(node) {
1429
+ return typeNodeKinds.has(node.type);
1430
+ }
1431
+ var noUnsafeDictionaryTypeRule = defineRule13({
1432
+ meta: {
1433
+ type: "problem",
1434
+ docs: {
1435
+ description: "Disallow object-dictionary contracts whose direct value type is unknown, any, object, {}, or a union/alias containing one of those escape hatches."
1436
+ },
1437
+ messages: {
1438
+ unsafeDictionary: "This dictionary's {{value}} value type gives callers no concrete value contract. Use an owner/schema-derived value type; parse external payloads before insertion."
1439
+ }
1440
+ },
1441
+ createOnce(context) {
1442
+ let environment = null;
1443
+ const report = (node, value) => {
1444
+ context.report({
1445
+ node,
1446
+ messageId: "unsafeDictionary",
1447
+ data: { value }
1448
+ });
1449
+ };
1450
+ const reportIfUnsafe = (node) => {
1451
+ if (environment === null) {
1452
+ return;
1453
+ }
1454
+ if (node.type === "TSTypeReference" && (node.typeArguments?.params.length ?? 0) === 0) {
1455
+ const name = typeReferenceName(node);
1456
+ if (name !== null && environment.aliases.has(name)) {
1457
+ let owner = node.parent;
1458
+ while (owner.type !== "Program" && owner.type !== "TSTypeAliasDeclaration") {
1459
+ owner = owner.parent;
1460
+ }
1461
+ if (owner.type !== "TSTypeAliasDeclaration") {
1462
+ return;
1463
+ }
1464
+ }
1465
+ }
1466
+ const unsafe = dictionaryTypesClassify(node, environment);
1467
+ if (unsafe === null) {
1468
+ return;
1469
+ }
1470
+ let current = node.parent;
1471
+ while (current.type !== "Program") {
1472
+ if (isTypeNode(current) && dictionaryTypesClassify(current, environment) !== null) {
1473
+ return;
1474
+ }
1475
+ current = current.parent;
1476
+ }
1477
+ report(node, unsafe);
1478
+ };
1479
+ return {
1480
+ Program(node) {
1481
+ environment = typeEnvironmentCreate(node);
1482
+ },
1483
+ TSTypeReference: reportIfUnsafe,
1484
+ TSTypeLiteral: reportIfUnsafe,
1485
+ TSMappedType: reportIfUnsafe,
1486
+ TSIndexSignature(node) {
1487
+ if (environment === null || node.parent.type === "TSTypeLiteral") {
1488
+ return;
1489
+ }
1490
+ const unsafe = dictionaryTypesUnsafeValue(node.typeAnnotation.typeAnnotation, environment, new Map, new Set);
1491
+ if (unsafe !== null) {
1492
+ report(node, unsafe);
1493
+ }
1494
+ }
1495
+ };
1496
+ }
1497
+ });
1498
+
1499
+ // src/vendor/dillon-anti-slop/rules/no-widen-then-assert.ts
1500
+ import { defineRule as defineRule14 } from "@oxlint/plugins";
1501
+ var functionBoundaryTypes = new Set([
1502
+ "ArrowFunctionExpression",
1503
+ "FunctionDeclaration",
1504
+ "FunctionExpression",
1505
+ "TSDeclareFunction",
1506
+ "TSEmptyBodyFunctionExpression"
1507
+ ]);
1508
+ var definitelyObjectTypes = new Set([
1509
+ "TSArrayType",
1510
+ "TSConstructorType",
1511
+ "TSFunctionType",
1512
+ "TSMappedType",
1513
+ "TSObjectKeyword",
1514
+ "TSTupleType"
1515
+ ]);
1516
+ function unwrapTypeParentheses(type) {
1517
+ let current = type;
1518
+ while (current.type === "TSParenthesizedType") {
1519
+ current = current.typeAnnotation;
1520
+ }
1521
+ return current;
1522
+ }
1523
+ function isUnknownOrAnyType(type) {
1524
+ const unwrapped = unwrapTypeParentheses(type);
1525
+ return unwrapped.type === "TSUnknownKeyword" || unwrapped.type === "TSAnyKeyword";
1526
+ }
1527
+ function isBroadRecordKeyType(type) {
1528
+ const unwrapped = unwrapTypeParentheses(type);
1529
+ if (unwrapped.type === "TSStringKeyword" || unwrapped.type === "TSNumberKeyword" || unwrapped.type === "TSSymbolKeyword") {
1530
+ return true;
1531
+ }
1532
+ if (unwrapped.type === "TSUnionType") {
1533
+ return unwrapped.types.every(isBroadRecordKeyType);
1534
+ }
1535
+ return unwrapped.type === "TSTypeReference" && typeReferenceName(unwrapped) === "PropertyKey";
1536
+ }
1537
+ function isBroadRecordType(type) {
1538
+ const unwrapped = unwrapTypeParentheses(type);
1539
+ if (unwrapped.type === "TSTypeReference") {
1540
+ if (typeReferenceName(unwrapped) === "Readonly") {
1541
+ const inner = unwrapped.typeArguments?.params.at(0);
1542
+ return inner !== undefined && isBroadRecordType(inner);
1543
+ }
1544
+ if (typeReferenceName(unwrapped) !== "Record") {
1545
+ return false;
1546
+ }
1547
+ const parameters = unwrapped.typeArguments?.params ?? [];
1548
+ return parameters.length === 2 && isBroadRecordKeyType(parameters[0]) && isUnknownOrAnyType(parameters[1]);
1549
+ }
1550
+ if (unwrapped.type !== "TSTypeLiteral" || unwrapped.members.length !== 1) {
1551
+ return false;
1552
+ }
1553
+ const [member] = unwrapped.members;
1554
+ return member.type === "TSIndexSignature" && member.parameters.length === 1 && isBroadRecordKeyType(member.parameters[0].typeAnnotation.typeAnnotation) && isUnknownOrAnyType(member.typeAnnotation.typeAnnotation);
1555
+ }
1556
+ function broadTypeKind(type) {
1557
+ const unwrapped = unwrapTypeParentheses(type);
1558
+ if (unwrapped.type === "TSUnknownKeyword" || unwrapped.type === "TSAnyKeyword") {
1559
+ return "top";
1560
+ }
1561
+ if (unwrapped.type === "TSObjectKeyword") {
1562
+ return "object";
1563
+ }
1564
+ return isBroadRecordType(unwrapped) ? "record" : null;
1565
+ }
1566
+ function normalizedTypeText(sourceText, type) {
1567
+ const unwrapped = unwrapTypeParentheses(type);
1568
+ return sourceText.slice(unwrapped.start, unwrapped.end).replaceAll(/\s+/gu, "");
1569
+ }
1570
+ function isDefinitelyObjectType(type) {
1571
+ const unwrapped = unwrapTypeParentheses(type);
1572
+ if (definitelyObjectTypes.has(unwrapped.type)) {
1573
+ return true;
1574
+ }
1575
+ if (unwrapped.type === "TSTypeLiteral") {
1576
+ return unwrapped.members.length > 0;
1577
+ }
1578
+ if (unwrapped.type === "TSIntersectionType") {
1579
+ return unwrapped.types.every(isDefinitelyObjectType);
1580
+ }
1581
+ return unwrapped.type === "TSTypeOperator" && unwrapped.operator === "readonly" && isDefinitelyObjectType(unwrapped.typeAnnotation);
1582
+ }
1583
+ function isDefinitelyNarrowerRecordType(type) {
1584
+ const unwrapped = unwrapTypeParentheses(type);
1585
+ if (unwrapped.type === "TSTypeLiteral") {
1586
+ return unwrapped.members.some((member) => member.type !== "TSIndexSignature");
1587
+ }
1588
+ if (unwrapped.type !== "TSTypeReference") {
1589
+ return false;
1590
+ }
1591
+ if (typeReferenceName(unwrapped) === "Readonly") {
1592
+ const inner = unwrapped.typeArguments?.params.at(0);
1593
+ return inner !== undefined && isDefinitelyNarrowerRecordType(inner);
1594
+ }
1595
+ if (typeReferenceName(unwrapped) !== "Record") {
1596
+ return false;
1597
+ }
1598
+ const parameters = unwrapped.typeArguments?.params ?? [];
1599
+ return parameters.length === 2 && !isUnknownOrAnyType(parameters[1]);
1600
+ }
1601
+ function functionBoundary(node) {
1602
+ let current = node.parent;
1603
+ while (current !== null && current.type !== "Program") {
1604
+ if (functionBoundaryTypes.has(current.type)) {
1605
+ return current;
1606
+ }
1607
+ current = current.parent;
1608
+ }
1609
+ return null;
1610
+ }
1611
+ function stableConstBinding(variable) {
1612
+ for (const definition of variable.defs) {
1613
+ if (definition.type === "Variable" && definition.node.type === "VariableDeclarator") {
1614
+ const declarator = definition.node;
1615
+ const { init } = declarator;
1616
+ return init !== null && declarator.parent.type === "VariableDeclaration" && declarator.parent.kind === "const" && !variable.references.some((reference) => reference.isWrite() && !reference.init) ? { declarator, init } : null;
1617
+ }
1618
+ }
1619
+ return null;
1620
+ }
1621
+ function knownValueEvidence(expression, sourceCode, boundary, visitedVariables) {
1622
+ const unwrapped = expressionsUnwrapParentheses(expression);
1623
+ if (expressionsIsAssertion(unwrapped)) {
1624
+ return broadTypeKind(unwrapped.typeAnnotation) === null ? { type: unwrapped.typeAnnotation } : null;
1625
+ }
1626
+ if (unwrapped.type === "Literal" || unwrapped.type === "TemplateLiteral" || unwrapped.type === "ArrayExpression" || unwrapped.type === "ArrowFunctionExpression" || unwrapped.type === "ClassExpression" || unwrapped.type === "FunctionExpression" || unwrapped.type === "NewExpression" || unwrapped.type === "ObjectExpression") {
1627
+ return { type: null };
1628
+ }
1629
+ if (unwrapped.type !== "Identifier") {
1630
+ return null;
1631
+ }
1632
+ const variable = resolveVariable(sourceCode, unwrapped);
1633
+ if (variable === null || visitedVariables.has(variable)) {
1634
+ return null;
1635
+ }
1636
+ const annotatedIdentifier = variable.identifiers.find((identifier) => identifier.typeAnnotation !== null && identifier.typeAnnotation !== undefined);
1637
+ const annotation = annotatedIdentifier?.typeAnnotation?.typeAnnotation;
1638
+ if (annotation !== undefined && annotatedIdentifier !== undefined) {
1639
+ return functionBoundary(annotatedIdentifier) !== boundary || broadTypeKind(annotation) !== null ? null : { type: annotation };
1640
+ }
1641
+ const binding = stableConstBinding(variable);
1642
+ if (binding === null || functionBoundary(binding.declarator) !== boundary) {
1643
+ return null;
1644
+ }
1645
+ return knownValueEvidence(binding.init, sourceCode, boundary, new Set([...visitedVariables, variable]));
1646
+ }
1647
+ var noWidenThenAssertRule = defineRule14({
1648
+ meta: {
1649
+ type: "problem",
1650
+ docs: {
1651
+ description: "Disallow local const flows that explicitly widen a known value before asserting the widened binding to a narrower type."
1652
+ },
1653
+ messages: {
1654
+ widenThenAssert: 'Binding "{{name}}" discards type evidence and later recreates it with an assertion. Keep the precise type from initialization through use; parse boundary input once.'
1655
+ }
1656
+ },
1657
+ createOnce(context) {
1658
+ const checkAssertion = (node) => {
1659
+ const expression = expressionsUnwrapParentheses(node.expression);
1660
+ if (expression.type !== "Identifier") {
1661
+ return;
1662
+ }
1663
+ const variable = resolveVariable(context.sourceCode, expression);
1664
+ const binding = variable === null ? null : stableConstBinding(variable);
1665
+ if (variable === null || binding?.declarator.id.type !== "Identifier") {
1666
+ return;
1667
+ }
1668
+ const { declarator, init } = binding;
1669
+ const boundary = functionBoundary(declarator);
1670
+ const declaredType = declarator.id.typeAnnotation?.typeAnnotation;
1671
+ const initializer = expressionsUnwrapParentheses(init);
1672
+ const initializerAssertion = expressionsIsAssertion(initializer) ? initializer : null;
1673
+ const initializerBroadKind = initializerAssertion === null ? null : broadTypeKind(initializerAssertion.typeAnnotation);
1674
+ const broadKind = (declaredType === undefined ? null : broadTypeKind(declaredType)) ?? initializerBroadKind;
1675
+ if (broadKind === null) {
1676
+ return;
1677
+ }
1678
+ const originalExpression = initializerAssertion !== null && initializerBroadKind !== null ? expressionsUnwrapParentheses(initializerAssertion.expression) : init;
1679
+ const evidence = knownValueEvidence(originalExpression, context.sourceCode, boundary, new Set([variable]));
1680
+ if (evidence === null || node.start <= declarator.end || functionBoundary(node) !== boundary) {
1681
+ return;
1682
+ }
1683
+ const assertedType = node.typeAnnotation;
1684
+ const sourceText = context.sourceCode.text;
1685
+ const narrower = broadTypeKind(assertedType) === null && (broadKind === "top" || evidence.type !== null && normalizedTypeText(sourceText, evidence.type) === normalizedTypeText(sourceText, assertedType) || (broadKind === "object" ? isDefinitelyObjectType(assertedType) : isDefinitelyNarrowerRecordType(assertedType)));
1686
+ if (!narrower) {
1687
+ return;
1688
+ }
1689
+ context.report({
1690
+ node,
1691
+ messageId: "widenThenAssert",
1692
+ data: { name: expression.name }
1693
+ });
1694
+ };
1695
+ return {
1696
+ TSAsExpression: checkAssertion,
1697
+ TSTypeAssertion: checkAssertion
1698
+ };
1699
+ }
1700
+ });
1701
+
1702
+ // src/vendor/dillon-anti-slop/rules/require-safety-comment-for-type-assertion.ts
1703
+ import { defineRule as defineRule15 } from "@oxlint/plugins";
1704
+ var commentOwnerKinds = new Set([
1705
+ "ExpressionStatement",
1706
+ "PropertyDefinition",
1707
+ "ReturnStatement",
1708
+ "ThrowStatement",
1709
+ "VariableDeclaration"
1710
+ ]);
1711
+ var requireSafetyCommentForTypeAssertionRule = defineRule15({
1712
+ meta: {
1713
+ type: "problem",
1714
+ docs: {
1715
+ description: "Require a nearby SAFETY comment for every TypeScript type assertion except const assertions."
1716
+ },
1717
+ messages: {
1718
+ missingSafetyComment: "This type assertion has no `SAFETY:` justification. State the checked invariant immediately before the assertion or its containing statement."
1719
+ }
1720
+ },
1721
+ createOnce(context) {
1722
+ const checkAssertion = (node) => {
1723
+ if (expressionsIsConstAssertion(node)) {
1724
+ return;
1725
+ }
1726
+ let current = node;
1727
+ for (;; ) {
1728
+ if (context.sourceCode.getCommentsBefore(current).some((comment) => comment.end <= node.start && /\bSAFETY\s*:/u.test(comment.value))) {
1729
+ return;
1730
+ }
1731
+ const parent = current.parent;
1732
+ if (commentOwnerKinds.has(current.type) && parent.type !== "ExportNamedDeclaration" && parent.type !== "ExportDefaultDeclaration" || parent.type === "Program") {
1733
+ break;
1734
+ }
1735
+ current = parent;
1736
+ }
1737
+ context.report({ node, messageId: "missingSafetyComment" });
1738
+ };
1739
+ return {
1740
+ TSAsExpression: checkAssertion,
1741
+ TSTypeAssertion: checkAssertion
1742
+ };
1743
+ }
1744
+ });
1745
+
1746
+ // src/vendor/dillon-anti-slop/index.ts
1747
+ var dillonAntiSlopPlugin = eslintCompatPlugin({
1748
+ meta: { name: "dillon-anti-slop" },
1749
+ rules: {
1750
+ "no-chained-type-assertions": noChainedTypeAssertionsRule,
1751
+ "no-conditional-empty-object-spread": noConditionalEmptyObjectSpreadRule,
1752
+ "no-known-value-widening": noKnownValueWideningRule,
1753
+ "no-module-mocking": noModuleMockingRule,
1754
+ "no-object-parameters": noObjectParametersRule,
1755
+ "no-reflect-apply": noReflectApplyRule,
1756
+ "no-reflect-get": noReflectGetRule,
1757
+ "no-runtime-typeof": noRuntimeTypeofRule,
1758
+ "no-unsafe-dictionary-type": noUnsafeDictionaryTypeRule,
1759
+ "no-shape-in-symbol-names": noForbiddenTermInSymbolNamesRule,
1760
+ "no-unknown-parameters": noUnknownParametersRule,
1761
+ "no-unknown-returns": noUnknownReturnsRule,
1762
+ "no-unknown-type-aliases": noUnknownTypeAliasesRule,
1763
+ "no-widen-then-assert": noWidenThenAssertRule,
1764
+ "require-safety-comment-for-type-assertion": requireSafetyCommentForTypeAssertionRule
1765
+ }
1766
+ });
1767
+ var dillon_anti_slop_default = dillonAntiSlopPlugin;
1768
+ export {
1769
+ dillon_anti_slop_default as default
1770
+ };