@nielspeter/eess-ts 0.2.1 → 0.4.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 +73 -31
- 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 +134 -30
- 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 +393 -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 +181 -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 +173 -26
- 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 +12 -3
- 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 +242 -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 +105 -29
- 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 +3 -2
- package/dist/cli/commands/baseline.d.ts.map +1 -1
- package/dist/cli/commands/baseline.js +68 -6
- 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 +241 -45
- 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 +60 -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 +98 -33
- 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 +21 -29
- package/dist/cli/load-rules.js.map +1 -1
- package/dist/cli/resolve-config.d.ts.map +1 -1
- package/dist/cli/resolve-config.js +24 -24
- 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 +293 -0
- package/dist/cli/rule-file-findings.js.map +1 -0
- package/dist/cli/watch.d.ts +20 -7
- package/dist/cli/watch.d.ts.map +1 -1
- package/dist/cli/watch.js +39 -14
- 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 +38 -17
- 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 +10 -0
- 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 +17 -4
- 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 +109 -92
- 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 +96 -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 +56 -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 +119 -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 +382 -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 +54 -0
- package/dist/core/exclusion-comments.d.ts.map +1 -0
- package/dist/core/exclusion-comments.js +310 -0
- package/dist/core/exclusion-comments.js.map +1 -0
- package/dist/core/execute-rule.d.ts +150 -0
- package/dist/core/execute-rule.d.ts.map +1 -0
- package/dist/core/execute-rule.js +580 -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/line-index.d.ts +3 -0
- package/dist/core/line-index.d.ts.map +1 -0
- package/dist/core/line-index.js +229 -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 +592 -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 +214 -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 +54 -0
- package/dist/core/path-universe.d.ts.map +1 -0
- package/dist/core/path-universe.js +65 -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 +24 -0
- package/dist/core/project.js.map +1 -1
- package/dist/core/rule-builder.d.ts +282 -0
- package/dist/core/rule-builder.d.ts.map +1 -0
- package/dist/core/rule-builder.js +445 -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 +126 -0
- package/dist/core/rule-declaration.js.map +1 -0
- package/dist/core/terminal-builder.d.ts +625 -0
- package/dist/core/terminal-builder.d.ts.map +1 -0
- package/dist/core/terminal-builder.js +787 -0
- package/dist/core/terminal-builder.js.map +1 -0
- package/dist/core/terminal-execution.d.ts +23 -0
- package/dist/core/terminal-execution.d.ts.map +1 -0
- package/dist/core/terminal-execution.js +71 -0
- package/dist/core/terminal-execution.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/index.js +1 -1
- package/dist/graphql/index.js.map +1 -1
- package/dist/graphql/resolver-rule-builder.d.ts +98 -23
- package/dist/graphql/resolver-rule-builder.d.ts.map +1 -1
- package/dist/graphql/resolver-rule-builder.js +151 -21
- 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 +81 -12
- package/dist/graphql/schema-loader.js.map +1 -1
- package/dist/graphql/schema-rule-builder.d.ts +57 -20
- package/dist/graphql/schema-rule-builder.d.ts.map +1 -1
- package/dist/graphql/schema-rule-builder.js +101 -25
- 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 +19 -0
- package/dist/helpers/baseline-generator.d.ts.map +1 -0
- package/dist/helpers/baseline-generator.js +18 -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 +122 -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 +48 -47
- 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 +44 -0
- package/dist/helpers/diff-aware.d.ts.map +1 -0
- package/dist/helpers/diff-aware.js +84 -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 +114 -20
- 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 +56 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +57 -13
- 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 +28 -6
- package/dist/models/arch-function.d.ts.map +1 -1
- package/dist/models/arch-function.js +106 -3
- package/dist/models/arch-function.js.map +1 -1
- package/dist/models/arch-jsx-element.js +2 -2
- 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/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 +22 -15
- package/dist/presets/agent-guardrails.d.ts.map +1 -1
- package/dist/presets/agent-guardrails.js +124 -19
- package/dist/presets/agent-guardrails.js.map +1 -1
- package/dist/presets/boundaries.d.ts +45 -2
- 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 +22 -2
- 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 +7 -5
- package/dist/presets/index.d.ts.map +1 -1
- package/dist/presets/index.js +9 -3
- package/dist/presets/index.js.map +1 -1
- package/dist/presets/layered.d.ts +46 -2
- 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 +80 -9
- 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 +270 -2
- package/dist/presets/shared.d.ts.map +1 -1
- package/dist/presets/shared.js +338 -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 +33 -6
- 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 +39 -9
- package/dist/rules/metrics.js.map +1 -1
- package/dist/smells/duplicate-bodies.d.ts +58 -5
- package/dist/smells/duplicate-bodies.d.ts.map +1 -1
- package/dist/smells/duplicate-bodies.js +137 -56
- package/dist/smells/duplicate-bodies.js.map +1 -1
- package/dist/smells/fingerprint.d.ts +8 -1
- package/dist/smells/fingerprint.d.ts.map +1 -1
- package/dist/smells/fingerprint.js +21 -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 +27 -0
- package/dist/smells/similar-pairs.d.ts.map +1 -0
- package/dist/smells/similar-pairs.js +52 -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 +111 -14
- package/dist/smells/smell-builder.js.map +1 -1
- 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 +64 -16
- package/dist/tsconfig/tsconfig-builder.js.map +1 -1
- package/package.json +3 -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,96 @@
|
|
|
1
|
+
import { ArchRuleError } from '@nielspeter/eess';
|
|
2
|
+
import { callerAggregates, writeReport } from './execute-rule.js';
|
|
3
|
+
import { dedupeConfigFindings } from '@nielspeter/eess';
|
|
4
|
+
import { suppressionNotice } from '@nielspeter/eess';
|
|
5
|
+
import { writeStderr } from '@nielspeter/eess';
|
|
6
|
+
import { edgeCoverageNotice, resetEdgeCoverage, untestedRules } from '@nielspeter/eess';
|
|
7
|
+
import { commentSuppressionNotice, resetCommentSuppression } from '@nielspeter/eess';
|
|
8
|
+
/**
|
|
9
|
+
* Run an array of rules (e.g. a spread preset) and throw one aggregated
|
|
10
|
+
* `ArchRuleError` if any **error-severity** violation is found. Warn-severity
|
|
11
|
+
* violations are reported but never throw — the same severity contract as the
|
|
12
|
+
* CLI `check`. This is the test-file terminal for the returning form:
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* checkAll(layeredArchitecture(p, opts))
|
|
16
|
+
* checkAll([...recommended(p), ...layeredArchitecture(p, opts)])
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* Each builder's `.violations()` already carries its stamped severity
|
|
20
|
+
* (via `.asSeverity()`), so aggregation and severity are preserved across the
|
|
21
|
+
* whole array — one readable error listing every error-severity violation.
|
|
22
|
+
*/
|
|
23
|
+
export function checkAll(rules, options) {
|
|
24
|
+
// Per run, like `runCheck` — a second `checkAll` in one vitest file must
|
|
25
|
+
// not inherit the first's rules.
|
|
26
|
+
resetEdgeCoverage();
|
|
27
|
+
resetCommentSuppression();
|
|
28
|
+
// One option, one finding (plan 0074). A preset fans a single bad option out
|
|
29
|
+
// across every generated rule, and only an aggregation point can see that.
|
|
30
|
+
let violations = dedupeConfigFindings(rules.flatMap((rule) => rule.violations()));
|
|
31
|
+
if (options?.baseline) {
|
|
32
|
+
violations = options.baseline.filterNew(violations);
|
|
33
|
+
}
|
|
34
|
+
// `checkAll` filters once for the whole array, so like the CLI it can state
|
|
35
|
+
// the real number (plan 0071). The per-rule terminals cannot — see
|
|
36
|
+
// `core/diff-disclosure.ts`.
|
|
37
|
+
let notice;
|
|
38
|
+
if (options?.diff) {
|
|
39
|
+
const before = violations.length;
|
|
40
|
+
violations = options.diff.filterToChanged(violations);
|
|
41
|
+
notice = suppressionNotice(before - violations.length, options.diff.size, options.diff.baseBranch);
|
|
42
|
+
if (notice !== undefined)
|
|
43
|
+
writeStderr(notice);
|
|
44
|
+
}
|
|
45
|
+
// `reason` is rendered as each violation's "Why:" line on the terminal path
|
|
46
|
+
// (`format.ts`: `v.because ?? reason`), so a RUN-level notice must not travel
|
|
47
|
+
// that way — it would appear as the justification for an unrelated finding.
|
|
48
|
+
// `summary.reason` in JSON is genuinely run-level, so it goes there, and
|
|
49
|
+
// stderr carries it for every other format. Found by sabotage: removing the
|
|
50
|
+
// `writeStderr` call left the tests green because the notice was reaching
|
|
51
|
+
// stderr through the "Why:" line instead.
|
|
52
|
+
// Bug 0203 — the third emitter, and the same contract `executeCheck` and
|
|
53
|
+
// `deliver()` now honour. A `checkAll()` at module scope used to print its
|
|
54
|
+
// findings before an aggregating caller saw them, and the caller then reported
|
|
55
|
+
// the same violations again off the throw below.
|
|
56
|
+
//
|
|
57
|
+
// **Suppress exactly what rides the throw, and nothing else** — ADR-008's
|
|
58
|
+
// amendment, and this function is the case that gives it teeth. The throw at the
|
|
59
|
+
// bottom carries only the ERROR-severity subset, so warn-severity findings ride
|
|
60
|
+
// nothing. Suppressing them too is not "the caller will report it", it is
|
|
61
|
+
// deleting them: measured, four warn findings produced and discarded under
|
|
62
|
+
// `✓ eess-ts — 4 rules across 1 file · 0 failing`, exit 0. A fake green through
|
|
63
|
+
// this package's own CLI. The first version of this guard did exactly that.
|
|
64
|
+
//
|
|
65
|
+
// The flag defaults to `false`, so `checkAll()` in a test file — where nobody
|
|
66
|
+
// aggregates — still prints everything, exactly as before.
|
|
67
|
+
const ridesTheThrow = (v) => (v.severity ?? 'error') === 'error';
|
|
68
|
+
const toWrite = callerAggregates() ? violations.filter((v) => !ridesTheThrow(v)) : violations;
|
|
69
|
+
if (toWrite.length > 0 || (!callerAggregates() && options?.format === 'json')) {
|
|
70
|
+
writeReport(toWrite, options?.format, options?.format === 'json' ? notice : undefined, untestedRules());
|
|
71
|
+
}
|
|
72
|
+
// Bug 0015 reaches the in-test path too. `checkAll` is the vitest-side
|
|
73
|
+
// equivalent of `runCheck`, and a disclosure the recommended runner never
|
|
74
|
+
// shows is a disclosure that does not exist — the same argument that got
|
|
75
|
+
// `diagnose()` exported for the vitest half of the audience. The residual,
|
|
76
|
+
// stated: a bare `.check()` per rule has no run boundary to reset or report
|
|
77
|
+
// at, so it still shows nothing.
|
|
78
|
+
if (options?.format !== 'json') {
|
|
79
|
+
const coverage = edgeCoverageNotice();
|
|
80
|
+
if (coverage !== undefined)
|
|
81
|
+
writeStderr(`${coverage}\n`);
|
|
82
|
+
}
|
|
83
|
+
// Inline exclusion comments, same footnote position and the same reason. Kept
|
|
84
|
+
// out of the JSON prose for the same reason coverage is: a consumer parsing
|
|
85
|
+
// that document gets the identities structurally, not as a sentence to grep.
|
|
86
|
+
if (options?.format !== 'json') {
|
|
87
|
+
const suppressed = commentSuppressionNotice();
|
|
88
|
+
if (suppressed !== undefined)
|
|
89
|
+
writeStderr(`${suppressed}\n`);
|
|
90
|
+
}
|
|
91
|
+
const errors = violations.filter(ridesTheThrow);
|
|
92
|
+
if (errors.length > 0) {
|
|
93
|
+
throw new ArchRuleError(errors);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=check-all.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-all.js","sourceRoot":"","sources":["../../src/core/check-all.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Predicate } from '@nielspeter/eess';
|
|
2
|
+
import type { TypeMatcher } from './type-matcher.js';
|
|
3
|
+
/**
|
|
4
|
+
* Negates a predicate or type matcher.
|
|
5
|
+
*
|
|
6
|
+
* Accepts both `Predicate<T>` objects (used in `.that()` chains) and
|
|
7
|
+
* `TypeMatcher` functions (used in `.should()` condition arguments).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // Negate a predicate:
|
|
11
|
+
* functions(p).that().satisfy(not(areAsync())).should()...
|
|
12
|
+
*
|
|
13
|
+
* // Negate a type matcher:
|
|
14
|
+
* .should().haveReturnTypeMatching(not(matching(/void/)))
|
|
15
|
+
*/
|
|
16
|
+
export declare function not<T>(input: Predicate<T>): Predicate<T>;
|
|
17
|
+
export declare function not(input: TypeMatcher): TypeMatcher;
|
|
18
|
+
/**
|
|
19
|
+
* Combines predicates or type matchers with AND logic.
|
|
20
|
+
*
|
|
21
|
+
* All inputs must be the same kind: either all `Predicate<T>` or all
|
|
22
|
+
* `TypeMatcher`. Requires at least one argument.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // Combine predicates:
|
|
26
|
+
* functions(p).that().satisfy(and(areAsync(), areExported())).should()...
|
|
27
|
+
*
|
|
28
|
+
* // Combine type matchers:
|
|
29
|
+
* .should().haveReturnTypeMatching(and(matching(/Promise/), not(matching(/void/))))
|
|
30
|
+
*/
|
|
31
|
+
export declare function and<T>(...predicates: Predicate<T>[]): Predicate<T>;
|
|
32
|
+
export declare function and(...matchers: TypeMatcher[]): TypeMatcher;
|
|
33
|
+
/**
|
|
34
|
+
* Combines predicates or type matchers with OR logic.
|
|
35
|
+
*
|
|
36
|
+
* All inputs must be the same kind: either all `Predicate<T>` or all
|
|
37
|
+
* `TypeMatcher`. Requires at least one argument.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* // Combine predicates:
|
|
41
|
+
* functions(p).that().satisfy(or(areAsync(), areExported())).should()...
|
|
42
|
+
*
|
|
43
|
+
* // Combine type matchers:
|
|
44
|
+
* .should().haveReturnTypeMatching(or(matching(/Promise/), matching(/Collection/)))
|
|
45
|
+
*/
|
|
46
|
+
export declare function or<T>(...predicates: Predicate<T>[]): Predicate<T>;
|
|
47
|
+
export declare function or(...matchers: TypeMatcher[]): TypeMatcher;
|
|
48
|
+
//# sourceMappingURL=combinators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"combinators.d.ts","sourceRoot":"","sources":["../../src/core/combinators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAGpD;;;;;;;;;;;;GAYG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;AACzD,wBAAgB,GAAG,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAAA;AAyBpD;;;;;;;;;;;;GAYG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,GAAG,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;AACnE,wBAAgB,GAAG,CAAC,GAAG,QAAQ,EAAE,WAAW,EAAE,GAAG,WAAW,CAAA;AAoB5D;;;;;;;;;;;;GAYG;AACH,wBAAgB,EAAE,CAAC,CAAC,EAAE,GAAG,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;AAClE,wBAAgB,EAAE,CAAC,GAAG,QAAQ,EAAE,WAAW,EAAE,GAAG,WAAW,CAAA"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { combineGlobs, negateGlobs } from '@nielspeter/eess';
|
|
2
|
+
export function not(input) {
|
|
3
|
+
if (typeof input === 'function') {
|
|
4
|
+
return (type) => !input(type);
|
|
5
|
+
}
|
|
6
|
+
return {
|
|
7
|
+
description: `not (${input.description})`,
|
|
8
|
+
test: (element) => !input.test(element),
|
|
9
|
+
// Negation-normal-form push-down: `op` inverts as well as `polarity`.
|
|
10
|
+
// `not(unsatisfiable)` selects everything, so a negated site is
|
|
11
|
+
// over-selection rather than vacuity and can never be a fault — but a
|
|
12
|
+
// `not` nested inside the subtree flips it back, which is why this cannot
|
|
13
|
+
// just flip polarity. See `negateGlobs`.
|
|
14
|
+
globs: input.globs && negateGlobs(input.globs),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function assertHomogeneous(inputs) {
|
|
18
|
+
if (inputs.length === 0)
|
|
19
|
+
return;
|
|
20
|
+
const firstIsFunction = typeof inputs[0] === 'function';
|
|
21
|
+
if (inputs.some((i) => (typeof i === 'function') !== firstIsFunction)) {
|
|
22
|
+
throw new TypeError('Cannot mix Predicate objects and TypeMatcher functions in and()/or()');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function and(...inputs) {
|
|
26
|
+
assertHomogeneous(inputs);
|
|
27
|
+
if (typeof inputs[0] === 'function') {
|
|
28
|
+
const matchers = inputs.filter((input) => typeof input === 'function');
|
|
29
|
+
const fn = (type) => matchers.every((m) => m(type));
|
|
30
|
+
return fn;
|
|
31
|
+
}
|
|
32
|
+
const predicates = inputs.filter((input) => typeof input !== 'function');
|
|
33
|
+
return {
|
|
34
|
+
description: predicates.map((p) => p.description).join(' and '),
|
|
35
|
+
test: (element) => predicates.every((p) => p.test(element)),
|
|
36
|
+
// A conjunction selects nothing as soon as ONE input does.
|
|
37
|
+
globs: combineGlobs('all', predicates.map((p) => p.globs)),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export function or(...inputs) {
|
|
41
|
+
assertHomogeneous(inputs);
|
|
42
|
+
if (typeof inputs[0] === 'function') {
|
|
43
|
+
const matchers = inputs.filter((input) => typeof input === 'function');
|
|
44
|
+
return (type) => matchers.some((m) => m(type));
|
|
45
|
+
}
|
|
46
|
+
const predicates = inputs.filter((input) => typeof input !== 'function');
|
|
47
|
+
return {
|
|
48
|
+
description: predicates.map((p) => p.description).join(' or '),
|
|
49
|
+
test: (element) => predicates.some((p) => p.test(element)),
|
|
50
|
+
// A disjunction selects nothing only when EVERY input does. Inputs that
|
|
51
|
+
// declare no globs become retained opaque children rather than being
|
|
52
|
+
// dropped — dropping them here is what would red `or(deadGlob, byName)`.
|
|
53
|
+
globs: combineGlobs('any', predicates.map((p) => p.globs)),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=combinators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"combinators.js","sourceRoot":"","sources":["../../src/core/combinators.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Node, SyntaxKind } from 'ts-morph';
|
|
2
|
+
/**
|
|
3
|
+
* Every descendant of `node` with the given kind, walked once per file version.
|
|
4
|
+
*
|
|
5
|
+
* A drop-in replacement for `node.getDescendantsOfKind(kind)`. Returns
|
|
6
|
+
* `readonly` because the array is shared: a caller that sorted or spliced it
|
|
7
|
+
* would corrupt every later matcher over the same body.
|
|
8
|
+
*/
|
|
9
|
+
export declare function descendantsOfKind(node: Node, kind: SyntaxKind): readonly Node[];
|
|
10
|
+
/**
|
|
11
|
+
* Every descendant of `node`, walked once per file version.
|
|
12
|
+
*
|
|
13
|
+
* The kind-independent twin of {@link descendantsOfKind}, for `findMatchesBroad`
|
|
14
|
+
* — the strategy `expression()` and `comment()` take, having no `syntaxKinds` to
|
|
15
|
+
* narrow by.
|
|
16
|
+
*
|
|
17
|
+
* **Measured** on this repository, 1,698 function bodies / 117,949 descendants,
|
|
18
|
+
* ts-morph's wrapper cache already warm:
|
|
19
|
+
*
|
|
20
|
+
* getDescendants() 49 ms <- what this removes
|
|
21
|
+
* + getText() on each 71 ms
|
|
22
|
+
* + regex test on each 68 ms
|
|
23
|
+
*
|
|
24
|
+
* The walk is roughly three quarters of a broad matcher's cost; the filter is the
|
|
25
|
+
* rest and is not shareable — `expression()`'s regex differs per matcher.
|
|
26
|
+
* (`comment()`'s dedup state was the other half of this until bug 0034 removed
|
|
27
|
+
* it; the filter is still per-matcher.) End to end, six successive broad
|
|
28
|
+
* rules over the same bodies: **~57 ms each becomes ~17 ms each.**
|
|
29
|
+
*
|
|
30
|
+
* The memory objection — that this retains every wrapper in every body rather
|
|
31
|
+
* than one kind's worth — does not survive checking. ts-morph's own
|
|
32
|
+
* `ForgetfulNodeCache` already holds every wrapper it creates for the lifetime of
|
|
33
|
+
* the `SourceFile`, so the array adds N references, not N objects.
|
|
34
|
+
*/
|
|
35
|
+
export declare function allDescendants(node: Node): readonly Node[];
|
|
36
|
+
//# sourceMappingURL=descendant-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"descendant-cache.d.ts","sourceRoot":"","sources":["../../src/core/descendant-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAc,UAAU,EAAE,MAAM,UAAU,CAAA;AA2I5D;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,GAAG,SAAS,IAAI,EAAE,CA0B/E;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,IAAI,EAAE,CAe1D"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { registerCacheReset } from '@nielspeter/eess';
|
|
2
|
+
let byFile = new WeakMap();
|
|
3
|
+
/** The kind-independent walk, in the same per-file lifetime as {@link byFile}. */
|
|
4
|
+
let allByFile = new WeakMap();
|
|
5
|
+
const watched = new WeakSet();
|
|
6
|
+
registerCacheReset(() => {
|
|
7
|
+
byFile = new WeakMap();
|
|
8
|
+
allByFile = new WeakMap();
|
|
9
|
+
});
|
|
10
|
+
/**
|
|
11
|
+
* Register the invalidation listener for a file, once.
|
|
12
|
+
*
|
|
13
|
+
* Not once per cache miss: a watch session that re-evaluates rules would
|
|
14
|
+
* otherwise accumulate one listener per rule execution. Both maps are dropped
|
|
15
|
+
* together, because the same event invalidates both.
|
|
16
|
+
*
|
|
17
|
+
* The closure reads `byFile` / `allByFile` as **live bindings** rather than
|
|
18
|
+
* capturing them, which is what keeps invalidation working after
|
|
19
|
+
* `registerCacheReset` replaces the maps. Capturing by value made a post-reset
|
|
20
|
+
* edit invisible and passed the entire suite — there is a test named for it.
|
|
21
|
+
*/
|
|
22
|
+
function watchOnce(sourceFile) {
|
|
23
|
+
if (watched.has(sourceFile))
|
|
24
|
+
return;
|
|
25
|
+
watched.add(sourceFile);
|
|
26
|
+
sourceFile.onModified(() => {
|
|
27
|
+
byFile.delete(sourceFile);
|
|
28
|
+
allByFile.delete(sourceFile);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Whether a cached list can still be read.
|
|
33
|
+
*
|
|
34
|
+
* Endpoints only, and that is not a heuristic: ts-morph's
|
|
35
|
+
* `ForgetfulNodeCache.forgetLastPoint` forgets a whole created-in-block set at
|
|
36
|
+
* once, so a partially-forgotten list is not a shape the mechanism produces.
|
|
37
|
+
* Walking the full list on every hit would cost what this module exists to save.
|
|
38
|
+
*/
|
|
39
|
+
function usable(nodes) {
|
|
40
|
+
const first = nodes[0];
|
|
41
|
+
if (first === undefined)
|
|
42
|
+
return true;
|
|
43
|
+
const last = nodes[nodes.length - 1];
|
|
44
|
+
return !first.wasForgotten() && last !== undefined && !last.wasForgotten();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Every descendant of `node` with the given kind, walked once per file version.
|
|
48
|
+
*
|
|
49
|
+
* A drop-in replacement for `node.getDescendantsOfKind(kind)`. Returns
|
|
50
|
+
* `readonly` because the array is shared: a caller that sorted or spliced it
|
|
51
|
+
* would corrupt every later matcher over the same body.
|
|
52
|
+
*/
|
|
53
|
+
export function descendantsOfKind(node, kind) {
|
|
54
|
+
const sourceFile = node.getSourceFile();
|
|
55
|
+
let perNode = byFile.get(sourceFile);
|
|
56
|
+
if (perNode === undefined) {
|
|
57
|
+
perNode = new Map();
|
|
58
|
+
byFile.set(sourceFile, perNode);
|
|
59
|
+
}
|
|
60
|
+
watchOnce(sourceFile);
|
|
61
|
+
let byKind = perNode.get(node);
|
|
62
|
+
if (byKind === undefined) {
|
|
63
|
+
byKind = new Map();
|
|
64
|
+
perNode.set(node, byKind);
|
|
65
|
+
}
|
|
66
|
+
const hit = byKind.get(kind);
|
|
67
|
+
// `usable`, not just `!== undefined`. A forget point forgets the walked
|
|
68
|
+
// DESCENDANTS while the key node stays live and unforgotten, so serving the
|
|
69
|
+
// cached list makes the next read throw where an uncached walk succeeded.
|
|
70
|
+
// Measured as a regression against `main`, through the rule path: 1 violation
|
|
71
|
+
// before, `InvalidOperationError` after. Re-walking is the correct answer —
|
|
72
|
+
// the nodes are gone, so the list is simply wrong.
|
|
73
|
+
if (hit !== undefined && usable(hit))
|
|
74
|
+
return hit;
|
|
75
|
+
const walked = node.getDescendantsOfKind(kind);
|
|
76
|
+
byKind.set(kind, walked);
|
|
77
|
+
return walked;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Every descendant of `node`, walked once per file version.
|
|
81
|
+
*
|
|
82
|
+
* The kind-independent twin of {@link descendantsOfKind}, for `findMatchesBroad`
|
|
83
|
+
* — the strategy `expression()` and `comment()` take, having no `syntaxKinds` to
|
|
84
|
+
* narrow by.
|
|
85
|
+
*
|
|
86
|
+
* **Measured** on this repository, 1,698 function bodies / 117,949 descendants,
|
|
87
|
+
* ts-morph's wrapper cache already warm:
|
|
88
|
+
*
|
|
89
|
+
* getDescendants() 49 ms <- what this removes
|
|
90
|
+
* + getText() on each 71 ms
|
|
91
|
+
* + regex test on each 68 ms
|
|
92
|
+
*
|
|
93
|
+
* The walk is roughly three quarters of a broad matcher's cost; the filter is the
|
|
94
|
+
* rest and is not shareable — `expression()`'s regex differs per matcher.
|
|
95
|
+
* (`comment()`'s dedup state was the other half of this until bug 0034 removed
|
|
96
|
+
* it; the filter is still per-matcher.) End to end, six successive broad
|
|
97
|
+
* rules over the same bodies: **~57 ms each becomes ~17 ms each.**
|
|
98
|
+
*
|
|
99
|
+
* The memory objection — that this retains every wrapper in every body rather
|
|
100
|
+
* than one kind's worth — does not survive checking. ts-morph's own
|
|
101
|
+
* `ForgetfulNodeCache` already holds every wrapper it creates for the lifetime of
|
|
102
|
+
* the `SourceFile`, so the array adds N references, not N objects.
|
|
103
|
+
*/
|
|
104
|
+
export function allDescendants(node) {
|
|
105
|
+
const sourceFile = node.getSourceFile();
|
|
106
|
+
let perNode = allByFile.get(sourceFile);
|
|
107
|
+
if (perNode === undefined) {
|
|
108
|
+
perNode = new Map();
|
|
109
|
+
allByFile.set(sourceFile, perNode);
|
|
110
|
+
}
|
|
111
|
+
watchOnce(sourceFile);
|
|
112
|
+
const hit = perNode.get(node);
|
|
113
|
+
if (hit !== undefined && usable(hit))
|
|
114
|
+
return hit;
|
|
115
|
+
const walked = node.getDescendants();
|
|
116
|
+
perNode.set(node, walked);
|
|
117
|
+
return walked;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=descendant-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"descendant-cache.js","sourceRoot":"","sources":["../../src/core/descendant-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import type { ArchProject } from './project.js';
|
|
2
|
+
import type { GlobPosition } from '@nielspeter/eess';
|
|
3
|
+
import type { GlobFault } from './glob-diagnosis.js';
|
|
4
|
+
import type { OnDisk } from './disk-set.js';
|
|
5
|
+
import type { RuleBuilderLike } from '@nielspeter/eess';
|
|
6
|
+
import type { GlobNode } from '@nielspeter/eess';
|
|
7
|
+
/**
|
|
8
|
+
* Anything `diagnose()` can inspect: a rule that can describe its globs.
|
|
9
|
+
*
|
|
10
|
+
* Structural rather than `TerminalBuilder`, so a caller can pass the same
|
|
11
|
+
* `RuleBuilderLike[]` array they already hand to `checkAll` without any
|
|
12
|
+
* of it being coupled to a class.
|
|
13
|
+
*/
|
|
14
|
+
export interface DiagnosableRule extends RuleBuilderLike {
|
|
15
|
+
globs?: () => readonly GlobNode[];
|
|
16
|
+
describeRule?: () => {
|
|
17
|
+
rule: string;
|
|
18
|
+
id?: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Whether this rule asserts anything about what it selected.
|
|
22
|
+
*
|
|
23
|
+
* A method rather than a look at `_conditions`: that field is protected, and
|
|
24
|
+
* reading it would need a type assertion (ADR-005) to duck-type a private
|
|
25
|
+
* name that no subclass is obliged to keep. Optional, because only the
|
|
26
|
+
* predicate/condition builders can be in the condition-less state at all —
|
|
27
|
+
* the rest take their condition as a constructor argument.
|
|
28
|
+
*/
|
|
29
|
+
assertsSomething?: () => boolean;
|
|
30
|
+
/**
|
|
31
|
+
* The remedy for this rule's assertion-less state. When present, `diagnose`
|
|
32
|
+
* reports it VERBATIM as the finding's advice, so the doctor and the
|
|
33
|
+
* configuration finding the gate raises at runtime carry the same string by
|
|
34
|
+
* construction (plan 0070) — they were measured diverging, and two texts for
|
|
35
|
+
* one state is a trust problem for an agent diffing them. Absent, the base
|
|
36
|
+
* `TerminalBuilder` text is used, from the one place that owns it.
|
|
37
|
+
*/
|
|
38
|
+
assertionAdvice?: () => string;
|
|
39
|
+
/** The project this rule was built against. */
|
|
40
|
+
getProject?: () => ArchProject | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* How many units this rule's family examined — plan 0096.
|
|
43
|
+
*
|
|
44
|
+
* PUBLIC because `DiagnosableRule` is structural: a protected member cannot
|
|
45
|
+
* satisfy it, which is the recorded reason `assertsSomething()` is public.
|
|
46
|
+
*
|
|
47
|
+
* The unit differs per family and each names its own (ADR-010 part 1), but
|
|
48
|
+
* every family answers it from the SAME method its `collectViolations()` uses
|
|
49
|
+
* — not a parallel derivation. A first attempt at this plan let the two
|
|
50
|
+
* diverge and they disagreed within one commit.
|
|
51
|
+
*
|
|
52
|
+
* Calling it RUNS that materialization. `diagnose()` and `doctor` used to
|
|
53
|
+
* promise they reported "without running any of them"; that sentence changed
|
|
54
|
+
* with this plan, in the docs as well as here.
|
|
55
|
+
*/
|
|
56
|
+
examinedUnits?: () => number;
|
|
57
|
+
/**
|
|
58
|
+
* Whether this rule's emptiness was DECLARED — plan 0097, read here by 0096.
|
|
59
|
+
*
|
|
60
|
+
* Public for the same structural reason as `assertsSomething()`. Without it
|
|
61
|
+
* the preview reports a finding on a rule the gate will accept, and tells the
|
|
62
|
+
* reader to do the thing they already did.
|
|
63
|
+
*/
|
|
64
|
+
declaresEmpty?: () => boolean;
|
|
65
|
+
/**
|
|
66
|
+
* This rule's own zero-subjects advice — plan 0099.
|
|
67
|
+
*
|
|
68
|
+
* When present, reported VERBATIM, exactly as `assertionAdvice()` is and for
|
|
69
|
+
* the identical reason plan 0070 recorded: the doctor and the finding the gate
|
|
70
|
+
* raises must carry the same string **by construction**, because two texts for
|
|
71
|
+
* one state is a trust problem for an agent diffing them.
|
|
72
|
+
*
|
|
73
|
+
* Measured before this seam existed: `check()` said "a declaration is an
|
|
74
|
+
* assertion, not a silencer" while `doctor` still said "the declaration is not
|
|
75
|
+
* itself checked yet ... A later release makes this state fail at check time" —
|
|
76
|
+
* in the release that makes it fail, on the surface ts-archunit's `docs/upgrading.md` tells
|
|
77
|
+
* people to run first.
|
|
78
|
+
*/
|
|
79
|
+
zeroSubjectsAdvice?: () => string;
|
|
80
|
+
/**
|
|
81
|
+
* How this family spells the declaration. Absent means the generic
|
|
82
|
+
* `.expectEmpty()`, which is a `TypeError` on `crossProject` — see
|
|
83
|
+
* `TerminalBuilder.emptyDeclarationAdvice()`.
|
|
84
|
+
*/
|
|
85
|
+
emptyDeclarationAdvice?: () => string;
|
|
86
|
+
/**
|
|
87
|
+
* Whether a condition on this rule declares emptiness as its PASSING state —
|
|
88
|
+
* `.notExist()` and friends. Zero examined is the assertion succeeding, so the
|
|
89
|
+
* evidence check must not report it. See `TerminalBuilder.assertsCardinality()`
|
|
90
|
+
* for why this is separate from `declaresEmpty()`.
|
|
91
|
+
*/
|
|
92
|
+
assertsCardinality?: () => boolean;
|
|
93
|
+
/**
|
|
94
|
+
* This rule's own adequacy advice — plan 0102.
|
|
95
|
+
*
|
|
96
|
+
* Distinct from `zeroSubjectsAdvice`: that covers `examinedUnits() === 0`.
|
|
97
|
+
* This covers a rule whose evidence is non-empty but which is structurally
|
|
98
|
+
* unable to ever produce a finding as configured (bug 0077(A) — a
|
|
99
|
+
* divergence-policing detector on a majority-less corpus). Returns the empty
|
|
100
|
+
* string for any rule that is not inert, so `diagnose()` reports nothing for
|
|
101
|
+
* a healthy control. Reported VERBATIM, exactly as `zeroSubjectsAdvice` is,
|
|
102
|
+
* for the same plan-0070 reason: the preview and the check-time finding must
|
|
103
|
+
* carry the same string by construction, not two texts for one state.
|
|
104
|
+
*/
|
|
105
|
+
inertAdvice?: () => string;
|
|
106
|
+
/**
|
|
107
|
+
* This rule's own deferred-warning advice — plan 0090.
|
|
108
|
+
*
|
|
109
|
+
* A DEFERRED warning (`.asSeverity('warn', { accepted })`) stays `warn` only
|
|
110
|
+
* for violations whose subject is in `accepted`; this reports when a CURRENT
|
|
111
|
+
* violation is not — the exact regression an accepted list exists to catch.
|
|
112
|
+
* Returns `''` for an advisory warning, for a rule at `'error'` severity, and
|
|
113
|
+
* for a deferred warning whose findings are all still accepted, matching
|
|
114
|
+
* `inertAdvice`/`zeroSubjectsAdvice`'s own precedent: reported VERBATIM, so
|
|
115
|
+
* `doctor`'s preview and `checkAll()`/CLI `check`'s eventual failure carry the
|
|
116
|
+
* same string by construction.
|
|
117
|
+
*/
|
|
118
|
+
deferredWarningAdvice?: () => string;
|
|
119
|
+
}
|
|
120
|
+
/** One thing wrong with one rule, named specifically enough to fix. */
|
|
121
|
+
export interface DiagnosticFinding {
|
|
122
|
+
/**
|
|
123
|
+
* `'project-empty'` — the project loaded no files, so nothing can match and
|
|
124
|
+
* the globs are not the fault (bug 0031); `'dead-glob'` — a glob that can
|
|
125
|
+
* never match; `'no-condition'` — a rule
|
|
126
|
+
* that asserts nothing; `'project-unknown'` — a rule whose globs could not
|
|
127
|
+
* be checked because it cannot name the project it was built against.
|
|
128
|
+
*/
|
|
129
|
+
readonly kind: 'dead-glob' | 'no-condition' | 'project-unknown' | 'project-empty'
|
|
130
|
+
/**
|
|
131
|
+
* A rule that examined **zero units** while its project loaded files, and
|
|
132
|
+
* for which nothing else explained the emptiness — plan 0096.
|
|
133
|
+
*
|
|
134
|
+
* The preview for plan 0098, which makes the same state FAIL. Distinct from
|
|
135
|
+
* `'project-empty'` (the instrument loaded nothing) and from `'dead-glob'`
|
|
136
|
+
* (a glob the author wrote matches nothing): this is the family's OWN
|
|
137
|
+
* filters removing everything, including defaults the author never wrote.
|
|
138
|
+
*
|
|
139
|
+
* It lands in `diagnose()` rather than in `doctor` so that a rule file
|
|
140
|
+
* importing a test runner — which `doctor` cannot load, ADR-009 rule 1's
|
|
141
|
+
* corollary — still gets a preview: `expect(diagnose(rules)).toEqual([])`
|
|
142
|
+
* runs inside the consumer's own suite.
|
|
143
|
+
*/
|
|
144
|
+
| 'zero-subjects'
|
|
145
|
+
/**
|
|
146
|
+
* A rule whose evidence is non-empty but which is structurally unable to
|
|
147
|
+
* ever produce a finding as configured — plan 0102. Distinct from
|
|
148
|
+
* `'zero-subjects'`: that fires when `examinedUnits() === 0`; this fires
|
|
149
|
+
* when `examinedUnits() > 0` but the family's own adequacy predicate
|
|
150
|
+
* (`inertAdvice?()`) says the rule can never fail regardless. ADR-009's
|
|
151
|
+
* Notes hand this class to ADR-008 explicitly: "a check can examine 500
|
|
152
|
+
* subjects and still assert nothing worth knowing."
|
|
153
|
+
*/
|
|
154
|
+
| 'inert'
|
|
155
|
+
/**
|
|
156
|
+
* An inline `// eess-exclude` comment naming a rule id no rule
|
|
157
|
+
* declares, so it suppresses nothing — [ts-archunit bug 0044](https://github.com/nielspeter/ts-archunit/blob/main/bugs/fixed/0044-an-inline-exclusion-comment-has-no-feedback-channel.md).
|
|
158
|
+
*
|
|
159
|
+
* Produced by `orphanExclusions()`, never by `diagnose()`: it needs every
|
|
160
|
+
* rule at once, and `diagnose()` is called per rule file.
|
|
161
|
+
*/
|
|
162
|
+
| 'orphan-exclusion'
|
|
163
|
+
/**
|
|
164
|
+
* A DEFERRED warning (`.asSeverity('warn', { accepted })`) whose current
|
|
165
|
+
* findings are not all covered by `accepted` — plan 0090. The preview for
|
|
166
|
+
* the escalation `.violations()`/`checkAll()`/CLI `check` already apply: one
|
|
167
|
+
* of those findings will report at `error` severity the moment this rule
|
|
168
|
+
* runs. Distinct from `'inert'` and `'zero-subjects'`, which are about
|
|
169
|
+
* whether a rule can ever fail; this is about a rule that already fails,
|
|
170
|
+
* previewed before the run that discovers it does.
|
|
171
|
+
*/
|
|
172
|
+
| 'deferred-warning';
|
|
173
|
+
/** The rule's id if it has one, else its assembled description. */
|
|
174
|
+
readonly rule: string;
|
|
175
|
+
/** Where the glob was written: `resideInFolder("**\/src/x/**")`. */
|
|
176
|
+
readonly origin?: string;
|
|
177
|
+
readonly glob?: string;
|
|
178
|
+
readonly position?: GlobPosition;
|
|
179
|
+
readonly fault?: GlobFault;
|
|
180
|
+
readonly onDisk?: OnDisk;
|
|
181
|
+
/** The sanctioned fix, or an honest list of causes where none is verifiable. */
|
|
182
|
+
readonly advice: string;
|
|
183
|
+
/**
|
|
184
|
+
* For `'orphan-exclusion'`, the line the comment sits on.
|
|
185
|
+
*/
|
|
186
|
+
readonly line?: number;
|
|
187
|
+
/**
|
|
188
|
+
* For `'orphan-exclusion'`, the **source** file holding the comment.
|
|
189
|
+
*
|
|
190
|
+
* Distinct from `ruleFile`, which names where a *rule* was written. An earlier
|
|
191
|
+
* revision reused `ruleFile` for this and gave JSON consumers two different
|
|
192
|
+
* things under one name depending on `kind`.
|
|
193
|
+
*/
|
|
194
|
+
readonly sourceFile?: string;
|
|
195
|
+
/**
|
|
196
|
+
* The rule file this rule was written in, when the caller knows it.
|
|
197
|
+
*
|
|
198
|
+
* `diagnose()` never sets this — it is handed rules, not files, and inventing
|
|
199
|
+
* a path it cannot verify is the thing this library exists to stop. `doctor`
|
|
200
|
+
* sets it, because its loop over rule files is the only place the mapping
|
|
201
|
+
* exists (bug 0026: `docs/cli.md` claimed identities "in which rule" and that
|
|
202
|
+
* was true of a dead glob's position and false of every `no-condition`
|
|
203
|
+
* finding, whose only identity was a prose sentence).
|
|
204
|
+
*/
|
|
205
|
+
readonly ruleFile?: string;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Report what each rule cannot enforce, without evaluating their conditions.
|
|
209
|
+
*
|
|
210
|
+
* It DOES materialize each rule's selection, as of plan 0096 — "this rule
|
|
211
|
+
* examined nothing" is a fact about the selection. The docstring said "without
|
|
212
|
+
* running any of them" and that stopped being true; it is the IDE-hover contract
|
|
213
|
+
* for an exported function, so it is corrected here and not only in `docs/`.
|
|
214
|
+
*
|
|
215
|
+
* As of plan 0102, one family's `inertAdvice?()` goes further than selection:
|
|
216
|
+
* `inconsistentSiblings` walks every sibling body's AST to answer it (the same
|
|
217
|
+
* work `check()` does), so for that one family this IS evaluating the
|
|
218
|
+
* condition, not just counting what would be handed to it (review: architect).
|
|
219
|
+
* Still no `Condition.evaluate()` call — the boundary this docstring's
|
|
220
|
+
* predecessor drew — but "without evaluating" is no longer exactly right for
|
|
221
|
+
* every family, and is corrected here rather than left for the next reader to
|
|
222
|
+
* discover by profiling `doctor`.
|
|
223
|
+
*
|
|
224
|
+
* The in-process half of `doctor`. It exists because rules written inside
|
|
225
|
+
* vitest are a co-equal documented path (`docs/running-in-tests.md`), and a
|
|
226
|
+
* CLI-only diagnostic would leave half the users unable to measure before R3
|
|
227
|
+
* flips anything — which is the one job R2a has.
|
|
228
|
+
*
|
|
229
|
+
* Reports **identities, never totals**: which glob, in which rule, at which
|
|
230
|
+
* position. A count is a snapshot, and under ADR-009 rule 4 a snapshot is the
|
|
231
|
+
* thing that rots. Callers who want a number can take `.length`.
|
|
232
|
+
*/
|
|
233
|
+
export declare function diagnose(rules: readonly DiagnosableRule[], project?: ArchProject): DiagnosticFinding[];
|
|
234
|
+
//# sourceMappingURL=diagnose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnose.d.ts","sourceRoot":"","sources":["../../src/core/diagnose.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,kBAAkB,CAAA;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAO3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAGhD;;;;;;GAMG;AACH,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,KAAK,CAAC,EAAE,MAAM,SAAS,QAAQ,EAAE,CAAA;IACjC,YAAY,CAAC,EAAE,MAAM;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAClD;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,MAAM,OAAO,CAAA;IAChC;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,MAAM,MAAM,CAAA;IAC9B,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,WAAW,GAAG,SAAS,CAAA;IAC1C;;;;;;;;;;;;;;OAcG;IACH,aAAa,CAAC,EAAE,MAAM,MAAM,CAAA;IAC5B;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,OAAO,CAAA;IAE7B;;;;;;;;;;;;;OAaG;IACH,kBAAkB,CAAC,EAAE,MAAM,MAAM,CAAA;IAEjC;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,MAAM,MAAM,CAAA;IAErC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAA;IAElC;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,EAAE,MAAM,MAAM,CAAA;IAE1B;;;;;;;;;;;OAWG;IACH,qBAAqB,CAAC,EAAE,MAAM,MAAM,CAAA;CACrC;AAED,uEAAuE;AACvE,MAAM,WAAW,iBAAiB;IAChC;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EACT,WAAW,GACX,cAAc,GACd,iBAAiB,GACjB,eAAe;IACjB;;;;;;;;;;;;;OAaG;OACD,eAAe;IACjB;;;;;;;;OAQG;OACD,OAAO;IACT;;;;;;OAMG;OACD,kBAAkB;IACpB;;;;;;;;OAQG;OACD,kBAAkB,CAAA;IACtB,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,oEAAoE;IACpE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAA;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,gFAAgF;IAChF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;;;;;;OASG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,SAAS,eAAe,EAAE,EACjC,OAAO,CAAC,EAAE,WAAW,GACpB,iBAAiB,EAAE,CA2MrB"}
|