@nielspeter/eess-ts 0.2.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (467) hide show
  1. package/README.md +61 -35
  2. package/dist/builders/call-rule-builder.d.ts +66 -26
  3. package/dist/builders/call-rule-builder.d.ts.map +1 -1
  4. package/dist/builders/call-rule-builder.js +75 -32
  5. package/dist/builders/call-rule-builder.js.map +1 -1
  6. package/dist/builders/class-rule-builder.d.ts +125 -26
  7. package/dist/builders/class-rule-builder.d.ts.map +1 -1
  8. package/dist/builders/class-rule-builder.js +141 -55
  9. package/dist/builders/class-rule-builder.js.map +1 -1
  10. package/dist/builders/correspondence-builder.d.ts +287 -0
  11. package/dist/builders/correspondence-builder.d.ts.map +1 -0
  12. package/dist/builders/correspondence-builder.js +385 -0
  13. package/dist/builders/correspondence-builder.js.map +1 -0
  14. package/dist/builders/correspondence-findings.d.ts +104 -0
  15. package/dist/builders/correspondence-findings.d.ts.map +1 -0
  16. package/dist/builders/correspondence-findings.js +301 -0
  17. package/dist/builders/correspondence-findings.js.map +1 -0
  18. package/dist/builders/cross-layer-builder.d.ts +99 -16
  19. package/dist/builders/cross-layer-builder.d.ts.map +1 -1
  20. package/dist/builders/cross-layer-builder.js +182 -35
  21. package/dist/builders/cross-layer-builder.js.map +1 -1
  22. package/dist/builders/function-rule-builder.d.ts +144 -25
  23. package/dist/builders/function-rule-builder.d.ts.map +1 -1
  24. package/dist/builders/function-rule-builder.js +177 -39
  25. package/dist/builders/function-rule-builder.js.map +1 -1
  26. package/dist/builders/jsx-rule-builder.d.ts +70 -14
  27. package/dist/builders/jsx-rule-builder.d.ts.map +1 -1
  28. package/dist/builders/jsx-rule-builder.js +73 -14
  29. package/dist/builders/jsx-rule-builder.js.map +1 -1
  30. package/dist/builders/module-rule-builder.d.ts +2 -2
  31. package/dist/builders/module-rule-builder.d.ts.map +1 -1
  32. package/dist/builders/module-rule-builder.js +16 -19
  33. package/dist/builders/module-rule-builder.js.map +1 -1
  34. package/dist/builders/scoped-function-rule-builder.d.ts +11 -0
  35. package/dist/builders/scoped-function-rule-builder.d.ts.map +1 -1
  36. package/dist/builders/scoped-function-rule-builder.js +12 -0
  37. package/dist/builders/scoped-function-rule-builder.js.map +1 -1
  38. package/dist/builders/slice-discovery-message.d.ts +36 -0
  39. package/dist/builders/slice-discovery-message.d.ts.map +1 -0
  40. package/dist/builders/slice-discovery-message.js +181 -0
  41. package/dist/builders/slice-discovery-message.js.map +1 -0
  42. package/dist/builders/slice-rule-builder.d.ts +151 -12
  43. package/dist/builders/slice-rule-builder.d.ts.map +1 -1
  44. package/dist/builders/slice-rule-builder.js +243 -35
  45. package/dist/builders/slice-rule-builder.js.map +1 -1
  46. package/dist/builders/type-rule-builder.d.ts +95 -24
  47. package/dist/builders/type-rule-builder.d.ts.map +1 -1
  48. package/dist/builders/type-rule-builder.js +109 -42
  49. package/dist/builders/type-rule-builder.js.map +1 -1
  50. package/dist/{helpers → builders}/within.d.ts +2 -2
  51. package/dist/builders/within.d.ts.map +1 -0
  52. package/dist/{helpers → builders}/within.js +1 -1
  53. package/dist/builders/within.js.map +1 -0
  54. package/dist/cli/commands/baseline.d.ts +8 -3
  55. package/dist/cli/commands/baseline.d.ts.map +1 -1
  56. package/dist/cli/commands/baseline.js +111 -7
  57. package/dist/cli/commands/baseline.js.map +1 -1
  58. package/dist/cli/commands/check.d.ts +7 -2
  59. package/dist/cli/commands/check.d.ts.map +1 -1
  60. package/dist/cli/commands/check.js +385 -47
  61. package/dist/cli/commands/check.js.map +1 -1
  62. package/dist/cli/commands/doctor.d.ts +29 -0
  63. package/dist/cli/commands/doctor.d.ts.map +1 -0
  64. package/dist/cli/commands/doctor.js +224 -0
  65. package/dist/cli/commands/doctor.js.map +1 -0
  66. package/dist/cli/commands/explain.d.ts +2 -1
  67. package/dist/cli/commands/explain.d.ts.map +1 -1
  68. package/dist/cli/commands/explain.js +19 -10
  69. package/dist/cli/commands/explain.js.map +1 -1
  70. package/dist/cli/commands/init.d.ts +9 -3
  71. package/dist/cli/commands/init.d.ts.map +1 -1
  72. package/dist/cli/commands/init.js +162 -137
  73. package/dist/cli/commands/init.js.map +1 -1
  74. package/dist/cli/import-rule-module.d.ts +29 -0
  75. package/dist/cli/import-rule-module.d.ts.map +1 -0
  76. package/dist/cli/import-rule-module.js +47 -0
  77. package/dist/cli/import-rule-module.js.map +1 -0
  78. package/dist/cli/index.d.ts +2 -2
  79. package/dist/cli/index.d.ts.map +1 -1
  80. package/dist/cli/index.js +101 -43
  81. package/dist/cli/index.js.map +1 -1
  82. package/dist/cli/load-rules.d.ts +6 -11
  83. package/dist/cli/load-rules.d.ts.map +1 -1
  84. package/dist/cli/load-rules.js +25 -32
  85. package/dist/cli/load-rules.js.map +1 -1
  86. package/dist/cli/resolve-config.d.ts +0 -8
  87. package/dist/cli/resolve-config.d.ts.map +1 -1
  88. package/dist/cli/resolve-config.js +25 -55
  89. package/dist/cli/resolve-config.js.map +1 -1
  90. package/dist/cli/rule-file-findings.d.ts +178 -0
  91. package/dist/cli/rule-file-findings.d.ts.map +1 -0
  92. package/dist/cli/rule-file-findings.js +351 -0
  93. package/dist/cli/rule-file-findings.js.map +1 -0
  94. package/dist/cli/watch.d.ts +17 -34
  95. package/dist/cli/watch.d.ts.map +1 -1
  96. package/dist/cli/watch.js +14 -129
  97. package/dist/cli/watch.js.map +1 -1
  98. package/dist/conditions/body-analysis-function.d.ts.map +1 -1
  99. package/dist/conditions/body-analysis-function.js +16 -7
  100. package/dist/conditions/body-analysis-function.js.map +1 -1
  101. package/dist/conditions/body-analysis-module.d.ts.map +1 -1
  102. package/dist/conditions/body-analysis-module.js +14 -9
  103. package/dist/conditions/body-analysis-module.js.map +1 -1
  104. package/dist/conditions/body-analysis.d.ts.map +1 -1
  105. package/dist/conditions/body-analysis.js +16 -7
  106. package/dist/conditions/body-analysis.js.map +1 -1
  107. package/dist/conditions/call.d.ts.map +1 -1
  108. package/dist/conditions/call.js +41 -19
  109. package/dist/conditions/call.js.map +1 -1
  110. package/dist/conditions/catch-analysis.d.ts +2 -1
  111. package/dist/conditions/catch-analysis.d.ts.map +1 -1
  112. package/dist/conditions/catch-analysis.js.map +1 -1
  113. package/dist/conditions/cross-layer.d.ts +2 -10
  114. package/dist/conditions/cross-layer.d.ts.map +1 -1
  115. package/dist/conditions/cross-layer.js +227 -23
  116. package/dist/conditions/cross-layer.js.map +1 -1
  117. package/dist/conditions/dependency.d.ts +35 -6
  118. package/dist/conditions/dependency.d.ts.map +1 -1
  119. package/dist/conditions/dependency.js +299 -45
  120. package/dist/conditions/dependency.js.map +1 -1
  121. package/dist/conditions/exports.d.ts.map +1 -1
  122. package/dist/conditions/exports.js +41 -37
  123. package/dist/conditions/exports.js.map +1 -1
  124. package/dist/conditions/function.d.ts.map +1 -1
  125. package/dist/conditions/function.js +19 -5
  126. package/dist/conditions/function.js.map +1 -1
  127. package/dist/conditions/helpers.d.ts +2 -1
  128. package/dist/conditions/helpers.d.ts.map +1 -1
  129. package/dist/conditions/helpers.js +4 -1
  130. package/dist/conditions/helpers.js.map +1 -1
  131. package/dist/conditions/jsx.d.ts.map +1 -1
  132. package/dist/conditions/jsx.js +7 -2
  133. package/dist/conditions/jsx.js.map +1 -1
  134. package/dist/conditions/match-identity.d.ts +43 -0
  135. package/dist/conditions/match-identity.d.ts.map +1 -0
  136. package/dist/conditions/match-identity.js +43 -0
  137. package/dist/conditions/match-identity.js.map +1 -0
  138. package/dist/conditions/members.d.ts.map +1 -1
  139. package/dist/conditions/members.js +20 -6
  140. package/dist/conditions/members.js.map +1 -1
  141. package/dist/conditions/reverse-dependency.d.ts +18 -5
  142. package/dist/conditions/reverse-dependency.d.ts.map +1 -1
  143. package/dist/conditions/reverse-dependency.js +155 -93
  144. package/dist/conditions/reverse-dependency.js.map +1 -1
  145. package/dist/conditions/slice.d.ts +86 -2
  146. package/dist/conditions/slice.d.ts.map +1 -1
  147. package/dist/conditions/slice.js +234 -53
  148. package/dist/conditions/slice.js.map +1 -1
  149. package/dist/conditions/structural.d.ts.map +1 -1
  150. package/dist/conditions/structural.js +16 -4
  151. package/dist/conditions/structural.js.map +1 -1
  152. package/dist/core/check-all.d.ts +19 -0
  153. package/dist/core/check-all.d.ts.map +1 -0
  154. package/dist/core/check-all.js +150 -0
  155. package/dist/core/check-all.js.map +1 -0
  156. package/dist/core/combinators.d.ts +48 -0
  157. package/dist/core/combinators.d.ts.map +1 -0
  158. package/dist/core/combinators.js +49 -0
  159. package/dist/core/combinators.js.map +1 -0
  160. package/dist/core/descendant-cache.d.ts +36 -0
  161. package/dist/core/descendant-cache.d.ts.map +1 -0
  162. package/dist/core/descendant-cache.js +117 -0
  163. package/dist/core/descendant-cache.js.map +1 -0
  164. package/dist/core/diagnose.d.ts +234 -0
  165. package/dist/core/diagnose.d.ts.map +1 -0
  166. package/dist/core/diagnose.js +390 -0
  167. package/dist/core/diagnose.js.map +1 -0
  168. package/dist/core/disk-set.d.ts +48 -0
  169. package/dist/core/disk-set.d.ts.map +1 -0
  170. package/dist/core/disk-set.js +218 -0
  171. package/dist/core/disk-set.js.map +1 -0
  172. package/dist/core/element-cache.d.ts +75 -0
  173. package/dist/core/element-cache.d.ts.map +1 -0
  174. package/dist/core/element-cache.js +32 -0
  175. package/dist/core/element-cache.js.map +1 -0
  176. package/dist/core/empty-project-advice.d.ts +75 -0
  177. package/dist/core/empty-project-advice.d.ts.map +1 -0
  178. package/dist/core/empty-project-advice.js +61 -0
  179. package/dist/core/empty-project-advice.js.map +1 -0
  180. package/dist/core/exclusion-comments.d.ts +19 -0
  181. package/dist/core/exclusion-comments.d.ts.map +1 -0
  182. package/dist/core/exclusion-comments.js +7 -0
  183. package/dist/core/exclusion-comments.js.map +1 -0
  184. package/dist/core/execute-rule.d.ts +158 -0
  185. package/dist/core/execute-rule.d.ts.map +1 -0
  186. package/dist/core/execute-rule.js +666 -0
  187. package/dist/core/execute-rule.js.map +1 -0
  188. package/dist/core/glob-diagnosis.d.ts +78 -0
  189. package/dist/core/glob-diagnosis.d.ts.map +1 -0
  190. package/dist/core/glob-diagnosis.js +134 -0
  191. package/dist/core/glob-diagnosis.js.map +1 -0
  192. package/dist/core/glob-evaluator.d.ts +48 -0
  193. package/dist/core/glob-evaluator.d.ts.map +1 -0
  194. package/dist/core/glob-evaluator.js +89 -0
  195. package/dist/core/glob-evaluator.js.map +1 -0
  196. package/dist/core/import-candidates.d.ts +60 -0
  197. package/dist/core/import-candidates.d.ts.map +1 -0
  198. package/dist/core/import-candidates.js +93 -0
  199. package/dist/core/import-candidates.js.map +1 -0
  200. package/dist/core/import-options.d.ts +55 -2
  201. package/dist/core/import-options.d.ts.map +1 -1
  202. package/dist/core/import-options.js +64 -0
  203. package/dist/core/import-options.js.map +1 -1
  204. package/dist/core/invalidate-on-modify.d.ts +20 -0
  205. package/dist/core/invalidate-on-modify.d.ts.map +1 -0
  206. package/dist/core/invalidate-on-modify.js +26 -0
  207. package/dist/core/invalidate-on-modify.js.map +1 -0
  208. package/dist/core/line-index.d.ts +3 -0
  209. package/dist/core/line-index.d.ts.map +1 -0
  210. package/dist/core/line-index.js +227 -0
  211. package/dist/core/line-index.js.map +1 -0
  212. package/dist/core/metric-violation.d.ts +86 -0
  213. package/dist/core/metric-violation.d.ts.map +1 -0
  214. package/dist/core/metric-violation.js +132 -0
  215. package/dist/core/metric-violation.js.map +1 -0
  216. package/dist/core/module-edges.d.ts +361 -0
  217. package/dist/core/module-edges.d.ts.map +1 -0
  218. package/dist/core/module-edges.js +593 -0
  219. package/dist/core/module-edges.js.map +1 -0
  220. package/dist/core/object-literal-functions.d.ts +42 -0
  221. package/dist/core/object-literal-functions.d.ts.map +1 -0
  222. package/dist/core/object-literal-functions.js +75 -0
  223. package/dist/core/object-literal-functions.js.map +1 -0
  224. package/dist/core/orphan-exclusions.d.ts +44 -0
  225. package/dist/core/orphan-exclusions.d.ts.map +1 -0
  226. package/dist/core/orphan-exclusions.js +224 -0
  227. package/dist/core/orphan-exclusions.js.map +1 -0
  228. package/dist/core/pair-condition.d.ts +32 -3
  229. package/dist/core/pair-condition.d.ts.map +1 -1
  230. package/dist/core/path-universe.d.ts +22 -0
  231. package/dist/core/path-universe.d.ts.map +1 -0
  232. package/dist/core/path-universe.js +45 -0
  233. package/dist/core/path-universe.js.map +1 -0
  234. package/dist/core/per-root-compiler-options.d.ts +20 -0
  235. package/dist/core/per-root-compiler-options.d.ts.map +1 -0
  236. package/dist/core/per-root-compiler-options.js +57 -0
  237. package/dist/core/per-root-compiler-options.js.map +1 -0
  238. package/dist/core/project-relative.d.ts +98 -0
  239. package/dist/core/project-relative.d.ts.map +1 -0
  240. package/dist/core/project-relative.js +185 -0
  241. package/dist/core/project-relative.js.map +1 -0
  242. package/dist/core/project.d.ts +7 -1
  243. package/dist/core/project.d.ts.map +1 -1
  244. package/dist/core/project.js +29 -4
  245. package/dist/core/project.js.map +1 -1
  246. package/dist/core/rule-builder.d.ts +303 -0
  247. package/dist/core/rule-builder.d.ts.map +1 -0
  248. package/dist/core/rule-builder.js +463 -0
  249. package/dist/core/rule-builder.js.map +1 -0
  250. package/dist/core/rule-declaration.d.ts +32 -0
  251. package/dist/core/rule-declaration.d.ts.map +1 -0
  252. package/dist/core/rule-declaration.js +88 -0
  253. package/dist/core/rule-declaration.js.map +1 -0
  254. package/dist/core/terminal-builder.d.ts +629 -0
  255. package/dist/core/terminal-builder.d.ts.map +1 -0
  256. package/dist/core/terminal-builder.js +807 -0
  257. package/dist/core/terminal-builder.js.map +1 -0
  258. package/dist/core/terminal-execution.d.ts +39 -0
  259. package/dist/core/terminal-execution.d.ts.map +1 -0
  260. package/dist/core/terminal-execution.js +103 -0
  261. package/dist/core/terminal-execution.js.map +1 -0
  262. package/dist/core/ts-comment-mask.d.ts +2 -0
  263. package/dist/core/ts-comment-mask.d.ts.map +1 -0
  264. package/dist/core/ts-comment-mask.js +102 -0
  265. package/dist/core/ts-comment-mask.js.map +1 -0
  266. package/dist/core/vacuity-diagnosis.d.ts +103 -0
  267. package/dist/core/vacuity-diagnosis.d.ts.map +1 -0
  268. package/dist/core/vacuity-diagnosis.js +415 -0
  269. package/dist/core/vacuity-diagnosis.js.map +1 -0
  270. package/dist/core/violation.d.ts +16 -11
  271. package/dist/core/violation.d.ts.map +1 -1
  272. package/dist/core/violation.js +33 -13
  273. package/dist/core/violation.js.map +1 -1
  274. package/dist/graphql/graphql-rule-builder.d.ts +95 -0
  275. package/dist/graphql/graphql-rule-builder.d.ts.map +1 -0
  276. package/dist/graphql/graphql-rule-builder.js +127 -0
  277. package/dist/graphql/graphql-rule-builder.js.map +1 -0
  278. package/dist/graphql/index.d.ts +1 -0
  279. package/dist/graphql/index.d.ts.map +1 -1
  280. package/dist/graphql/index.js +2 -1
  281. package/dist/graphql/index.js.map +1 -1
  282. package/dist/graphql/resolver-rule-builder.d.ts +44 -23
  283. package/dist/graphql/resolver-rule-builder.d.ts.map +1 -1
  284. package/dist/graphql/resolver-rule-builder.js +80 -72
  285. package/dist/graphql/resolver-rule-builder.js.map +1 -1
  286. package/dist/graphql/schema-loader.d.ts +21 -0
  287. package/dist/graphql/schema-loader.d.ts.map +1 -1
  288. package/dist/graphql/schema-loader.js +82 -12
  289. package/dist/graphql/schema-loader.js.map +1 -1
  290. package/dist/graphql/schema-predicates.d.ts.map +1 -1
  291. package/dist/graphql/schema-predicates.js +17 -12
  292. package/dist/graphql/schema-predicates.js.map +1 -1
  293. package/dist/graphql/schema-rule-builder.d.ts +15 -24
  294. package/dist/graphql/schema-rule-builder.d.ts.map +1 -1
  295. package/dist/graphql/schema-rule-builder.js +39 -77
  296. package/dist/graphql/schema-rule-builder.js.map +1 -1
  297. package/dist/helpers/baseline-diagnostics.d.ts +45 -0
  298. package/dist/helpers/baseline-diagnostics.d.ts.map +1 -0
  299. package/dist/helpers/baseline-diagnostics.js +168 -0
  300. package/dist/helpers/baseline-diagnostics.js.map +1 -0
  301. package/dist/helpers/baseline-generator.d.ts +28 -0
  302. package/dist/helpers/baseline-generator.d.ts.map +1 -0
  303. package/dist/helpers/baseline-generator.js +27 -0
  304. package/dist/helpers/baseline-generator.js.map +1 -0
  305. package/dist/helpers/baseline.d.ts +336 -0
  306. package/dist/helpers/baseline.d.ts.map +1 -0
  307. package/dist/helpers/baseline.js +664 -0
  308. package/dist/helpers/baseline.js.map +1 -0
  309. package/dist/helpers/body-traversal.d.ts +27 -2
  310. package/dist/helpers/body-traversal.d.ts.map +1 -1
  311. package/dist/helpers/body-traversal.js +135 -16
  312. package/dist/helpers/body-traversal.js.map +1 -1
  313. package/dist/helpers/callback-extractor.d.ts.map +1 -1
  314. package/dist/helpers/callback-extractor.js +53 -84
  315. package/dist/helpers/callback-extractor.js.map +1 -1
  316. package/dist/helpers/complexity.d.ts +13 -5
  317. package/dist/helpers/complexity.d.ts.map +1 -1
  318. package/dist/helpers/complexity.js +15 -6
  319. package/dist/helpers/complexity.js.map +1 -1
  320. package/dist/helpers/diff-aware.d.ts +16 -0
  321. package/dist/helpers/diff-aware.d.ts.map +1 -0
  322. package/dist/helpers/diff-aware.js +16 -0
  323. package/dist/helpers/diff-aware.js.map +1 -0
  324. package/dist/helpers/matchers.d.ts +68 -7
  325. package/dist/helpers/matchers.d.ts.map +1 -1
  326. package/dist/helpers/matchers.js +164 -86
  327. package/dist/helpers/matchers.js.map +1 -1
  328. package/dist/helpers/slice-graph.d.ts +100 -8
  329. package/dist/helpers/slice-graph.d.ts.map +1 -1
  330. package/dist/helpers/slice-graph.js +126 -34
  331. package/dist/helpers/slice-graph.js.map +1 -1
  332. package/dist/helpers/tarjan.d.ts +0 -14
  333. package/dist/helpers/tarjan.d.ts.map +1 -1
  334. package/dist/helpers/tarjan.js +29 -16
  335. package/dist/helpers/tarjan.js.map +1 -1
  336. package/dist/index.d.ts +55 -19
  337. package/dist/index.d.ts.map +1 -1
  338. package/dist/index.js +67 -15
  339. package/dist/index.js.map +1 -1
  340. package/dist/models/arch-call.d.ts +3 -2
  341. package/dist/models/arch-call.d.ts.map +1 -1
  342. package/dist/models/arch-call.js.map +1 -1
  343. package/dist/models/arch-function.d.ts +54 -8
  344. package/dist/models/arch-function.d.ts.map +1 -1
  345. package/dist/models/arch-function.js +145 -8
  346. package/dist/models/arch-function.js.map +1 -1
  347. package/dist/models/arch-jsx-element.d.ts.map +1 -1
  348. package/dist/models/arch-jsx-element.js +18 -19
  349. package/dist/models/arch-jsx-element.js.map +1 -1
  350. package/dist/models/slice.d.ts +33 -9
  351. package/dist/models/slice.d.ts.map +1 -1
  352. package/dist/models/slice.js +129 -19
  353. package/dist/models/slice.js.map +1 -1
  354. package/dist/predicates/call.d.ts.map +1 -1
  355. package/dist/predicates/call.js +5 -0
  356. package/dist/predicates/call.js.map +1 -1
  357. package/dist/predicates/identity.d.ts +21 -0
  358. package/dist/predicates/identity.d.ts.map +1 -1
  359. package/dist/predicates/identity.js +75 -3
  360. package/dist/predicates/identity.js.map +1 -1
  361. package/dist/predicates/index.d.ts +1 -1
  362. package/dist/predicates/index.d.ts.map +1 -1
  363. package/dist/predicates/index.js +1 -1
  364. package/dist/predicates/index.js.map +1 -1
  365. package/dist/predicates/jsx.d.ts.map +1 -1
  366. package/dist/predicates/jsx.js +2 -1
  367. package/dist/predicates/jsx.js.map +1 -1
  368. package/dist/predicates/metrics.d.ts +4 -2
  369. package/dist/predicates/metrics.d.ts.map +1 -1
  370. package/dist/predicates/metrics.js +4 -2
  371. package/dist/predicates/metrics.js.map +1 -1
  372. package/dist/predicates/module.d.ts +4 -12
  373. package/dist/predicates/module.d.ts.map +1 -1
  374. package/dist/predicates/module.js +57 -37
  375. package/dist/predicates/module.js.map +1 -1
  376. package/dist/presets/agent-guardrails.d.ts +49 -16
  377. package/dist/presets/agent-guardrails.d.ts.map +1 -1
  378. package/dist/presets/agent-guardrails.js +308 -19
  379. package/dist/presets/agent-guardrails.js.map +1 -1
  380. package/dist/presets/boundaries.d.ts +46 -3
  381. package/dist/presets/boundaries.d.ts.map +1 -1
  382. package/dist/presets/boundaries.js +132 -23
  383. package/dist/presets/boundaries.js.map +1 -1
  384. package/dist/presets/data-layer.d.ts +23 -3
  385. package/dist/presets/data-layer.d.ts.map +1 -1
  386. package/dist/presets/data-layer.js +58 -16
  387. package/dist/presets/data-layer.js.map +1 -1
  388. package/dist/presets/index.d.ts +10 -5
  389. package/dist/presets/index.d.ts.map +1 -1
  390. package/dist/presets/index.js +19 -3
  391. package/dist/presets/index.js.map +1 -1
  392. package/dist/presets/layered.d.ts +47 -3
  393. package/dist/presets/layered.d.ts.map +1 -1
  394. package/dist/presets/layered.js +66 -29
  395. package/dist/presets/layered.js.map +1 -1
  396. package/dist/presets/recommended.d.ts +81 -10
  397. package/dist/presets/recommended.d.ts.map +1 -1
  398. package/dist/presets/recommended.js +25 -23
  399. package/dist/presets/recommended.js.map +1 -1
  400. package/dist/presets/shared.d.ts +267 -2
  401. package/dist/presets/shared.d.ts.map +1 -1
  402. package/dist/presets/shared.js +367 -4
  403. package/dist/presets/shared.js.map +1 -1
  404. package/dist/rules/code-quality.d.ts.map +1 -1
  405. package/dist/rules/code-quality.js +15 -6
  406. package/dist/rules/code-quality.js.map +1 -1
  407. package/dist/rules/hygiene.d.ts +1 -1
  408. package/dist/rules/hygiene.js +1 -1
  409. package/dist/rules/metrics-function.d.ts +2 -1
  410. package/dist/rules/metrics-function.d.ts.map +1 -1
  411. package/dist/rules/metrics-function.js +63 -39
  412. package/dist/rules/metrics-function.js.map +1 -1
  413. package/dist/rules/metrics.d.ts +2 -1
  414. package/dist/rules/metrics.d.ts.map +1 -1
  415. package/dist/rules/metrics.js +80 -47
  416. package/dist/rules/metrics.js.map +1 -1
  417. package/dist/smells/clusters.d.ts +78 -0
  418. package/dist/smells/clusters.d.ts.map +1 -0
  419. package/dist/smells/clusters.js +124 -0
  420. package/dist/smells/clusters.js.map +1 -0
  421. package/dist/smells/duplicate-bodies.d.ts +92 -5
  422. package/dist/smells/duplicate-bodies.d.ts.map +1 -1
  423. package/dist/smells/duplicate-bodies.js +203 -73
  424. package/dist/smells/duplicate-bodies.js.map +1 -1
  425. package/dist/smells/duplicate-report.d.ts +90 -0
  426. package/dist/smells/duplicate-report.d.ts.map +1 -0
  427. package/dist/smells/duplicate-report.js +344 -0
  428. package/dist/smells/duplicate-report.js.map +1 -0
  429. package/dist/smells/fingerprint.d.ts +20 -1
  430. package/dist/smells/fingerprint.d.ts.map +1 -1
  431. package/dist/smells/fingerprint.js +27 -3
  432. package/dist/smells/fingerprint.js.map +1 -1
  433. package/dist/smells/inconsistent-siblings.d.ts +128 -7
  434. package/dist/smells/inconsistent-siblings.d.ts.map +1 -1
  435. package/dist/smells/inconsistent-siblings.js +288 -86
  436. package/dist/smells/inconsistent-siblings.js.map +1 -1
  437. package/dist/smells/sibling-files.d.ts +47 -0
  438. package/dist/smells/sibling-files.d.ts.map +1 -0
  439. package/dist/smells/sibling-files.js +104 -0
  440. package/dist/smells/sibling-files.js.map +1 -0
  441. package/dist/smells/similar-pairs.d.ts +28 -0
  442. package/dist/smells/similar-pairs.d.ts.map +1 -0
  443. package/dist/smells/similar-pairs.js +134 -0
  444. package/dist/smells/similar-pairs.js.map +1 -0
  445. package/dist/smells/smell-builder.d.ts +57 -12
  446. package/dist/smells/smell-builder.d.ts.map +1 -1
  447. package/dist/smells/smell-builder.js +112 -14
  448. package/dist/smells/smell-builder.js.map +1 -1
  449. package/dist/smells/variation.d.ts +47 -0
  450. package/dist/smells/variation.d.ts.map +1 -0
  451. package/dist/smells/variation.js +90 -0
  452. package/dist/smells/variation.js.map +1 -0
  453. package/dist/tsconfig/index.d.ts +19 -0
  454. package/dist/tsconfig/index.d.ts.map +1 -0
  455. package/dist/tsconfig/index.js +20 -0
  456. package/dist/tsconfig/index.js.map +1 -0
  457. package/dist/tsconfig/tsconfig-builder.d.ts +42 -9
  458. package/dist/tsconfig/tsconfig-builder.d.ts.map +1 -1
  459. package/dist/tsconfig/tsconfig-builder.js +65 -16
  460. package/dist/tsconfig/tsconfig-builder.js.map +1 -1
  461. package/package.json +4 -2
  462. package/dist/core/module-dependencies.d.ts +0 -28
  463. package/dist/core/module-dependencies.d.ts.map +0 -1
  464. package/dist/core/module-dependencies.js +0 -35
  465. package/dist/core/module-dependencies.js.map +0 -1
  466. package/dist/helpers/within.d.ts.map +0 -1
  467. package/dist/helpers/within.js.map +0 -1
@@ -0,0 +1,124 @@
1
+ import { ArchConfigError } from '@nielspeter/eess';
2
+ /**
3
+ * Group reported pairs into connected components.
4
+ *
5
+ * A pair is the wrong unit of report and it is not a close call. Measured on a
6
+ * ~5,600-file production monorepo: 407 clusters produced **4,770** pair
7
+ * findings, the eight largest clusters alone produced 49% of them, one cluster
8
+ * of 89 members produced 398, and the worst single function was named 29 times.
9
+ *
10
+ * Every one of those findings can be true and the output is still unreadable,
11
+ * because N mutually-similar bodies carry ONE observation and emit N^2/2 lines
12
+ * of it. The observation is "these 89 share a shape", which is also the unit a
13
+ * reader can act on. That is what this returns.
14
+ */
15
+ export function clusterPairs(pairs) {
16
+ const parent = new Map();
17
+ const find = (x) => {
18
+ let root = parent.get(x) ?? x;
19
+ if (root === x) {
20
+ parent.set(x, x);
21
+ return x;
22
+ }
23
+ root = find(root);
24
+ parent.set(x, root);
25
+ return root;
26
+ };
27
+ const union = (a, b) => {
28
+ const ra = find(a);
29
+ const rb = find(b);
30
+ if (ra !== rb)
31
+ parent.set(ra, rb);
32
+ };
33
+ for (const pair of pairs)
34
+ union(pair.a, pair.b);
35
+ // First-seen order throughout, so the report is stable across runs. Map
36
+ // iteration order is insertion order, and `pairs` arrives in the order the
37
+ // comparison found them, which is the source-file walk order.
38
+ const byRoot = new Map();
39
+ const seen = new Set();
40
+ for (const pair of pairs) {
41
+ const root = find(pair.a);
42
+ let entry = byRoot.get(root);
43
+ if (!entry) {
44
+ entry = { members: [], pairs: [] };
45
+ byRoot.set(root, entry);
46
+ }
47
+ entry.pairs.push(pair);
48
+ for (const fn of [pair.a, pair.b]) {
49
+ if (seen.has(fn))
50
+ continue;
51
+ seen.add(fn);
52
+ entry.members.push(fn);
53
+ }
54
+ }
55
+ // Narrowed here, at the one place clusters are constructed, rather than at
56
+ // every place they are read. An entry exists only because a pair created it,
57
+ // and both of that pair's ends are pushed, so `members` always holds at least
58
+ // two — but the compiler cannot see that through `push`. A cluster that
59
+ // somehow held fewer is a broken invariant in THIS function, and dropping it
60
+ // silently at emission is what the type change exists to prevent, so it is
61
+ // reported as a configuration finding rather than filtered away.
62
+ return [...byRoot.values()].map((entry) => {
63
+ const [first, second, ...rest] = entry.members;
64
+ if (!first || !second) {
65
+ throw new ArchConfigError('duplicateBodies', 'a similarity cluster was built with fewer than two members, which cannot happen: ' +
66
+ 'every cluster is created from a pair and both of its ends are recorded. ' +
67
+ 'This is a defect in clusterPairs, not in the code being analysed.');
68
+ }
69
+ // Annotated, never cast (ADR-005): the annotation makes the compiler CHECK
70
+ // the literal is a valid `NonEmptyMembers`, where a cast would only assert
71
+ // it.
72
+ const members = [first, second, ...rest];
73
+ return {
74
+ members,
75
+ pairs: entry.pairs,
76
+ peakSimilarity: entry.pairs.reduce((best, p) => Math.max(best, p.similarity), 0),
77
+ };
78
+ });
79
+ }
80
+ /**
81
+ * How likely a cluster is to be worth acting on, highest first.
82
+ *
83
+ * Not a filter and deliberately not a score change — the similarity number is
84
+ * left exactly as it was. This decides only what a reader sees first, because at
85
+ * 4,770 findings the order IS the product.
86
+ *
87
+ * The signal is the one the fingerprint throws away: a body's identifiers are
88
+ * ignored by design (that is what makes the score a type-2 clone score), and so
89
+ * is the DECLARATION's own name, which is where the evidence was. Measured over
90
+ * that same corpus, bucketed by how the two names relate:
91
+ *
92
+ * | bucket | share | reading |
93
+ * | ----------------------------- | ----- | -------------------------- |
94
+ * | different file, different name | 56% | convergent idiom |
95
+ * | same class | 20% | siblings, often extractable |
96
+ * | different file, SAME name | 14% | a COPY of one function |
97
+ * | same file, different class | 10% | co-located |
98
+ *
99
+ * Two pairs from that run, both scored 100%: `timestampPrefix` in two files (a
100
+ * literal copy) and two unrelated SDK wrapper methods (a shared idiom). Same
101
+ * number on screen, opposite verdicts, and the thing that separates them costs
102
+ * nothing to compute.
103
+ *
104
+ * **It is a ranking and not a filter on purpose.** Dropping the different-name
105
+ * bucket would discard real same-class duplication — one repository in that
106
+ * corpus has six `exists*` methods differing only in a table name. Dropping
107
+ * cross-file would have discarded the finding that led to bug 0227.
108
+ */
109
+ export function clusterRank(cluster) {
110
+ const bare = (fn) => (fn.getName() ?? '<anonymous>').split('.').pop() ?? '';
111
+ const file = (fn) => fn.getSourceFile().getFilePath();
112
+ let best = 0;
113
+ for (const pair of cluster.pairs) {
114
+ const sameFile = file(pair.a) === file(pair.b);
115
+ const sameName = bare(pair.a) === bare(pair.b);
116
+ // A copy of one function into another file is the most actionable thing
117
+ // this detector can find, and the cheapest to verify.
118
+ const score = !sameFile && sameName ? 3 : sameFile ? 2 : 1;
119
+ if (score > best)
120
+ best = score;
121
+ }
122
+ return best;
123
+ }
124
+ //# sourceMappingURL=clusters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clusters.js","sourceRoot":"","sources":["../../src/smells/clusters.ts"],"names":[],"mappings":"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"}
@@ -1,24 +1,111 @@
1
+ import type { RuleDescription } from '@nielspeter/eess';
1
2
  import { SmellBuilder } from './smell-builder.js';
2
- import type { ArchViolation } from '../core/violation.js';
3
+ import type { ArchViolation } from '@nielspeter/eess';
3
4
  import type { ArchProject } from '../core/project.js';
4
5
  export declare class DuplicateBodiesBuilder extends SmellBuilder {
5
6
  private _minSimilarity;
7
+ private _minDistinctVocabulary;
6
8
  constructor(project: ArchProject);
7
9
  /** Set the AST similarity threshold. Default: 0.85. */
8
10
  withMinSimilarity(threshold: number): this;
11
+ /**
12
+ * Minimum count of distinct identifier/literal text either body must carry
13
+ * before a pair is even compared — not raw line count, and not similarity.
14
+ * Two bodies can share a syntactic shape for no reason other than the shape
15
+ * being mandated (a wither, a getter, a boilerplate skeleton); below this
16
+ * threshold a "match" carries no information about what the code actually
17
+ * does. Default: 8 — see plan 0103's Phase 0 triage for how it was chosen.
18
+ * Tune down for a codebase with terser naming than this default assumes;
19
+ * tune up if short, low-vocabulary bodies keep surfacing as noise.
20
+ */
21
+ minDistinctVocabulary(n: number): this;
22
+ /**
23
+ * Named by id or by what the detector checks — the inherited version returns
24
+ * the sentinel `'unnamed'`, and `inconsistent-siblings.ts` already carries this
25
+ * override for that reason.
26
+ *
27
+ * It became load-bearing in plan 0099: the floor makes an over-filtered
28
+ * detector FAIL, and `dedupeConfigFindings` keys on `(file, ruleId ?? rule,
29
+ * element)`. With `file: ''` and `'unnamed'` in both other slots, three
30
+ * genuinely different detectors — different similarity, different
31
+ * `ignorePaths` — collapsed into one finding claiming they were "one option"
32
+ * and "one edit". Two were silently discarded and the survivor said
33
+ * `Rule: unnamed`.
34
+ */
35
+ describeRule(): RuleDescription;
9
36
  protected detect(): ArchViolation[];
10
37
  protected describe(): string;
11
38
  /** Check if a file path passes all glob-based filters. */
39
+ /**
40
+ * The three matcher sets travel together as one `filters` — they are one
41
+ * configuration, and four positional `picomatch.Matcher[]` arguments in a row
42
+ * are exactly the transposition risk the parameter cap exists to prevent.
43
+ */
12
44
  private passesFileFilters;
13
45
  /** Check if a function body meets the minimum line count. */
14
46
  private meetsMinLines;
15
47
  /** Collect all functions matching folder/path/test filters. */
48
+ /**
49
+ * Bodies entering pairwise comparison — plan 0096, and the ONE method both
50
+ * readers call.
51
+ *
52
+ * The seam is AFTER `minLines` and the path filters: a project can load 300
53
+ * files while every body sits under the threshold, and the count that notices
54
+ * has to be taken where the comparison receives its input, not where the files
55
+ * were read.
56
+ *
57
+ * No fingerprinting to count. `meetsMinLines` already returns false for a
58
+ * bodyless function, so `fingerprintAll(xs).length === xs.length` **always** —
59
+ * fingerprinting to answer "is it zero" is a full AST pass of dead work on
60
+ * what becomes the hot path of every consumer's `diagnose()` call.
61
+ */
62
+ private selected;
63
+ /** Units this detector examined — plan 0096. */
64
+ examinedUnits(): number;
16
65
  private collectFilteredFunctions;
17
- /** Build fingerprints for all collected functions. */
18
- private fingerprintAll;
19
- /** Compare all pairs of fingerprints, collect those above threshold. */
20
- private findSimilarPairs;
21
66
  /** Build violations from similar pairs. */
67
+ /**
68
+ * Report order for pairs — which, measured, never has anything to order.
69
+ *
70
+ * Extracted from {@link buildViolations} so that method is the violation shape
71
+ * and nothing else. Enforcement review of bug 0242 read this as a live defect
72
+ * (keyed on `a`, i.e. walk order, while the finding reports at the anchor).
73
+ * Probing it says otherwise: {@link buildViolations} is reached only from
74
+ * {@link buildClusterViolations} for a cluster of two or fewer members, and
75
+ * such a cluster carries exactly one pair. Instrumented to throw on more than
76
+ * one, the whole `packages/ts` suite (3604 tests) produced **zero** hits.
77
+ *
78
+ * So this cannot reorder anything today, and {@link orderedClusters} is what
79
+ * actually orders the output. The key is corrected anyway — being right if
80
+ * this ever becomes reachable costs one expression — but the correction fixes
81
+ * no observable behaviour, and saying otherwise would be the kind of unmeasured
82
+ * claim this repo keeps catching.
83
+ */
84
+ private orderedPairs;
85
+ /**
86
+ * One violation per CLUSTER of mutually-similar bodies, not per pair.
87
+ *
88
+ * A pair is the wrong unit and it is not a close call. Measured on a
89
+ * ~5,600-file production monorepo: 407 clusters emitted **4,770** pair
90
+ * findings — more findings than the 3,810 bodies that produced them. The
91
+ * eight largest clusters were 49% of the output, one cluster of 89 members
92
+ * emitted 398 lines, and the worst single function was named 29 times. Every
93
+ * one of those can be TRUE and the report is still unreadable, because N
94
+ * mutually-similar bodies carry one observation and emit N^2/2 lines of it.
95
+ *
96
+ * Two-member clusters — the common case — keep the exact message and identity
97
+ * they had before, so existing baselines for them are untouched. Only a group
98
+ * of three or more collapses, which is where the inflation lives.
99
+ */
100
+ /**
101
+ * Report order.
102
+ *
103
+ * Rank is presentation only — no pair is dropped and no score changes. At four
104
+ * thousand findings the ORDER is the product: what a reader sees first decides
105
+ * whether they read at all. `.groupByFolder()` still wins when asked for.
106
+ */
107
+ private orderedClusters;
108
+ private buildClusterViolations;
22
109
  private buildViolations;
23
110
  }
24
111
  //# sourceMappingURL=duplicate-bodies.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"duplicate-bodies.d.ts","sourceRoot":"","sources":["../../src/smells/duplicate-bodies.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAIjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAYrD,qBAAa,sBAAuB,SAAQ,YAAY;IACtD,OAAO,CAAC,cAAc,CAAO;gBAEjB,OAAO,EAAE,WAAW;IAIhC,uDAAuD;IACvD,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAK1C,SAAS,CAAC,MAAM,IAAI,aAAa,EAAE;IAOnC,SAAS,CAAC,QAAQ,IAAI,MAAM;IAK5B,0DAA0D;IAC1D,OAAO,CAAC,iBAAiB;IAYzB,6DAA6D;IAC7D,OAAO,CAAC,aAAa;IAOrB,+DAA+D;IAC/D,OAAO,CAAC,wBAAwB;IAuBhC,sDAAsD;IACtD,OAAO,CAAC,cAAc;IAUtB,wEAAwE;IACxE,OAAO,CAAC,gBAAgB;IA0BxB,2CAA2C;IAC3C,OAAO,CAAC,eAAe;CAsCxB"}
1
+ {"version":3,"file":"duplicate-bodies.d.ts","sourceRoot":"","sources":["../../src/smells/duplicate-bodies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAIvD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAOjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AASrD,qBAAa,sBAAuB,SAAQ,YAAY;IACtD,OAAO,CAAC,cAAc,CAAO;IAC7B,OAAO,CAAC,sBAAsB,CAAI;gBAEtB,OAAO,EAAE,WAAW;IAIhC,uDAAuD;IACvD,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAM1C;;;;;;;;;OASG;IACH,qBAAqB,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAMtC;;;;;;;;;;;;OAYG;IACM,YAAY,IAAI,eAAe;IAOxC,SAAS,CAAC,MAAM,IAAI,aAAa,EAAE;IAOnC,SAAS,CAAC,QAAQ,IAAI,MAAM;IAqB5B,0DAA0D;IAC1D;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAoBzB,6DAA6D;IAC7D,OAAO,CAAC,aAAa;IAOrB,+DAA+D;IAC/D;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,QAAQ;IAIhB,gDAAgD;IAChD,aAAa,IAAI,MAAM;IAIvB,OAAO,CAAC,wBAAwB;IAmChC,2CAA2C;IAC3C;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,YAAY;IAepB;;;;;;;;;;;;;;OAcG;IACH;;;;;;OAMG;IACH,OAAO,CAAC,eAAe;IA8BvB,OAAO,CAAC,sBAAsB;IAe9B,OAAO,CAAC,eAAe;CAIxB"}
@@ -1,37 +1,103 @@
1
1
  import picomatch from 'picomatch';
2
2
  import path from 'node:path';
3
+ import { selectionMemo } from '@nielspeter/eess/internal';
3
4
  import { SmellBuilder } from './smell-builder.js';
4
5
  import { collectFunctions } from '../models/arch-function.js';
5
- import { buildFingerprint, computeSimilarity } from './fingerprint.js';
6
+ import { fingerprintAll, findSimilarPairs } from './similar-pairs.js';
7
+ import { anchorFile, clusterViolation, pairViolation } from './duplicate-report.js';
8
+ import { clusterPairs, clusterRank } from './clusters.js';
9
+ import { relativeToRoot } from '../core/project-relative.js';
6
10
  /** Test file patterns for ignoreTests(). */
7
11
  const TEST_PATTERNS = ['**/*.test.ts', '**/*.spec.ts', '**/__tests__/**'];
12
+ const selectionOf = selectionMemo();
8
13
  export class DuplicateBodiesBuilder extends SmellBuilder {
9
14
  _minSimilarity = 0.85;
15
+ _minDistinctVocabulary = 8;
10
16
  constructor(project) {
11
17
  super(project);
12
18
  }
13
19
  /** Set the AST similarity threshold. Default: 0.85. */
14
20
  withMinSimilarity(threshold) {
15
- this._minSimilarity = threshold;
16
- return this;
21
+ const next = this.copy();
22
+ next._minSimilarity = threshold;
23
+ return next;
24
+ }
25
+ /**
26
+ * Minimum count of distinct identifier/literal text either body must carry
27
+ * before a pair is even compared — not raw line count, and not similarity.
28
+ * Two bodies can share a syntactic shape for no reason other than the shape
29
+ * being mandated (a wither, a getter, a boilerplate skeleton); below this
30
+ * threshold a "match" carries no information about what the code actually
31
+ * does. Default: 8 — see plan 0103's Phase 0 triage for how it was chosen.
32
+ * Tune down for a codebase with terser naming than this default assumes;
33
+ * tune up if short, low-vocabulary bodies keep surfacing as noise.
34
+ */
35
+ minDistinctVocabulary(n) {
36
+ const next = this.copy();
37
+ next._minDistinctVocabulary = n;
38
+ return next;
39
+ }
40
+ /**
41
+ * Named by id or by what the detector checks — the inherited version returns
42
+ * the sentinel `'unnamed'`, and `inconsistent-siblings.ts` already carries this
43
+ * override for that reason.
44
+ *
45
+ * It became load-bearing in plan 0099: the floor makes an over-filtered
46
+ * detector FAIL, and `dedupeConfigFindings` keys on `(file, ruleId ?? rule,
47
+ * element)`. With `file: ''` and `'unnamed'` in both other slots, three
48
+ * genuinely different detectors — different similarity, different
49
+ * `ignorePaths` — collapsed into one finding claiming they were "one option"
50
+ * and "one edit". Two were silently discarded and the survivor said
51
+ * `Rule: unnamed`.
52
+ */
53
+ describeRule() {
54
+ return {
55
+ ...super.describeRule(),
56
+ rule: this._metadata?.id ?? this.describe(),
57
+ };
17
58
  }
18
59
  detect() {
19
- const functions = this.collectFilteredFunctions();
20
- const fingerprinted = this.fingerprintAll(functions);
21
- const pairs = this.findSimilarPairs(fingerprinted);
22
- return this.buildViolations(pairs);
60
+ const functions = this.selected();
61
+ const fingerprinted = fingerprintAll(functions);
62
+ const pairs = findSimilarPairs(fingerprinted, this._minSimilarity, this._minDistinctVocabulary);
63
+ return this.buildClusterViolations(pairs);
23
64
  }
24
65
  describe() {
25
66
  const scope = this._folders.length > 0 ? this._folders.join(', ') : 'all files';
26
- return `No duplicate function bodies in ${scope} (similarity >= ${String(this._minSimilarity)})`;
67
+ // EVERY narrowing that distinguishes two instances, not just similarity.
68
+ //
69
+ // This is the `Rule:` line a reader sees, and since plan 0099 it is also the
70
+ // dedupe identity for a detector with no `.rule({ id })`. Rendering only
71
+ // folders and similarity meant three detectors differing in `minLines` shared
72
+ // one key: measured, 3 findings collapsed to 1 claiming they were "one edit",
73
+ // and fixing the surviving threshold left the other two dead and green.
74
+ const filters = [
75
+ `minLines >= ${String(this._minLines)}`,
76
+ `minDistinctVocabulary >= ${String(this._minDistinctVocabulary)}`,
77
+ ];
78
+ if (this._ignorePaths.length > 0)
79
+ filters.push(`ignoring ${this._ignorePaths.join(', ')}`);
80
+ if (this._ignoreTests)
81
+ filters.push('ignoring tests');
82
+ return (`No duplicate function bodies in ${scope} ` +
83
+ `(similarity >= ${String(this._minSimilarity)}, ${filters.join(', ')})`);
27
84
  }
28
85
  /** Check if a file path passes all glob-based filters. */
29
- passesFileFilters(filePath, folderMatchers, ignoreMatchers, testMatchers) {
30
- if (folderMatchers.length > 0 && !folderMatchers.some((m) => m(filePath)))
86
+ /**
87
+ * The three matcher sets travel together as one `filters` — they are one
88
+ * configuration, and four positional `picomatch.Matcher[]` arguments in a row
89
+ * are exactly the transposition risk the parameter cap exists to prevent.
90
+ */
91
+ passesFileFilters(filePath, filters, fromRoot) {
92
+ const { folderMatchers, ignoreMatchers, testMatchers } = filters;
93
+ // Both forms, for every set — bug 0036. A project-relative `inFolder()` or
94
+ // `ignorePaths()` glob could never match an absolute path.
95
+ const hits = (ms) => ms.some((m) => m(filePath)) || (fromRoot !== undefined && ms.some((m) => m(fromRoot)));
96
+ if (folderMatchers.length > 0 && !hits(folderMatchers))
31
97
  return false;
32
- if (ignoreMatchers.some((m) => m(filePath)))
98
+ if (hits(ignoreMatchers))
33
99
  return false;
34
- if (testMatchers.some((m) => m(filePath)))
100
+ if (hits(testMatchers))
35
101
  return false;
36
102
  return true;
37
103
  }
@@ -44,6 +110,27 @@ export class DuplicateBodiesBuilder extends SmellBuilder {
44
110
  return lineCount >= this._minLines;
45
111
  }
46
112
  /** Collect all functions matching folder/path/test filters. */
113
+ /**
114
+ * Bodies entering pairwise comparison — plan 0096, and the ONE method both
115
+ * readers call.
116
+ *
117
+ * The seam is AFTER `minLines` and the path filters: a project can load 300
118
+ * files while every body sits under the threshold, and the count that notices
119
+ * has to be taken where the comparison receives its input, not where the files
120
+ * were read.
121
+ *
122
+ * No fingerprinting to count. `meetsMinLines` already returns false for a
123
+ * bodyless function, so `fingerprintAll(xs).length === xs.length` **always** —
124
+ * fingerprinting to answer "is it zero" is a full AST pass of dead work on
125
+ * what becomes the hot path of every consumer's `diagnose()` call.
126
+ */
127
+ selected() {
128
+ return selectionOf(this, () => this.collectFilteredFunctions());
129
+ }
130
+ /** Units this detector examined — plan 0096. */
131
+ examinedUnits() {
132
+ return this.selected().length;
133
+ }
47
134
  collectFilteredFunctions() {
48
135
  const sourceFiles = this.project.getSourceFiles();
49
136
  const folderMatchers = this._folders.map((g) => picomatch(g));
@@ -51,10 +138,16 @@ export class DuplicateBodiesBuilder extends SmellBuilder {
51
138
  const testMatchers = this._ignoreTests ? TEST_PATTERNS.map((g) => picomatch(g)) : [];
52
139
  const allFunctions = [];
53
140
  for (const sf of sourceFiles) {
54
- if (!this.passesFileFilters(sf.getFilePath(), folderMatchers, ignoreMatchers, testMatchers)) {
141
+ if (!this.passesFileFilters(sf.getFilePath(), { folderMatchers, ignoreMatchers, testMatchers }, relativeToRoot(sf, sf.getFilePath(), this.project.tsConfigPath))) {
55
142
  continue;
56
143
  }
57
- for (const fn of collectFunctions(sf)) {
144
+ // Detectors scan for a property of the code, not a user-declared subject
145
+ // set, so they always include object-literal functions. `functions()`
146
+ // keeps that opt-in because widening a selector silently changes every
147
+ // existing rule; a detector has no such contract to break, and a
148
+ // duplicated arrow under an object key — a resolver, a route handler, a
149
+ // reducer case — is exactly the copy-paste rot this exists to find.
150
+ for (const fn of collectFunctions(sf, { includeObjectLiteralFunctions: true })) {
58
151
  if (this.meetsMinLines(fn)) {
59
152
  allFunctions.push(fn);
60
153
  }
@@ -62,70 +155,107 @@ export class DuplicateBodiesBuilder extends SmellBuilder {
62
155
  }
63
156
  return allFunctions;
64
157
  }
65
- /** Build fingerprints for all collected functions. */
66
- fingerprintAll(functions) {
67
- const result = [];
68
- for (const fn of functions) {
69
- const body = fn.getBody();
70
- if (!body)
71
- continue;
72
- result.push({ fn, fingerprint: buildFingerprint(body) });
73
- }
74
- return result;
158
+ /** Build violations from similar pairs. */
159
+ /**
160
+ * Report order for pairs — which, measured, never has anything to order.
161
+ *
162
+ * Extracted from {@link buildViolations} so that method is the violation shape
163
+ * and nothing else. Enforcement review of bug 0242 read this as a live defect
164
+ * (keyed on `a`, i.e. walk order, while the finding reports at the anchor).
165
+ * Probing it says otherwise: {@link buildViolations} is reached only from
166
+ * {@link buildClusterViolations} for a cluster of two or fewer members, and
167
+ * such a cluster carries exactly one pair. Instrumented to throw on more than
168
+ * one, the whole `packages/ts` suite (3604 tests) produced **zero** hits.
169
+ *
170
+ * So this cannot reorder anything today, and {@link orderedClusters} is what
171
+ * actually orders the output. The key is corrected anyway — being right if
172
+ * this ever becomes reachable costs one expression — but the correction fixes
173
+ * no observable behaviour, and saying otherwise would be the kind of unmeasured
174
+ * claim this repo keeps catching.
175
+ */
176
+ orderedPairs(pairs) {
177
+ if (!this._groupByFolder)
178
+ return pairs;
179
+ // Keyed on the ANCHOR's folder, not on `a`'s. Which endpoint is `a` is the
180
+ // source walk; the anchor is where the finding says it is (bug 0242). While
181
+ // those agreed this was invisible, and after the anchor moved a finding
182
+ // reported in one folder would sort into another folder's group — the one
183
+ // thing this option exists to prevent.
184
+ const keyed = pairs.map((pair) => ({
185
+ pair,
186
+ folder: path.dirname(anchorFile([pair.a, pair.b])),
187
+ }));
188
+ keyed.sort((x, y) => (x.folder < y.folder ? -1 : x.folder > y.folder ? 1 : 0));
189
+ return keyed.map((k) => k.pair);
75
190
  }
76
- /** Compare all pairs of fingerprints, collect those above threshold. */
77
- findSimilarPairs(items) {
78
- const pairs = [];
79
- for (let i = 0; i < items.length; i++) {
80
- for (let j = i + 1; j < items.length; j++) {
81
- const a = items[i];
82
- const b = items[j];
83
- if (!a || !b)
84
- continue;
85
- // Fast rejection: if node counts differ too much, similarity cannot reach threshold
86
- const maxCount = Math.max(a.fingerprint.nodeCount, b.fingerprint.nodeCount);
87
- const minCount = Math.min(a.fingerprint.nodeCount, b.fingerprint.nodeCount);
88
- if (maxCount > 0 && minCount / maxCount < this._minSimilarity) {
89
- continue;
90
- }
91
- const similarity = computeSimilarity(a.fingerprint, b.fingerprint);
92
- if (similarity >= this._minSimilarity) {
93
- pairs.push({ a: a.fn, b: b.fn, similarity });
94
- }
95
- }
96
- }
97
- return pairs;
191
+ /**
192
+ * One violation per CLUSTER of mutually-similar bodies, not per pair.
193
+ *
194
+ * A pair is the wrong unit and it is not a close call. Measured on a
195
+ * ~5,600-file production monorepo: 407 clusters emitted **4,770** pair
196
+ * findings — more findings than the 3,810 bodies that produced them. The
197
+ * eight largest clusters were 49% of the output, one cluster of 89 members
198
+ * emitted 398 lines, and the worst single function was named 29 times. Every
199
+ * one of those can be TRUE and the report is still unreadable, because N
200
+ * mutually-similar bodies carry one observation and emit N^2/2 lines of it.
201
+ *
202
+ * Two-member clusters — the common case — keep the exact message and identity
203
+ * they had before, so existing baselines for them are untouched. Only a group
204
+ * of three or more collapses, which is where the inflation lives.
205
+ */
206
+ /**
207
+ * Report order.
208
+ *
209
+ * Rank is presentation only — no pair is dropped and no score changes. At four
210
+ * thousand findings the ORDER is the product: what a reader sees first decides
211
+ * whether they read at all. `.groupByFolder()` still wins when asked for.
212
+ */
213
+ orderedClusters(clusters) {
214
+ // Decorated once, then sorted. `anchorFile` asks ts-morph for a path and a
215
+ // line per member, and a comparator runs O(n log n) times — on the 407
216
+ // clusters this module's own comments measure, computing it inside the
217
+ // comparator is tens of thousands of avoidable calls.
218
+ const keyed = clusters.map((cluster) => {
219
+ // The ANCHOR's folder, not `members[0]`'s: `members[0]` is the source walk
220
+ // and the finding is reported at the path-then-line minimum (bug 0242), so
221
+ // grouping on the walk would file a finding under a folder it is not
222
+ // reported in — the one thing `.groupByFolder()` exists to prevent.
223
+ const anchor = anchorFile(cluster.members);
224
+ return { cluster, anchor, folder: path.dirname(anchor), rank: clusterRank(cluster) };
225
+ });
226
+ // Plain `<`, not `localeCompare`: the latter's result depends on the
227
+ // runtime's ICU build and default locale, which is this record's own failure
228
+ // class — a report that reads differently on two machines — in the
229
+ // expression fixing it. `comparePositions` next door uses `<` too.
230
+ const text = (x, y) => (x < y ? -1 : x > y ? 1 : 0);
231
+ keyed.sort((x, y) => {
232
+ const primary = this._groupByFolder ? text(x.folder, y.folder) : y.rank - x.rank;
233
+ // The tie-break is what makes the SEQUENCE deterministic, and without it
234
+ // the default path had none: `clusterRank` returns one of four values over
235
+ // hundreds of clusters, and `Array#sort` is stable, so equal ranks kept
236
+ // walk order. Found by architecture review of bug 0242's fix; the branch
237
+ // had disclosed it in a test comment and nowhere else.
238
+ return primary !== 0 ? primary : text(x.anchor, y.anchor);
239
+ });
240
+ return keyed.map((k) => k.cluster);
98
241
  }
99
- /** Build violations from similar pairs. */
100
- buildViolations(pairs) {
101
- const ruleDescription = this.describe();
242
+ buildClusterViolations(pairs) {
102
243
  const violations = [];
103
- // Optionally sort pairs by folder for grouped output
104
- const sortedPairs = this._groupByFolder
105
- ? [...pairs].sort((x, y) => {
106
- const folderA = path.dirname(x.a.getSourceFile().getFilePath());
107
- const folderB = path.dirname(y.a.getSourceFile().getFilePath());
108
- return folderA.localeCompare(folderB);
109
- })
110
- : pairs;
111
- for (const pair of sortedPairs) {
112
- const nameA = pair.a.getName() ?? '<anonymous>';
113
- const fileA = pair.a.getSourceFile().getFilePath();
114
- const lineA = pair.a.getStartLineNumber();
115
- const nameB = pair.b.getName() ?? '<anonymous>';
116
- const fileB = pair.b.getSourceFile().getFilePath();
117
- const lineB = pair.b.getStartLineNumber();
118
- const pct = Math.round(pair.similarity * 100);
119
- violations.push({
120
- rule: ruleDescription,
121
- element: nameA,
122
- file: fileA,
123
- line: lineA,
124
- message: `${nameA} (${fileA}:${String(lineA)}) is ${String(pct)}% similar to ${nameB} (${fileB}:${String(lineB)})`,
125
- because: this._reason,
126
- });
244
+ for (const cluster of this.orderedClusters(clusterPairs(pairs))) {
245
+ // A two-member cluster IS the pair, so it keeps the message and the
246
+ // baseline identity that already shipped. Only three-or-more collapses,
247
+ // which is where the inflation lives.
248
+ if (cluster.members.length <= 2) {
249
+ violations.push(...this.buildViolations(cluster.pairs));
250
+ continue;
251
+ }
252
+ violations.push(clusterViolation(cluster, { rule: this.describe(), because: this._reason }));
127
253
  }
128
254
  return violations;
129
255
  }
256
+ buildViolations(pairs) {
257
+ const context = { rule: this.describe(), because: this._reason };
258
+ return this.orderedPairs([...pairs]).map((pair) => pairViolation(pair, context));
259
+ }
130
260
  }
131
261
  //# sourceMappingURL=duplicate-bodies.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"duplicate-bodies.js","sourceRoot":"","sources":["../../src/smells/duplicate-bodies.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"duplicate-bodies.js","sourceRoot":"","sources":["../../src/smells/duplicate-bodies.ts"],"names":[],"mappings":"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"}