@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.
- package/README.md +61 -35
- package/dist/builders/call-rule-builder.d.ts +66 -26
- package/dist/builders/call-rule-builder.d.ts.map +1 -1
- package/dist/builders/call-rule-builder.js +75 -32
- package/dist/builders/call-rule-builder.js.map +1 -1
- package/dist/builders/class-rule-builder.d.ts +125 -26
- package/dist/builders/class-rule-builder.d.ts.map +1 -1
- package/dist/builders/class-rule-builder.js +141 -55
- package/dist/builders/class-rule-builder.js.map +1 -1
- package/dist/builders/correspondence-builder.d.ts +287 -0
- package/dist/builders/correspondence-builder.d.ts.map +1 -0
- package/dist/builders/correspondence-builder.js +385 -0
- package/dist/builders/correspondence-builder.js.map +1 -0
- package/dist/builders/correspondence-findings.d.ts +104 -0
- package/dist/builders/correspondence-findings.d.ts.map +1 -0
- package/dist/builders/correspondence-findings.js +301 -0
- package/dist/builders/correspondence-findings.js.map +1 -0
- package/dist/builders/cross-layer-builder.d.ts +99 -16
- package/dist/builders/cross-layer-builder.d.ts.map +1 -1
- package/dist/builders/cross-layer-builder.js +182 -35
- package/dist/builders/cross-layer-builder.js.map +1 -1
- package/dist/builders/function-rule-builder.d.ts +144 -25
- package/dist/builders/function-rule-builder.d.ts.map +1 -1
- package/dist/builders/function-rule-builder.js +177 -39
- package/dist/builders/function-rule-builder.js.map +1 -1
- package/dist/builders/jsx-rule-builder.d.ts +70 -14
- package/dist/builders/jsx-rule-builder.d.ts.map +1 -1
- package/dist/builders/jsx-rule-builder.js +73 -14
- package/dist/builders/jsx-rule-builder.js.map +1 -1
- package/dist/builders/module-rule-builder.d.ts +2 -2
- package/dist/builders/module-rule-builder.d.ts.map +1 -1
- package/dist/builders/module-rule-builder.js +16 -19
- package/dist/builders/module-rule-builder.js.map +1 -1
- package/dist/builders/scoped-function-rule-builder.d.ts +11 -0
- package/dist/builders/scoped-function-rule-builder.d.ts.map +1 -1
- package/dist/builders/scoped-function-rule-builder.js +12 -0
- package/dist/builders/scoped-function-rule-builder.js.map +1 -1
- package/dist/builders/slice-discovery-message.d.ts +36 -0
- package/dist/builders/slice-discovery-message.d.ts.map +1 -0
- package/dist/builders/slice-discovery-message.js +181 -0
- package/dist/builders/slice-discovery-message.js.map +1 -0
- package/dist/builders/slice-rule-builder.d.ts +151 -12
- package/dist/builders/slice-rule-builder.d.ts.map +1 -1
- package/dist/builders/slice-rule-builder.js +243 -35
- package/dist/builders/slice-rule-builder.js.map +1 -1
- package/dist/builders/type-rule-builder.d.ts +95 -24
- package/dist/builders/type-rule-builder.d.ts.map +1 -1
- package/dist/builders/type-rule-builder.js +109 -42
- package/dist/builders/type-rule-builder.js.map +1 -1
- package/dist/{helpers → builders}/within.d.ts +2 -2
- package/dist/builders/within.d.ts.map +1 -0
- package/dist/{helpers → builders}/within.js +1 -1
- package/dist/builders/within.js.map +1 -0
- package/dist/cli/commands/baseline.d.ts +8 -3
- package/dist/cli/commands/baseline.d.ts.map +1 -1
- package/dist/cli/commands/baseline.js +111 -7
- package/dist/cli/commands/baseline.js.map +1 -1
- package/dist/cli/commands/check.d.ts +7 -2
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +385 -47
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +29 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +224 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/explain.d.ts +2 -1
- package/dist/cli/commands/explain.d.ts.map +1 -1
- package/dist/cli/commands/explain.js +19 -10
- package/dist/cli/commands/explain.js.map +1 -1
- package/dist/cli/commands/init.d.ts +9 -3
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +162 -137
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/import-rule-module.d.ts +29 -0
- package/dist/cli/import-rule-module.d.ts.map +1 -0
- package/dist/cli/import-rule-module.js +47 -0
- package/dist/cli/import-rule-module.js.map +1 -0
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +101 -43
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/load-rules.d.ts +6 -11
- package/dist/cli/load-rules.d.ts.map +1 -1
- package/dist/cli/load-rules.js +25 -32
- package/dist/cli/load-rules.js.map +1 -1
- package/dist/cli/resolve-config.d.ts +0 -8
- package/dist/cli/resolve-config.d.ts.map +1 -1
- package/dist/cli/resolve-config.js +25 -55
- package/dist/cli/resolve-config.js.map +1 -1
- package/dist/cli/rule-file-findings.d.ts +178 -0
- package/dist/cli/rule-file-findings.d.ts.map +1 -0
- package/dist/cli/rule-file-findings.js +351 -0
- package/dist/cli/rule-file-findings.js.map +1 -0
- package/dist/cli/watch.d.ts +17 -34
- package/dist/cli/watch.d.ts.map +1 -1
- package/dist/cli/watch.js +14 -129
- package/dist/cli/watch.js.map +1 -1
- package/dist/conditions/body-analysis-function.d.ts.map +1 -1
- package/dist/conditions/body-analysis-function.js +16 -7
- package/dist/conditions/body-analysis-function.js.map +1 -1
- package/dist/conditions/body-analysis-module.d.ts.map +1 -1
- package/dist/conditions/body-analysis-module.js +14 -9
- package/dist/conditions/body-analysis-module.js.map +1 -1
- package/dist/conditions/body-analysis.d.ts.map +1 -1
- package/dist/conditions/body-analysis.js +16 -7
- package/dist/conditions/body-analysis.js.map +1 -1
- package/dist/conditions/call.d.ts.map +1 -1
- package/dist/conditions/call.js +41 -19
- package/dist/conditions/call.js.map +1 -1
- package/dist/conditions/catch-analysis.d.ts +2 -1
- package/dist/conditions/catch-analysis.d.ts.map +1 -1
- package/dist/conditions/catch-analysis.js.map +1 -1
- package/dist/conditions/cross-layer.d.ts +2 -10
- package/dist/conditions/cross-layer.d.ts.map +1 -1
- package/dist/conditions/cross-layer.js +227 -23
- package/dist/conditions/cross-layer.js.map +1 -1
- package/dist/conditions/dependency.d.ts +35 -6
- package/dist/conditions/dependency.d.ts.map +1 -1
- package/dist/conditions/dependency.js +299 -45
- package/dist/conditions/dependency.js.map +1 -1
- package/dist/conditions/exports.d.ts.map +1 -1
- package/dist/conditions/exports.js +41 -37
- package/dist/conditions/exports.js.map +1 -1
- package/dist/conditions/function.d.ts.map +1 -1
- package/dist/conditions/function.js +19 -5
- package/dist/conditions/function.js.map +1 -1
- package/dist/conditions/helpers.d.ts +2 -1
- package/dist/conditions/helpers.d.ts.map +1 -1
- package/dist/conditions/helpers.js +4 -1
- package/dist/conditions/helpers.js.map +1 -1
- package/dist/conditions/jsx.d.ts.map +1 -1
- package/dist/conditions/jsx.js +7 -2
- package/dist/conditions/jsx.js.map +1 -1
- package/dist/conditions/match-identity.d.ts +43 -0
- package/dist/conditions/match-identity.d.ts.map +1 -0
- package/dist/conditions/match-identity.js +43 -0
- package/dist/conditions/match-identity.js.map +1 -0
- package/dist/conditions/members.d.ts.map +1 -1
- package/dist/conditions/members.js +20 -6
- package/dist/conditions/members.js.map +1 -1
- package/dist/conditions/reverse-dependency.d.ts +18 -5
- package/dist/conditions/reverse-dependency.d.ts.map +1 -1
- package/dist/conditions/reverse-dependency.js +155 -93
- package/dist/conditions/reverse-dependency.js.map +1 -1
- package/dist/conditions/slice.d.ts +86 -2
- package/dist/conditions/slice.d.ts.map +1 -1
- package/dist/conditions/slice.js +234 -53
- package/dist/conditions/slice.js.map +1 -1
- package/dist/conditions/structural.d.ts.map +1 -1
- package/dist/conditions/structural.js +16 -4
- package/dist/conditions/structural.js.map +1 -1
- package/dist/core/check-all.d.ts +19 -0
- package/dist/core/check-all.d.ts.map +1 -0
- package/dist/core/check-all.js +150 -0
- package/dist/core/check-all.js.map +1 -0
- package/dist/core/combinators.d.ts +48 -0
- package/dist/core/combinators.d.ts.map +1 -0
- package/dist/core/combinators.js +49 -0
- package/dist/core/combinators.js.map +1 -0
- package/dist/core/descendant-cache.d.ts +36 -0
- package/dist/core/descendant-cache.d.ts.map +1 -0
- package/dist/core/descendant-cache.js +117 -0
- package/dist/core/descendant-cache.js.map +1 -0
- package/dist/core/diagnose.d.ts +234 -0
- package/dist/core/diagnose.d.ts.map +1 -0
- package/dist/core/diagnose.js +390 -0
- package/dist/core/diagnose.js.map +1 -0
- package/dist/core/disk-set.d.ts +48 -0
- package/dist/core/disk-set.d.ts.map +1 -0
- package/dist/core/disk-set.js +218 -0
- package/dist/core/disk-set.js.map +1 -0
- package/dist/core/element-cache.d.ts +75 -0
- package/dist/core/element-cache.d.ts.map +1 -0
- package/dist/core/element-cache.js +32 -0
- package/dist/core/element-cache.js.map +1 -0
- package/dist/core/empty-project-advice.d.ts +75 -0
- package/dist/core/empty-project-advice.d.ts.map +1 -0
- package/dist/core/empty-project-advice.js +61 -0
- package/dist/core/empty-project-advice.js.map +1 -0
- package/dist/core/exclusion-comments.d.ts +19 -0
- package/dist/core/exclusion-comments.d.ts.map +1 -0
- package/dist/core/exclusion-comments.js +7 -0
- package/dist/core/exclusion-comments.js.map +1 -0
- package/dist/core/execute-rule.d.ts +158 -0
- package/dist/core/execute-rule.d.ts.map +1 -0
- package/dist/core/execute-rule.js +666 -0
- package/dist/core/execute-rule.js.map +1 -0
- package/dist/core/glob-diagnosis.d.ts +78 -0
- package/dist/core/glob-diagnosis.d.ts.map +1 -0
- package/dist/core/glob-diagnosis.js +134 -0
- package/dist/core/glob-diagnosis.js.map +1 -0
- package/dist/core/glob-evaluator.d.ts +48 -0
- package/dist/core/glob-evaluator.d.ts.map +1 -0
- package/dist/core/glob-evaluator.js +89 -0
- package/dist/core/glob-evaluator.js.map +1 -0
- package/dist/core/import-candidates.d.ts +60 -0
- package/dist/core/import-candidates.d.ts.map +1 -0
- package/dist/core/import-candidates.js +93 -0
- package/dist/core/import-candidates.js.map +1 -0
- package/dist/core/import-options.d.ts +55 -2
- package/dist/core/import-options.d.ts.map +1 -1
- package/dist/core/import-options.js +64 -0
- package/dist/core/import-options.js.map +1 -1
- package/dist/core/invalidate-on-modify.d.ts +20 -0
- package/dist/core/invalidate-on-modify.d.ts.map +1 -0
- package/dist/core/invalidate-on-modify.js +26 -0
- package/dist/core/invalidate-on-modify.js.map +1 -0
- package/dist/core/line-index.d.ts +3 -0
- package/dist/core/line-index.d.ts.map +1 -0
- package/dist/core/line-index.js +227 -0
- package/dist/core/line-index.js.map +1 -0
- package/dist/core/metric-violation.d.ts +86 -0
- package/dist/core/metric-violation.d.ts.map +1 -0
- package/dist/core/metric-violation.js +132 -0
- package/dist/core/metric-violation.js.map +1 -0
- package/dist/core/module-edges.d.ts +361 -0
- package/dist/core/module-edges.d.ts.map +1 -0
- package/dist/core/module-edges.js +593 -0
- package/dist/core/module-edges.js.map +1 -0
- package/dist/core/object-literal-functions.d.ts +42 -0
- package/dist/core/object-literal-functions.d.ts.map +1 -0
- package/dist/core/object-literal-functions.js +75 -0
- package/dist/core/object-literal-functions.js.map +1 -0
- package/dist/core/orphan-exclusions.d.ts +44 -0
- package/dist/core/orphan-exclusions.d.ts.map +1 -0
- package/dist/core/orphan-exclusions.js +224 -0
- package/dist/core/orphan-exclusions.js.map +1 -0
- package/dist/core/pair-condition.d.ts +32 -3
- package/dist/core/pair-condition.d.ts.map +1 -1
- package/dist/core/path-universe.d.ts +22 -0
- package/dist/core/path-universe.d.ts.map +1 -0
- package/dist/core/path-universe.js +45 -0
- package/dist/core/path-universe.js.map +1 -0
- package/dist/core/per-root-compiler-options.d.ts +20 -0
- package/dist/core/per-root-compiler-options.d.ts.map +1 -0
- package/dist/core/per-root-compiler-options.js +57 -0
- package/dist/core/per-root-compiler-options.js.map +1 -0
- package/dist/core/project-relative.d.ts +98 -0
- package/dist/core/project-relative.d.ts.map +1 -0
- package/dist/core/project-relative.js +185 -0
- package/dist/core/project-relative.js.map +1 -0
- package/dist/core/project.d.ts +7 -1
- package/dist/core/project.d.ts.map +1 -1
- package/dist/core/project.js +29 -4
- package/dist/core/project.js.map +1 -1
- package/dist/core/rule-builder.d.ts +303 -0
- package/dist/core/rule-builder.d.ts.map +1 -0
- package/dist/core/rule-builder.js +463 -0
- package/dist/core/rule-builder.js.map +1 -0
- package/dist/core/rule-declaration.d.ts +32 -0
- package/dist/core/rule-declaration.d.ts.map +1 -0
- package/dist/core/rule-declaration.js +88 -0
- package/dist/core/rule-declaration.js.map +1 -0
- package/dist/core/terminal-builder.d.ts +629 -0
- package/dist/core/terminal-builder.d.ts.map +1 -0
- package/dist/core/terminal-builder.js +807 -0
- package/dist/core/terminal-builder.js.map +1 -0
- package/dist/core/terminal-execution.d.ts +39 -0
- package/dist/core/terminal-execution.d.ts.map +1 -0
- package/dist/core/terminal-execution.js +103 -0
- package/dist/core/terminal-execution.js.map +1 -0
- package/dist/core/ts-comment-mask.d.ts +2 -0
- package/dist/core/ts-comment-mask.d.ts.map +1 -0
- package/dist/core/ts-comment-mask.js +102 -0
- package/dist/core/ts-comment-mask.js.map +1 -0
- package/dist/core/vacuity-diagnosis.d.ts +103 -0
- package/dist/core/vacuity-diagnosis.d.ts.map +1 -0
- package/dist/core/vacuity-diagnosis.js +415 -0
- package/dist/core/vacuity-diagnosis.js.map +1 -0
- package/dist/core/violation.d.ts +16 -11
- package/dist/core/violation.d.ts.map +1 -1
- package/dist/core/violation.js +33 -13
- package/dist/core/violation.js.map +1 -1
- package/dist/graphql/graphql-rule-builder.d.ts +95 -0
- package/dist/graphql/graphql-rule-builder.d.ts.map +1 -0
- package/dist/graphql/graphql-rule-builder.js +127 -0
- package/dist/graphql/graphql-rule-builder.js.map +1 -0
- package/dist/graphql/index.d.ts +1 -0
- package/dist/graphql/index.d.ts.map +1 -1
- package/dist/graphql/index.js +2 -1
- package/dist/graphql/index.js.map +1 -1
- package/dist/graphql/resolver-rule-builder.d.ts +44 -23
- package/dist/graphql/resolver-rule-builder.d.ts.map +1 -1
- package/dist/graphql/resolver-rule-builder.js +80 -72
- package/dist/graphql/resolver-rule-builder.js.map +1 -1
- package/dist/graphql/schema-loader.d.ts +21 -0
- package/dist/graphql/schema-loader.d.ts.map +1 -1
- package/dist/graphql/schema-loader.js +82 -12
- package/dist/graphql/schema-loader.js.map +1 -1
- package/dist/graphql/schema-predicates.d.ts.map +1 -1
- package/dist/graphql/schema-predicates.js +17 -12
- package/dist/graphql/schema-predicates.js.map +1 -1
- package/dist/graphql/schema-rule-builder.d.ts +15 -24
- package/dist/graphql/schema-rule-builder.d.ts.map +1 -1
- package/dist/graphql/schema-rule-builder.js +39 -77
- package/dist/graphql/schema-rule-builder.js.map +1 -1
- package/dist/helpers/baseline-diagnostics.d.ts +45 -0
- package/dist/helpers/baseline-diagnostics.d.ts.map +1 -0
- package/dist/helpers/baseline-diagnostics.js +168 -0
- package/dist/helpers/baseline-diagnostics.js.map +1 -0
- package/dist/helpers/baseline-generator.d.ts +28 -0
- package/dist/helpers/baseline-generator.d.ts.map +1 -0
- package/dist/helpers/baseline-generator.js +27 -0
- package/dist/helpers/baseline-generator.js.map +1 -0
- package/dist/helpers/baseline.d.ts +336 -0
- package/dist/helpers/baseline.d.ts.map +1 -0
- package/dist/helpers/baseline.js +664 -0
- package/dist/helpers/baseline.js.map +1 -0
- package/dist/helpers/body-traversal.d.ts +27 -2
- package/dist/helpers/body-traversal.d.ts.map +1 -1
- package/dist/helpers/body-traversal.js +135 -16
- package/dist/helpers/body-traversal.js.map +1 -1
- package/dist/helpers/callback-extractor.d.ts.map +1 -1
- package/dist/helpers/callback-extractor.js +53 -84
- package/dist/helpers/callback-extractor.js.map +1 -1
- package/dist/helpers/complexity.d.ts +13 -5
- package/dist/helpers/complexity.d.ts.map +1 -1
- package/dist/helpers/complexity.js +15 -6
- package/dist/helpers/complexity.js.map +1 -1
- package/dist/helpers/diff-aware.d.ts +16 -0
- package/dist/helpers/diff-aware.d.ts.map +1 -0
- package/dist/helpers/diff-aware.js +16 -0
- package/dist/helpers/diff-aware.js.map +1 -0
- package/dist/helpers/matchers.d.ts +68 -7
- package/dist/helpers/matchers.d.ts.map +1 -1
- package/dist/helpers/matchers.js +164 -86
- package/dist/helpers/matchers.js.map +1 -1
- package/dist/helpers/slice-graph.d.ts +100 -8
- package/dist/helpers/slice-graph.d.ts.map +1 -1
- package/dist/helpers/slice-graph.js +126 -34
- package/dist/helpers/slice-graph.js.map +1 -1
- package/dist/helpers/tarjan.d.ts +0 -14
- package/dist/helpers/tarjan.d.ts.map +1 -1
- package/dist/helpers/tarjan.js +29 -16
- package/dist/helpers/tarjan.js.map +1 -1
- package/dist/index.d.ts +55 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +67 -15
- package/dist/index.js.map +1 -1
- package/dist/models/arch-call.d.ts +3 -2
- package/dist/models/arch-call.d.ts.map +1 -1
- package/dist/models/arch-call.js.map +1 -1
- package/dist/models/arch-function.d.ts +54 -8
- package/dist/models/arch-function.d.ts.map +1 -1
- package/dist/models/arch-function.js +145 -8
- package/dist/models/arch-function.js.map +1 -1
- package/dist/models/arch-jsx-element.d.ts.map +1 -1
- package/dist/models/arch-jsx-element.js +18 -19
- package/dist/models/arch-jsx-element.js.map +1 -1
- package/dist/models/slice.d.ts +33 -9
- package/dist/models/slice.d.ts.map +1 -1
- package/dist/models/slice.js +129 -19
- package/dist/models/slice.js.map +1 -1
- package/dist/predicates/call.d.ts.map +1 -1
- package/dist/predicates/call.js +5 -0
- package/dist/predicates/call.js.map +1 -1
- package/dist/predicates/identity.d.ts +21 -0
- package/dist/predicates/identity.d.ts.map +1 -1
- package/dist/predicates/identity.js +75 -3
- package/dist/predicates/identity.js.map +1 -1
- package/dist/predicates/index.d.ts +1 -1
- package/dist/predicates/index.d.ts.map +1 -1
- package/dist/predicates/index.js +1 -1
- package/dist/predicates/index.js.map +1 -1
- package/dist/predicates/jsx.d.ts.map +1 -1
- package/dist/predicates/jsx.js +2 -1
- package/dist/predicates/jsx.js.map +1 -1
- package/dist/predicates/metrics.d.ts +4 -2
- package/dist/predicates/metrics.d.ts.map +1 -1
- package/dist/predicates/metrics.js +4 -2
- package/dist/predicates/metrics.js.map +1 -1
- package/dist/predicates/module.d.ts +4 -12
- package/dist/predicates/module.d.ts.map +1 -1
- package/dist/predicates/module.js +57 -37
- package/dist/predicates/module.js.map +1 -1
- package/dist/presets/agent-guardrails.d.ts +49 -16
- package/dist/presets/agent-guardrails.d.ts.map +1 -1
- package/dist/presets/agent-guardrails.js +308 -19
- package/dist/presets/agent-guardrails.js.map +1 -1
- package/dist/presets/boundaries.d.ts +46 -3
- package/dist/presets/boundaries.d.ts.map +1 -1
- package/dist/presets/boundaries.js +132 -23
- package/dist/presets/boundaries.js.map +1 -1
- package/dist/presets/data-layer.d.ts +23 -3
- package/dist/presets/data-layer.d.ts.map +1 -1
- package/dist/presets/data-layer.js +58 -16
- package/dist/presets/data-layer.js.map +1 -1
- package/dist/presets/index.d.ts +10 -5
- package/dist/presets/index.d.ts.map +1 -1
- package/dist/presets/index.js +19 -3
- package/dist/presets/index.js.map +1 -1
- package/dist/presets/layered.d.ts +47 -3
- package/dist/presets/layered.d.ts.map +1 -1
- package/dist/presets/layered.js +66 -29
- package/dist/presets/layered.js.map +1 -1
- package/dist/presets/recommended.d.ts +81 -10
- package/dist/presets/recommended.d.ts.map +1 -1
- package/dist/presets/recommended.js +25 -23
- package/dist/presets/recommended.js.map +1 -1
- package/dist/presets/shared.d.ts +267 -2
- package/dist/presets/shared.d.ts.map +1 -1
- package/dist/presets/shared.js +367 -4
- package/dist/presets/shared.js.map +1 -1
- package/dist/rules/code-quality.d.ts.map +1 -1
- package/dist/rules/code-quality.js +15 -6
- package/dist/rules/code-quality.js.map +1 -1
- package/dist/rules/hygiene.d.ts +1 -1
- package/dist/rules/hygiene.js +1 -1
- package/dist/rules/metrics-function.d.ts +2 -1
- package/dist/rules/metrics-function.d.ts.map +1 -1
- package/dist/rules/metrics-function.js +63 -39
- package/dist/rules/metrics-function.js.map +1 -1
- package/dist/rules/metrics.d.ts +2 -1
- package/dist/rules/metrics.d.ts.map +1 -1
- package/dist/rules/metrics.js +80 -47
- package/dist/rules/metrics.js.map +1 -1
- package/dist/smells/clusters.d.ts +78 -0
- package/dist/smells/clusters.d.ts.map +1 -0
- package/dist/smells/clusters.js +124 -0
- package/dist/smells/clusters.js.map +1 -0
- package/dist/smells/duplicate-bodies.d.ts +92 -5
- package/dist/smells/duplicate-bodies.d.ts.map +1 -1
- package/dist/smells/duplicate-bodies.js +203 -73
- package/dist/smells/duplicate-bodies.js.map +1 -1
- package/dist/smells/duplicate-report.d.ts +90 -0
- package/dist/smells/duplicate-report.d.ts.map +1 -0
- package/dist/smells/duplicate-report.js +344 -0
- package/dist/smells/duplicate-report.js.map +1 -0
- package/dist/smells/fingerprint.d.ts +20 -1
- package/dist/smells/fingerprint.d.ts.map +1 -1
- package/dist/smells/fingerprint.js +27 -3
- package/dist/smells/fingerprint.js.map +1 -1
- package/dist/smells/inconsistent-siblings.d.ts +128 -7
- package/dist/smells/inconsistent-siblings.d.ts.map +1 -1
- package/dist/smells/inconsistent-siblings.js +288 -86
- package/dist/smells/inconsistent-siblings.js.map +1 -1
- package/dist/smells/sibling-files.d.ts +47 -0
- package/dist/smells/sibling-files.d.ts.map +1 -0
- package/dist/smells/sibling-files.js +104 -0
- package/dist/smells/sibling-files.js.map +1 -0
- package/dist/smells/similar-pairs.d.ts +28 -0
- package/dist/smells/similar-pairs.d.ts.map +1 -0
- package/dist/smells/similar-pairs.js +134 -0
- package/dist/smells/similar-pairs.js.map +1 -0
- package/dist/smells/smell-builder.d.ts +57 -12
- package/dist/smells/smell-builder.d.ts.map +1 -1
- package/dist/smells/smell-builder.js +112 -14
- package/dist/smells/smell-builder.js.map +1 -1
- package/dist/smells/variation.d.ts +47 -0
- package/dist/smells/variation.d.ts.map +1 -0
- package/dist/smells/variation.js +90 -0
- package/dist/smells/variation.js.map +1 -0
- package/dist/tsconfig/index.d.ts +19 -0
- package/dist/tsconfig/index.d.ts.map +1 -0
- package/dist/tsconfig/index.js +20 -0
- package/dist/tsconfig/index.js.map +1 -0
- package/dist/tsconfig/tsconfig-builder.d.ts +42 -9
- package/dist/tsconfig/tsconfig-builder.d.ts.map +1 -1
- package/dist/tsconfig/tsconfig-builder.js +65 -16
- package/dist/tsconfig/tsconfig-builder.js.map +1 -1
- package/package.json +4 -2
- package/dist/core/module-dependencies.d.ts +0 -28
- package/dist/core/module-dependencies.d.ts.map +0 -1
- package/dist/core/module-dependencies.js +0 -35
- package/dist/core/module-dependencies.js.map +0 -1
- package/dist/helpers/within.d.ts.map +0 -1
- package/dist/helpers/within.js.map +0 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ArchProject } from './project.js';
|
|
2
|
+
/**
|
|
3
|
+
* What the filesystem says about a glob that the compiler's file set does not.
|
|
4
|
+
*
|
|
5
|
+
* Only populated for `no-match` — the other faults are syntactic and the disk
|
|
6
|
+
* has nothing to add. `not-determined` is the honest answer above the walk's
|
|
7
|
+
* entry budget, or where the walk refused to look.
|
|
8
|
+
*
|
|
9
|
+
* Declared here rather than in `glob-diagnosis.ts` because this is the module
|
|
10
|
+
* that produces it: the other way round made the two files import each other.
|
|
11
|
+
* Both edges were `import type` and therefore erased at runtime — but our own
|
|
12
|
+
* `arch/no-cycles` rule slices by directory, so it could not see a cycle
|
|
13
|
+
* INSIDE `core/`, and a per-file slicing in a test found it immediately. A
|
|
14
|
+
* cycle nothing can see is the shape this whole plan is about.
|
|
15
|
+
*/
|
|
16
|
+
export type OnDisk = 'holds-typescript' | 'no-typescript' | 'absent' | 'not-determined';
|
|
17
|
+
/**
|
|
18
|
+
* What the filesystem knows that the compiler's file set does not.
|
|
19
|
+
*
|
|
20
|
+
* The second derivation ADR-009 rule 5 asks for: filesystem contents versus
|
|
21
|
+
* compiler membership. It is what distinguishes "your glob is misspelled" from
|
|
22
|
+
* "your glob is fine and your tsconfig scope excludes it" — the cheapest wrong
|
|
23
|
+
* action an agent can take, and the majority case in a real monorepo.
|
|
24
|
+
*/
|
|
25
|
+
export interface DiskSet {
|
|
26
|
+
/** Classify a glob by what exists on disk under the paths it matches. */
|
|
27
|
+
classify(glob: string): OnDisk;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The project's disk set, walked at most once and only when asked.
|
|
31
|
+
*
|
|
32
|
+
* Lazy on purpose. This is only ever reached from `diagnoseGlob`, which is
|
|
33
|
+
* only ever reached from an already-firing fault, so a project with no faults
|
|
34
|
+
* never touches the filesystem. An eager version would charge every `check()`
|
|
35
|
+
* a recursive walk to answer a question no fault asked.
|
|
36
|
+
*/
|
|
37
|
+
export declare function diskSet(project: ArchProject): DiskSet;
|
|
38
|
+
/**
|
|
39
|
+
* The walk, with the budget injectable.
|
|
40
|
+
*
|
|
41
|
+
* Exported for tests only. The degrade path is the difference between "not
|
|
42
|
+
* determined" and a *partial, wrong* classification — a false "contains no
|
|
43
|
+
* TypeScript" in the one message whose whole defence is that it states only
|
|
44
|
+
* facts — and with the budget a module constant it could only ever have been
|
|
45
|
+
* reached by accident on a repository nobody has.
|
|
46
|
+
*/
|
|
47
|
+
export declare function buildDiskSet(project: ArchProject, budgetLimit?: number): DiskSet;
|
|
48
|
+
//# sourceMappingURL=disk-set.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disk-set.d.ts","sourceRoot":"","sources":["../../src/core/disk-set.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAkD/C;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,MAAM,GAAG,kBAAkB,GAAG,eAAe,GAAG,QAAQ,GAAG,gBAAgB,CAAA;AAEvF;;;;;;;GAOG;AACH,MAAM,WAAW,OAAO;IACtB,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;CAC/B;AAID;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAMrD;AAED;;;;;;;;GAQG;AAEH,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,WAAW,SAAe,GAAG,OAAO,CAEtF"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import picomatch from 'picomatch';
|
|
4
|
+
import { discoverIdentityRoot } from '@nielspeter/eess/internal';
|
|
5
|
+
/**
|
|
6
|
+
* Directories never worth walking.
|
|
7
|
+
*
|
|
8
|
+
* `node_modules` and `.git` dominate the cost. The build-output names are here
|
|
9
|
+
* because a walk that reports `dist/` as "absent from the project" is noise,
|
|
10
|
+
* not a finding. The list cannot be complete — a real TypeScript monorepo may
|
|
11
|
+
* hold a Rust `target/`, a Python `.venv`, a `.gradle` — which is why the
|
|
12
|
+
* entry budget below exists rather than a longer list.
|
|
13
|
+
*/
|
|
14
|
+
const PRUNE = new Set([
|
|
15
|
+
'node_modules',
|
|
16
|
+
'.git',
|
|
17
|
+
'dist',
|
|
18
|
+
'build',
|
|
19
|
+
'out',
|
|
20
|
+
'coverage',
|
|
21
|
+
'.next',
|
|
22
|
+
'.turbo',
|
|
23
|
+
'.venv',
|
|
24
|
+
'vendor',
|
|
25
|
+
'target',
|
|
26
|
+
'.gradle',
|
|
27
|
+
'.yarn',
|
|
28
|
+
'.cache',
|
|
29
|
+
]);
|
|
30
|
+
/**
|
|
31
|
+
* How many directory entries the walk will read before giving up.
|
|
32
|
+
*
|
|
33
|
+
* An implementation constant, not part of the public contract and not
|
|
34
|
+
* tunable. It exists because the walk is unbounded in principle: a
|
|
35
|
+
* contributor who has run `cargo build` inside a TypeScript monorepo has tens
|
|
36
|
+
* of thousands of entries under one directory, and a *failing* run that then
|
|
37
|
+
* hangs inside a 5s vitest timeout is a worse experience than the false green
|
|
38
|
+
* this whole mechanism exists to remove. Above the budget the classification
|
|
39
|
+
* degrades to `not-determined`, which costs message quality and nothing else —
|
|
40
|
+
* the enrichment is already fail-open.
|
|
41
|
+
*/
|
|
42
|
+
const ENTRY_BUDGET = 50_000;
|
|
43
|
+
// `.d.ts` and its `.d.mts`/`.d.cts` siblings count. They ARE TypeScript for
|
|
44
|
+
// the question this set answers — "does this path contain TypeScript your
|
|
45
|
+
// tsconfig is keeping out" — and excluding them made a `types/` directory of
|
|
46
|
+
// pure declarations report "this path exists but contains no TypeScript",
|
|
47
|
+
// which is false.
|
|
48
|
+
const TS_FILE = /\.(m|c)?tsx?$/;
|
|
49
|
+
const cache = new WeakMap();
|
|
50
|
+
/**
|
|
51
|
+
* The project's disk set, walked at most once and only when asked.
|
|
52
|
+
*
|
|
53
|
+
* Lazy on purpose. This is only ever reached from `diagnoseGlob`, which is
|
|
54
|
+
* only ever reached from an already-firing fault, so a project with no faults
|
|
55
|
+
* never touches the filesystem. An eager version would charge every `check()`
|
|
56
|
+
* a recursive walk to answer a question no fault asked.
|
|
57
|
+
*/
|
|
58
|
+
export function diskSet(project) {
|
|
59
|
+
const cached = cache.get(project);
|
|
60
|
+
if (cached)
|
|
61
|
+
return cached;
|
|
62
|
+
const built = build(project, ENTRY_BUDGET);
|
|
63
|
+
cache.set(project, built);
|
|
64
|
+
return built;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The walk, with the budget injectable.
|
|
68
|
+
*
|
|
69
|
+
* Exported for tests only. The degrade path is the difference between "not
|
|
70
|
+
* determined" and a *partial, wrong* classification — a false "contains no
|
|
71
|
+
* TypeScript" in the one message whose whole defence is that it states only
|
|
72
|
+
* facts — and with the budget a module constant it could only ever have been
|
|
73
|
+
* reached by accident on a repository nobody has.
|
|
74
|
+
*/
|
|
75
|
+
// eess-exclude eess/no-unused-exports: consumed by the test suite; the build tsconfig this gate reads excludes tests, so `src` is the only usage it can see
|
|
76
|
+
export function buildDiskSet(project, budgetLimit = ENTRY_BUDGET) {
|
|
77
|
+
return build(project, budgetLimit);
|
|
78
|
+
}
|
|
79
|
+
function build(project, budgetLimit) {
|
|
80
|
+
// Guard on the INPUT, before deriving anything. `discoverIdentityRoot` calls
|
|
81
|
+
// `path.resolve`, so every root it returns is absolute and checking the
|
|
82
|
+
// output can never fail. Both halves matter, and this repo's own suite
|
|
83
|
+
// supplies both: the relative `'in-memory'` double (whose dirname is '.',
|
|
84
|
+
// which would walk the real CWD) and absolute paths that do not exist, where
|
|
85
|
+
// `readdirSync` throws from inside a guard. Counted in prose as "eight
|
|
86
|
+
// doubles, two relative" until the suite reached 114 of them — so the shapes
|
|
87
|
+
// are named and the arithmetic is not. And `ArchProject` is a public type, so
|
|
88
|
+
// this protects user-constructed projects, not only test doubles.
|
|
89
|
+
if (!path.isAbsolute(project.tsConfigPath))
|
|
90
|
+
return UNDETERMINED;
|
|
91
|
+
const root = discoverIdentityRoot(path.dirname(project.tsConfigPath));
|
|
92
|
+
if (!fs.existsSync(root))
|
|
93
|
+
return UNDETERMINED;
|
|
94
|
+
const files = [];
|
|
95
|
+
/** Every file, TypeScript or not — so `absent` means absent, not "not TypeScript". */
|
|
96
|
+
const everyFile = [];
|
|
97
|
+
const dirs = [];
|
|
98
|
+
/**
|
|
99
|
+
* Directories the walk refused to enter.
|
|
100
|
+
*
|
|
101
|
+
* A glob matching one of these cannot be classified: nothing under it was
|
|
102
|
+
* seen. Reporting `absent` would say "this path does not exist" about
|
|
103
|
+
* `**\/dist/**` or `**\/vendor/**` — all realistic rule scopes — and
|
|
104
|
+
* `absent` carries no advice, so the caller then falls back to a cause list
|
|
105
|
+
* beginning "a path segment is misspelled".
|
|
106
|
+
*/
|
|
107
|
+
const pruned = [];
|
|
108
|
+
let budget = budgetLimit;
|
|
109
|
+
let exhausted = false;
|
|
110
|
+
const walk = (dir) => {
|
|
111
|
+
if (exhausted)
|
|
112
|
+
return;
|
|
113
|
+
let entries;
|
|
114
|
+
try {
|
|
115
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
void err; // unreadable or gone: not a finding, just not walkable
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
budget -= entries.length;
|
|
122
|
+
if (budget < 0) {
|
|
123
|
+
exhausted = true;
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
for (const entry of entries) {
|
|
127
|
+
const full = path.join(dir, entry.name).replaceAll('\\', '/');
|
|
128
|
+
// Prune by NAME, before asking whether it is a directory.
|
|
129
|
+
//
|
|
130
|
+
// [ts-archunit Bug 0045](https://github.com/nielspeter/ts-archunit/blob/main/bugs/fixed/0045-two-tests-fail-by-environment-and-corrupt-sabotage-verdicts.md):
|
|
131
|
+
// `Dirent.isDirectory()` is false for a symlink, so a symlinked
|
|
132
|
+
// `node_modules` — what pnpm produces, and what `git worktree add`
|
|
133
|
+
// leaves behind — fell through to the `else` branch and was recorded as
|
|
134
|
+
// a **file**. It never entered `pruned`, so a glob under it classified
|
|
135
|
+
// `absent` ("no such path") instead of `not-determined` ("this walk
|
|
136
|
+
// cannot say"). Those carry different advice, and `absent` is the one
|
|
137
|
+
// that asserts something false.
|
|
138
|
+
//
|
|
139
|
+
// Safe: pruning records the path and does not recurse, so no link is
|
|
140
|
+
// followed and the loop argument below is untouched.
|
|
141
|
+
if (PRUNE.has(entry.name)) {
|
|
142
|
+
pruned.push(full);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
// `Dirent.isDirectory()` is false for a symlink under `withFileTypes`,
|
|
146
|
+
// so symlink loops are impossible by construction. Do not "fix" this
|
|
147
|
+
// with `statSync`, which follows them.
|
|
148
|
+
//
|
|
149
|
+
// The cost, for symlinks we do NOT prune: a symlinked source directory —
|
|
150
|
+
// pnpm and yarn workspaces create them — is recorded as a file, so a glob
|
|
151
|
+
// naming it classifies `no-typescript`. Wrong, but wrong in the direction
|
|
152
|
+
// that only weakens a message; following the link risks a walk that never
|
|
153
|
+
// terminates.
|
|
154
|
+
if (entry.isDirectory()) {
|
|
155
|
+
dirs.push(full);
|
|
156
|
+
walk(full);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
everyFile.push(full);
|
|
160
|
+
if (TS_FILE.test(entry.name))
|
|
161
|
+
files.push(full);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
walk(root.replaceAll('\\', '/'));
|
|
166
|
+
if (exhausted)
|
|
167
|
+
return UNDETERMINED;
|
|
168
|
+
// Containment is TRANSITIVE, and that is load-bearing. Using each file's
|
|
169
|
+
// immediate parent instead labels `docs/` "contains no TypeScript" while
|
|
170
|
+
// `docs/.vitepress/config.ts` sits one level below it — a false statement in
|
|
171
|
+
// the one message whose entire defence is that it states only facts.
|
|
172
|
+
// Measured on this repo: 36 directories hold TypeScript transitively but not
|
|
173
|
+
// directly.
|
|
174
|
+
const holdsTypeScript = new Set();
|
|
175
|
+
for (const file of files) {
|
|
176
|
+
let dir = path.dirname(file);
|
|
177
|
+
while (dir.length >= root.length) {
|
|
178
|
+
holdsTypeScript.add(dir);
|
|
179
|
+
const parent = path.dirname(dir);
|
|
180
|
+
if (parent === dir)
|
|
181
|
+
break;
|
|
182
|
+
dir = parent;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Directories AND every file, not just the TypeScript ones. Deriving
|
|
186
|
+
// `absent` from the TypeScript-only set asserted "this path does not exist"
|
|
187
|
+
// about any path holding a `.md`, a `.json`, or anything under a pruned
|
|
188
|
+
// name — and `absent` carries no advice, so the caller fell back to
|
|
189
|
+
// `no-match`'s list, whose first cause is "a path segment is misspelled".
|
|
190
|
+
// Exactly the confidently-wrong cause ADR-009 rule 2 forbids.
|
|
191
|
+
const everything = [...everyFile, ...dirs];
|
|
192
|
+
const typeScript = new Set(files);
|
|
193
|
+
return {
|
|
194
|
+
classify(glob) {
|
|
195
|
+
const isMatch = picomatch(glob);
|
|
196
|
+
// Never `everything.some(isMatch)` — picomatch reads the array index as
|
|
197
|
+
// its second argument and returns a truthy object from index 1 onwards.
|
|
198
|
+
const matched = everything.filter((candidate) => isMatch(candidate));
|
|
199
|
+
if (matched.length === 0) {
|
|
200
|
+
// Not seen is not the same as not there.
|
|
201
|
+
return pruned.some((dir) => isMatch(dir) || glob.includes(dir.slice(root.length + 1)))
|
|
202
|
+
? 'not-determined'
|
|
203
|
+
: 'absent';
|
|
204
|
+
}
|
|
205
|
+
// Per GLOB, not per path: one glob routinely matches paths in both
|
|
206
|
+
// categories — `**/tests/**` matched 44 directories of mixed kind on the
|
|
207
|
+
// monorepo this was gated against. Any matched path holding TypeScript
|
|
208
|
+
// makes the tsconfig the story worth telling.
|
|
209
|
+
return matched.some((candidate) => holdsTypeScript.has(candidate) || typeScript.has(candidate))
|
|
210
|
+
? 'holds-typescript'
|
|
211
|
+
: 'no-typescript';
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
const UNDETERMINED = {
|
|
216
|
+
classify: () => 'not-determined',
|
|
217
|
+
};
|
|
218
|
+
//# sourceMappingURL=disk-set.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disk-set.js","sourceRoot":"","sources":["../../src/core/disk-set.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { ArchProject } from './project.js';
|
|
2
|
+
/**
|
|
3
|
+
* Collect a builder's elements once per project instead of once per rule.
|
|
4
|
+
*
|
|
5
|
+
* Plan 0075. `filterElements()` calls `getElements()` on every rule execution
|
|
6
|
+
* and each builder re-collects from scratch, so a suite with five `calls()`
|
|
7
|
+
* rules walks every file's AST five times. Measured on this repository (518
|
|
8
|
+
* files): **5 × `calls()` issued 2,600 `getDescendantsOfKind` queries in 692ms;
|
|
9
|
+
* with this memo, 0 in 3ms warm** — measured against the implementation by
|
|
10
|
+
* stashing it, not projected from a prototype.
|
|
11
|
+
*
|
|
12
|
+
* ## Why a factory rather than one shared map
|
|
13
|
+
*
|
|
14
|
+
* A single `WeakMap<ArchProject, Map<string, unknown[]>>` would need a cast to
|
|
15
|
+
* hand `unknown[]` back as `ArchCall[]`, and ADR-005 bars both `any` and `as`.
|
|
16
|
+
* Each builder module instead creates its own instance at module scope, closed
|
|
17
|
+
* over its own element type, so the type survives end to end with no assertion.
|
|
18
|
+
*
|
|
19
|
+
* ## Why `WeakMap`, keyed on the project object
|
|
20
|
+
*
|
|
21
|
+
* The same shape `src/core/disk-set.ts:83` and `src/core/path-universe.ts:35`
|
|
22
|
+
* already use. Keying on **object identity** is what makes a stale entry
|
|
23
|
+
* unreachable: `resetProjectCache()` (`project.ts:178`) clears the `project()`
|
|
24
|
+
* and `workspace()` maps, so the next call constructs a new object literal and
|
|
25
|
+
* therefore a new key. Watch mode depends on that, and it is where a stale
|
|
26
|
+
* cache would be an ADR-008 failure rather than a slow test — a rule
|
|
27
|
+
* re-evaluated against a pre-edit AST reports a pass the edit did not earn. A
|
|
28
|
+
* cache keyed on `tsConfigPath` would pass this repository's whole suite and
|
|
29
|
+
* silently break watch mode.
|
|
30
|
+
*
|
|
31
|
+
* ## What it does not cover, measured rather than asserted
|
|
32
|
+
*
|
|
33
|
+
* An `ArchProject` a consumer built themselves and holds across a change to the
|
|
34
|
+
* underlying ts-morph project. An earlier version of this docstring said the memo
|
|
35
|
+
* "does not worsen" that case. **It does**, and review measured it:
|
|
36
|
+
*
|
|
37
|
+
* classes(p).subjects() -> One
|
|
38
|
+
* m.createSourceFile('/two.ts', …)
|
|
39
|
+
* classes(p).subjects() -> One (before this cache: One, Two)
|
|
40
|
+
*
|
|
41
|
+
* The population is frozen at first collection for the lifetime of the project
|
|
42
|
+
* object, so a rule about `Two` selects nothing and passes — an ADR-008 false
|
|
43
|
+
* green manufactured by a cache. Re-collection used to heal it.
|
|
44
|
+
*
|
|
45
|
+
* Two things make it survivable, and both are load-bearing rather than
|
|
46
|
+
* reassuring: the CLI is unaffected, because `resetProjectCache()`
|
|
47
|
+
* (`project.ts`) builds a new `ArchProject` per run and `--watch` calls it; and
|
|
48
|
+
* `resetProjectCache()` now **also clears these caches**, so a consumer holding
|
|
49
|
+
* their own project object has a documented way out. Call it after mutating.
|
|
50
|
+
*
|
|
51
|
+
* ## What must NOT be cached through this
|
|
52
|
+
*
|
|
53
|
+
* The **unfiltered** `getElements()` result only. `filterElements()`
|
|
54
|
+
* unconditionally calls `.filter(...)`, which always allocates, so `subjects()`
|
|
55
|
+
* keeps handing out a fresh array and no caller can alias the cached one.
|
|
56
|
+
* Memoizing `filterElements()` instead would break that *and* be wrong:
|
|
57
|
+
* `ScopedFunctionRuleBuilder` overrides `getElements()` to draw from a call
|
|
58
|
+
* selection rather than the project, so a shared key would serve
|
|
59
|
+
* `within(sel).functions()` the plain `functions()` population and let
|
|
60
|
+
* `.should().notExist()` pass vacuously.
|
|
61
|
+
*/
|
|
62
|
+
interface ElementCache<T> {
|
|
63
|
+
/**
|
|
64
|
+
* The cached collection for `project` under `key`, collecting it on first
|
|
65
|
+
* ask. `key` distinguishes populations that differ for the same project —
|
|
66
|
+
* see `FunctionRuleBuilder`, whose collection options change what it returns.
|
|
67
|
+
*/
|
|
68
|
+
get(project: ArchProject, key: string, collect: () => T[]): T[];
|
|
69
|
+
}
|
|
70
|
+
/** A cache private to one builder module, typed to that builder's element. */
|
|
71
|
+
export declare function createElementCache<T>(): ElementCache<T>;
|
|
72
|
+
/** The key for builders whose population is a function of the project alone. */
|
|
73
|
+
export declare const SOLE_POPULATION = "default";
|
|
74
|
+
export {};
|
|
75
|
+
//# sourceMappingURL=element-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element-cache.d.ts","sourceRoot":"","sources":["../../src/core/element-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,UAAU,YAAY,CAAC,CAAC;IACtB;;;;OAIG;IACH,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,EAAE,CAAA;CAChE;AAED,8EAA8E;AAC9E,wBAAgB,kBAAkB,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,CA0BvD;AAED,gFAAgF;AAChF,eAAO,MAAM,eAAe,YAAY,CAAA"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { registerCacheReset } from '@nielspeter/eess/internal';
|
|
2
|
+
/** A cache private to one builder module, typed to that builder's element. */
|
|
3
|
+
export function createElementCache() {
|
|
4
|
+
let perProject = new WeakMap();
|
|
5
|
+
// Registered rather than exported: a `clearElementCaches()` that `project.ts`
|
|
6
|
+
// imported directly would close the cycle `project -> element-cache -> project`
|
|
7
|
+
// (the back edge is `import type { ArchProject }`, which counts).
|
|
8
|
+
registerCacheReset(() => {
|
|
9
|
+
perProject = new WeakMap();
|
|
10
|
+
});
|
|
11
|
+
return {
|
|
12
|
+
get(project, key, collect) {
|
|
13
|
+
let byKey = perProject.get(project);
|
|
14
|
+
if (byKey === undefined) {
|
|
15
|
+
byKey = new Map();
|
|
16
|
+
perProject.set(project, byKey);
|
|
17
|
+
}
|
|
18
|
+
const hit = byKey.get(key);
|
|
19
|
+
// `has`, not truthiness: a legitimately empty collection is `[]`, and
|
|
20
|
+
// `[]` is truthy — but an empty project is exactly the case where
|
|
21
|
+
// re-collecting on every rule is pure waste, so it must cache too.
|
|
22
|
+
if (hit !== undefined)
|
|
23
|
+
return hit;
|
|
24
|
+
const fresh = collect();
|
|
25
|
+
byKey.set(key, fresh);
|
|
26
|
+
return fresh;
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** The key for builders whose population is a function of the project alone. */
|
|
31
|
+
export const SOLE_POPULATION = 'default';
|
|
32
|
+
//# sourceMappingURL=element-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element-cache.js","sourceRoot":"","sources":["../../src/core/element-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAuE9D,8EAA8E;AAC9E,MAAM,UAAU,kBAAkB;IAChC,IAAI,UAAU,GAAG,IAAI,OAAO,EAAiC,CAAA;IAC7D,8EAA8E;IAC9E,gFAAgF;IAChF,kEAAkE;IAClE,kBAAkB,CAAC,GAAG,EAAE;QACtB,UAAU,GAAG,IAAI,OAAO,EAAiC,CAAA;IAC3D,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,GAAG,CAAC,OAAoB,EAAE,GAAW,EAAE,OAAkB;YACvD,IAAI,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YACnC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,KAAK,GAAG,IAAI,GAAG,EAAe,CAAA;gBAC9B,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;YAChC,CAAC;YACD,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAC1B,sEAAsE;YACtE,kEAAkE;YAClE,mEAAmE;YACnE,IAAI,GAAG,KAAK,SAAS;gBAAE,OAAO,GAAG,CAAA;YACjC,MAAM,KAAK,GAAG,OAAO,EAAE,CAAA;YACvB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;YACrB,OAAO,KAAK,CAAA;QACd,CAAC;KACF,CAAA;AACH,CAAC;AAED,gFAAgF;AAChF,MAAM,CAAC,MAAM,eAAe,GAAG,SAAS,CAAA"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one text for "this project loaded nothing", owned in one place.
|
|
3
|
+
*
|
|
4
|
+
* Two surfaces state this fact: `diagnose()` (and through it `doctor`) and
|
|
5
|
+
* `SliceRuleBuilder`'s discovery message, which is what a **failing `check`
|
|
6
|
+
* build** prints. They were written separately and had already diverged at
|
|
7
|
+
* birth — the builder said only "Check that this tsconfig includes your
|
|
8
|
+
* sources", which bug 0031 itself records as not actionable for a config that
|
|
9
|
+
* has no `include` at all, while `diagnose` named the solution-style cause. So
|
|
10
|
+
* the high-stakes surface carried the weaker text.
|
|
11
|
+
*
|
|
12
|
+
* This is the `assertionAdvice` precedent applied to a second state: plan 0070
|
|
13
|
+
* put that one behind a single owner after the two copies were **measured**
|
|
14
|
+
* diverging, and a later review found a third copy re-added with nothing
|
|
15
|
+
* failing. Two texts for one state is a trust problem for an agent diffing
|
|
16
|
+
* them.
|
|
17
|
+
*
|
|
18
|
+
* Reported by review of the bug 0031 fix, which created the second copy while
|
|
19
|
+
* quoting the bug's own instruction not to.
|
|
20
|
+
*/
|
|
21
|
+
import type { ArchProject } from './project.js';
|
|
22
|
+
/**
|
|
23
|
+
* Why nothing can match, and what to do about it.
|
|
24
|
+
*
|
|
25
|
+
* Deliberately **not** ending in a period: both call sites append their own
|
|
26
|
+
* trailing sentence.
|
|
27
|
+
*
|
|
28
|
+
* ## The solution-style clause is conditional, and that is the point
|
|
29
|
+
*
|
|
30
|
+
* An earlier revision **asserted** it — "this one is solution-style, so point
|
|
31
|
+
* the rules at the tsconfig that does" — and review refuted that: the imperative
|
|
32
|
+
* is impossible on several reachable shapes with no such sibling (an `include`
|
|
33
|
+
* that matches nothing yet, a repository with no `.ts` files, `allowJs: false`
|
|
34
|
+
* over a `.js` tree, `"files": []` with no `references` at all). ADR-008
|
|
35
|
+
* rule 2 — a stated fix that is impossible on the path that produced it is
|
|
36
|
+
* worse than none.
|
|
37
|
+
*
|
|
38
|
+
* The obvious repair was to read the tsconfig and state it only when true. That
|
|
39
|
+
* was **written, and then removed by this project's own architecture rules**:
|
|
40
|
+
* it put `JSON.parse` in `src/core/`, which `hygiene/no-json-parse` bans with
|
|
41
|
+
* the reason "eess-ts analyzes AST, not JSON", and `references` is not in
|
|
42
|
+
* `getCompilerOptions()` so ts-morph cannot supply it (ADR-002 rules out the
|
|
43
|
+
* raw TypeScript API). Exempting the rule to accommodate this file would be
|
|
44
|
+
* the wrong direction — the rule is right.
|
|
45
|
+
*
|
|
46
|
+
* So the clause is phrased as a **condition the reader can evaluate in one
|
|
47
|
+
* glance at their own file**. It is true whether or not their config has that
|
|
48
|
+
* shape, it names the mechanism that produced the commonest real occurrence,
|
|
49
|
+
* and it asserts nothing the tool has not checked.
|
|
50
|
+
*/
|
|
51
|
+
/**
|
|
52
|
+
* Did this project load nothing at all?
|
|
53
|
+
*
|
|
54
|
+
* The **decision**, extracted — [ts-archunit bug 0048](https://github.com/nielspeter/ts-archunit/blob/main/bugs/fixed/0048-the-dead-glob-gate-blames-the-glob-when-the-project-is-empty.md).
|
|
55
|
+
*
|
|
56
|
+
* `emptyProjectAdvice` already owned the *text*, and that was taken to mean the
|
|
57
|
+
* state had one owner. It did not: the test `if (getSourceFiles().length === 0)`
|
|
58
|
+
* lived in `diagnose.ts` and in `SliceRuleBuilder`, and **not** in the assertion
|
|
59
|
+
* gate — so a selector-position glob in an empty project was told its glob could
|
|
60
|
+
* never match and to correct it. The glob was correct; the tsconfig loaded
|
|
61
|
+
* nothing.
|
|
62
|
+
*
|
|
63
|
+
* Measured on `tests/fixtures/does-not-load`: the selector path said *"This
|
|
64
|
+
* rule's selector … can never match anything … Correct the glob, or remove the
|
|
65
|
+
* rule"* while `doctor` and the slice path both said *"The project loaded 0
|
|
66
|
+
* source files"*.
|
|
67
|
+
*
|
|
68
|
+
* Two texts for one state is a trust problem for an agent diffing them — which
|
|
69
|
+
* is this file's original argument. Two **decisions** about when to use the one
|
|
70
|
+
* text is the same problem one level up, and it is the level the first fix
|
|
71
|
+
* missed.
|
|
72
|
+
*/
|
|
73
|
+
export declare function loadedNothing(project: ArchProject): boolean;
|
|
74
|
+
export declare function emptyProjectAdvice(project: ArchProject): string;
|
|
75
|
+
//# sourceMappingURL=empty-project-advice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"empty-project-advice.d.ts","sourceRoot":"","sources":["../../src/core/empty-project-advice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAE3D;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAO/D"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Why nothing can match, and what to do about it.
|
|
3
|
+
*
|
|
4
|
+
* Deliberately **not** ending in a period: both call sites append their own
|
|
5
|
+
* trailing sentence.
|
|
6
|
+
*
|
|
7
|
+
* ## The solution-style clause is conditional, and that is the point
|
|
8
|
+
*
|
|
9
|
+
* An earlier revision **asserted** it — "this one is solution-style, so point
|
|
10
|
+
* the rules at the tsconfig that does" — and review refuted that: the imperative
|
|
11
|
+
* is impossible on several reachable shapes with no such sibling (an `include`
|
|
12
|
+
* that matches nothing yet, a repository with no `.ts` files, `allowJs: false`
|
|
13
|
+
* over a `.js` tree, `"files": []` with no `references` at all). ADR-008
|
|
14
|
+
* rule 2 — a stated fix that is impossible on the path that produced it is
|
|
15
|
+
* worse than none.
|
|
16
|
+
*
|
|
17
|
+
* The obvious repair was to read the tsconfig and state it only when true. That
|
|
18
|
+
* was **written, and then removed by this project's own architecture rules**:
|
|
19
|
+
* it put `JSON.parse` in `src/core/`, which `hygiene/no-json-parse` bans with
|
|
20
|
+
* the reason "eess-ts analyzes AST, not JSON", and `references` is not in
|
|
21
|
+
* `getCompilerOptions()` so ts-morph cannot supply it (ADR-002 rules out the
|
|
22
|
+
* raw TypeScript API). Exempting the rule to accommodate this file would be
|
|
23
|
+
* the wrong direction — the rule is right.
|
|
24
|
+
*
|
|
25
|
+
* So the clause is phrased as a **condition the reader can evaluate in one
|
|
26
|
+
* glance at their own file**. It is true whether or not their config has that
|
|
27
|
+
* shape, it names the mechanism that produced the commonest real occurrence,
|
|
28
|
+
* and it asserts nothing the tool has not checked.
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* Did this project load nothing at all?
|
|
32
|
+
*
|
|
33
|
+
* The **decision**, extracted — [ts-archunit bug 0048](https://github.com/nielspeter/ts-archunit/blob/main/bugs/fixed/0048-the-dead-glob-gate-blames-the-glob-when-the-project-is-empty.md).
|
|
34
|
+
*
|
|
35
|
+
* `emptyProjectAdvice` already owned the *text*, and that was taken to mean the
|
|
36
|
+
* state had one owner. It did not: the test `if (getSourceFiles().length === 0)`
|
|
37
|
+
* lived in `diagnose.ts` and in `SliceRuleBuilder`, and **not** in the assertion
|
|
38
|
+
* gate — so a selector-position glob in an empty project was told its glob could
|
|
39
|
+
* never match and to correct it. The glob was correct; the tsconfig loaded
|
|
40
|
+
* nothing.
|
|
41
|
+
*
|
|
42
|
+
* Measured on `tests/fixtures/does-not-load`: the selector path said *"This
|
|
43
|
+
* rule's selector … can never match anything … Correct the glob, or remove the
|
|
44
|
+
* rule"* while `doctor` and the slice path both said *"The project loaded 0
|
|
45
|
+
* source files"*.
|
|
46
|
+
*
|
|
47
|
+
* Two texts for one state is a trust problem for an agent diffing them — which
|
|
48
|
+
* is this file's original argument. Two **decisions** about when to use the one
|
|
49
|
+
* text is the same problem one level up, and it is the level the first fix
|
|
50
|
+
* missed.
|
|
51
|
+
*/
|
|
52
|
+
export function loadedNothing(project) {
|
|
53
|
+
return project.getSourceFiles().length === 0;
|
|
54
|
+
}
|
|
55
|
+
export function emptyProjectAdvice(project) {
|
|
56
|
+
return (`the project loaded 0 source files (${project.tsConfigPath}), so no glob can match. ` +
|
|
57
|
+
`Check that this tsconfig includes your sources — and if it delegates to project ` +
|
|
58
|
+
`references ("files": [] with "references"), it loads none of them itself, so the rules ` +
|
|
59
|
+
`need the tsconfig that holds your sources rather than this one`);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=empty-project-advice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"empty-project-advice.js","sourceRoot":"","sources":["../../src/core/empty-project-advice.ts"],"names":[],"mappings":"AAsBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,aAAa,CAAC,OAAoB;IAChD,OAAO,OAAO,CAAC,cAAc,EAAE,CAAC,MAAM,KAAK,CAAC,CAAA;AAC9C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAoB;IACrD,OAAO,CACL,sCAAsC,OAAO,CAAC,YAAY,2BAA2B;QACrF,kFAAkF;QAClF,yFAAyF;QACzF,gEAAgE,CACjE,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { isExcludedByComment as isExcludedShared } from '@nielspeter/eess';
|
|
2
|
+
import type { ExclusionComment, ExclusionWarning, ParseResult } from '@nielspeter/eess';
|
|
3
|
+
/**
|
|
4
|
+
* Exclusion comments for `eess-ts` — the kernel's parser, with this dialect's
|
|
5
|
+
* lexer.
|
|
6
|
+
*
|
|
7
|
+
* **This file used to be a second parser** (426 lines), and it drifted: bug
|
|
8
|
+
* 0158's fix landed on the kernel copy and never reached here, so a bare
|
|
9
|
+
* `eess-exclude-start` was silent in `eess-ts` and blamed the `-end` line when it
|
|
10
|
+
* did speak. That is bug 0227, and it is why ADR-012 exists.
|
|
11
|
+
*
|
|
12
|
+
* What was ever this package's own is the masker — knowing which spans of a
|
|
13
|
+
* `.ts` file are string literals needs a TypeScript parser, and the kernel
|
|
14
|
+
* cannot have one. That is now the only thing passed across.
|
|
15
|
+
*/
|
|
16
|
+
export type { ExclusionComment, ExclusionWarning, ParseResult };
|
|
17
|
+
export declare function parseExclusionComments(sourceText: string, filePath: string): ParseResult;
|
|
18
|
+
export declare const isExcludedByComment: typeof isExcludedShared;
|
|
19
|
+
//# sourceMappingURL=exclusion-comments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exclusion-comments.d.ts","sourceRoot":"","sources":["../../src/core/exclusion-comments.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,mBAAmB,IAAI,gBAAgB,EACxC,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAGvF;;;;;;;;;;;;GAYG;AACH,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAA;AAE/D,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,CAExF;AAED,eAAO,MAAM,mBAAmB,yBAAmB,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { parseExclusionComments as parseShared, isExcludedByComment as isExcludedShared, } from '@nielspeter/eess';
|
|
2
|
+
import { maskTsLiterals } from './ts-comment-mask.js';
|
|
3
|
+
export function parseExclusionComments(sourceText, filePath) {
|
|
4
|
+
return parseShared(sourceText, filePath, { mask: maskTsLiterals });
|
|
5
|
+
}
|
|
6
|
+
export const isExcludedByComment = isExcludedShared;
|
|
7
|
+
//# sourceMappingURL=exclusion-comments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exclusion-comments.js","sourceRoot":"","sources":["../../src/core/exclusion-comments.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,IAAI,WAAW,EACrC,mBAAmB,IAAI,gBAAgB,GACxC,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAiBrD,MAAM,UAAU,sBAAsB,CAAC,UAAkB,EAAE,QAAgB;IACzE,OAAO,WAAW,CAAC,UAAU,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAA;AACpE,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,gBAAgB,CAAA"}
|