@nielspeter/eess 0.2.2 → 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 +97 -4
- package/dist/assertion-advice.d.ts +26 -0
- package/dist/assertion-advice.d.ts.map +1 -0
- package/dist/assertion-advice.js +29 -0
- package/dist/assertion-advice.js.map +1 -0
- package/dist/baseline-generator.d.ts +9 -0
- package/dist/baseline-generator.d.ts.map +1 -1
- package/dist/baseline-generator.js +9 -0
- package/dist/baseline-generator.js.map +1 -1
- package/dist/baseline.d.ts +69 -4
- package/dist/baseline.d.ts.map +1 -1
- package/dist/baseline.js +119 -13
- package/dist/baseline.js.map +1 -1
- package/dist/cache-registry.d.ts +14 -0
- package/dist/cache-registry.d.ts.map +1 -0
- package/dist/cache-registry.js +37 -0
- package/dist/cache-registry.js.map +1 -0
- package/dist/cardinality.d.ts +35 -0
- package/dist/cardinality.d.ts.map +1 -0
- package/dist/cardinality.js +80 -0
- package/dist/cardinality.js.map +1 -0
- package/dist/check-options.d.ts +14 -0
- package/dist/check-options.d.ts.map +1 -1
- package/dist/cli-config.d.ts +59 -0
- package/dist/cli-config.d.ts.map +1 -0
- package/dist/cli-config.js +84 -0
- package/dist/cli-config.js.map +1 -0
- package/dist/collect-result.d.ts +94 -0
- package/dist/collect-result.d.ts.map +1 -0
- package/dist/collect-result.js +142 -0
- package/dist/collect-result.js.map +1 -0
- package/dist/combinators.d.ts +14 -0
- package/dist/combinators.d.ts.map +1 -1
- package/dist/combinators.js +53 -16
- package/dist/combinators.js.map +1 -1
- package/dist/comment-suppression.d.ts +60 -0
- package/dist/comment-suppression.d.ts.map +1 -0
- package/dist/comment-suppression.js +89 -0
- package/dist/comment-suppression.js.map +1 -0
- package/dist/condition.d.ts +43 -0
- package/dist/condition.d.ts.map +1 -1
- package/dist/condition.js +48 -1
- package/dist/condition.js.map +1 -1
- package/dist/correspondence-core.d.ts +35 -0
- package/dist/correspondence-core.d.ts.map +1 -0
- package/dist/correspondence-core.js +38 -0
- package/dist/correspondence-core.js.map +1 -0
- package/dist/correspondence.d.ts +57 -5
- package/dist/correspondence.d.ts.map +1 -1
- package/dist/correspondence.js +74 -5
- package/dist/correspondence.js.map +1 -1
- package/dist/dedupe-config-findings.d.ts +56 -0
- package/dist/dedupe-config-findings.d.ts.map +1 -0
- package/dist/dedupe-config-findings.js +101 -0
- package/dist/dedupe-config-findings.js.map +1 -0
- package/dist/define.d.ts +44 -2
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js +45 -4
- package/dist/define.js.map +1 -1
- package/dist/diff-aware.d.ts +8 -1
- package/dist/diff-aware.d.ts.map +1 -1
- package/dist/diff-aware.js +39 -9
- package/dist/diff-aware.js.map +1 -1
- package/dist/diff-disclosure.d.ts +72 -0
- package/dist/diff-disclosure.d.ts.map +1 -0
- package/dist/diff-disclosure.js +110 -0
- package/dist/diff-disclosure.js.map +1 -0
- package/dist/disk-set.d.ts +27 -0
- package/dist/disk-set.d.ts.map +1 -0
- package/dist/disk-set.js +12 -0
- package/dist/disk-set.js.map +1 -0
- package/dist/edge-coverage.d.ts +96 -0
- package/dist/edge-coverage.d.ts.map +1 -0
- package/dist/edge-coverage.js +108 -0
- package/dist/edge-coverage.js.map +1 -0
- package/dist/emitter-findings.d.ts +167 -0
- package/dist/emitter-findings.d.ts.map +1 -0
- package/dist/emitter-findings.js +237 -0
- package/dist/emitter-findings.js.map +1 -0
- package/dist/errors.d.ts +73 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +93 -0
- package/dist/errors.js.map +1 -1
- package/dist/exclusion-comments.d.ts +36 -1
- package/dist/exclusion-comments.d.ts.map +1 -1
- package/dist/exclusion-comments.js +185 -37
- package/dist/exclusion-comments.js.map +1 -1
- package/dist/execute-rule.d.ts +11 -1
- package/dist/execute-rule.d.ts.map +1 -1
- package/dist/execute-rule.js +220 -11
- package/dist/execute-rule.js.map +1 -1
- package/dist/file-walk.d.ts +22 -0
- package/dist/file-walk.d.ts.map +1 -0
- package/dist/file-walk.js +51 -0
- package/dist/file-walk.js.map +1 -0
- package/dist/format-github.d.ts.map +1 -1
- package/dist/format-github.js +37 -5
- package/dist/format-github.js.map +1 -1
- package/dist/format-json.d.ts +96 -1
- package/dist/format-json.d.ts.map +1 -1
- package/dist/format-json.js +94 -9
- package/dist/format-json.js.map +1 -1
- package/dist/format.d.ts +4 -2
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +41 -19
- package/dist/format.js.map +1 -1
- package/dist/glob-site.d.ts +232 -0
- package/dist/glob-site.d.ts.map +1 -0
- package/dist/glob-site.js +156 -0
- package/dist/glob-site.js.map +1 -0
- package/dist/identity-root.d.ts +55 -0
- package/dist/identity-root.d.ts.map +1 -0
- package/dist/identity-root.js +170 -0
- package/dist/identity-root.js.map +1 -0
- package/dist/index.d.ts +18 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -10
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +55 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +92 -0
- package/dist/internal.js.map +1 -0
- package/dist/mask-non-comment.d.ts +49 -0
- package/dist/mask-non-comment.d.ts.map +1 -0
- package/dist/mask-non-comment.js +261 -0
- package/dist/mask-non-comment.js.map +1 -0
- package/dist/owns-empty-discovery.d.ts +5 -0
- package/dist/owns-empty-discovery.d.ts.map +1 -0
- package/dist/owns-empty-discovery.js +85 -0
- package/dist/owns-empty-discovery.js.map +1 -0
- package/dist/path-suffix.d.ts +57 -0
- package/dist/path-suffix.d.ts.map +1 -0
- package/dist/path-suffix.js +73 -0
- package/dist/path-suffix.js.map +1 -0
- package/dist/path-universe.d.ts +44 -0
- package/dist/path-universe.d.ts.map +1 -0
- package/dist/path-universe.js +21 -0
- package/dist/path-universe.js.map +1 -0
- package/dist/predicate.d.ts +45 -0
- package/dist/predicate.d.ts.map +1 -1
- package/dist/predicate.js +20 -1
- package/dist/predicate.js.map +1 -1
- package/dist/preset-dispatch.d.ts +6 -15
- package/dist/preset-dispatch.d.ts.map +1 -1
- package/dist/preset-dispatch.js +35 -17
- package/dist/preset-dispatch.js.map +1 -1
- package/dist/project-relative.d.ts +25 -0
- package/dist/project-relative.d.ts.map +1 -0
- package/dist/project-relative.js +54 -0
- package/dist/project-relative.js.map +1 -0
- package/dist/report.d.ts +42 -12
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +190 -14
- package/dist/report.js.map +1 -1
- package/dist/rule-builder-like.d.ts +17 -0
- package/dist/rule-builder-like.d.ts.map +1 -0
- package/dist/rule-builder-like.js +2 -0
- package/dist/rule-builder-like.js.map +1 -0
- package/dist/rule-builder.d.ts +124 -84
- package/dist/rule-builder.d.ts.map +1 -1
- package/dist/rule-builder.js +230 -181
- package/dist/rule-builder.js.map +1 -1
- package/dist/rule-description.d.ts +83 -1
- package/dist/rule-description.d.ts.map +1 -1
- package/dist/rule-description.js +75 -1
- package/dist/rule-description.js.map +1 -1
- package/dist/rule-metadata.d.ts +20 -3
- package/dist/rule-metadata.d.ts.map +1 -1
- package/dist/selection-memo.d.ts +45 -0
- package/dist/selection-memo.d.ts.map +1 -0
- package/dist/selection-memo.js +66 -0
- package/dist/selection-memo.js.map +1 -0
- package/dist/shallow-clone.d.ts +20 -0
- package/dist/shallow-clone.d.ts.map +1 -0
- package/dist/shallow-clone.js +27 -0
- package/dist/shallow-clone.js.map +1 -0
- package/dist/silent-exclusion.d.ts +12 -0
- package/dist/silent-exclusion.d.ts.map +1 -1
- package/dist/silent-exclusion.js +22 -0
- package/dist/silent-exclusion.js.map +1 -1
- package/dist/stderr.d.ts +16 -0
- package/dist/stderr.d.ts.map +1 -0
- package/dist/stderr.js +73 -0
- package/dist/stderr.js.map +1 -0
- package/dist/terminal-builder.d.ts +224 -10
- package/dist/terminal-builder.d.ts.map +1 -1
- package/dist/terminal-builder.js +336 -46
- package/dist/terminal-builder.js.map +1 -1
- package/dist/type-guards.d.ts +38 -0
- package/dist/type-guards.d.ts.map +1 -0
- package/dist/type-guards.js +42 -0
- package/dist/type-guards.js.map +1 -0
- package/dist/unsuppressable.d.ts +54 -0
- package/dist/unsuppressable.d.ts.map +1 -0
- package/dist/unsuppressable.js +76 -0
- package/dist/unsuppressable.js.map +1 -0
- package/dist/vacuity-findings.d.ts +49 -0
- package/dist/vacuity-findings.d.ts.map +1 -0
- package/dist/vacuity-findings.js +94 -0
- package/dist/vacuity-findings.js.map +1 -0
- package/dist/violation.d.ts +173 -4
- package/dist/violation.d.ts.map +1 -1
- package/dist/violation.js +262 -1
- package/dist/violation.js.map +1 -1
- package/dist/watch.d.ts +71 -0
- package/dist/watch.d.ts.map +1 -0
- package/dist/watch.js +129 -0
- package/dist/watch.js.map +1 -0
- package/package.json +6 -1
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a cited path against a set of repo-relative paths.
|
|
3
|
+
*
|
|
4
|
+
* Two dialects had written this independently — `eess-md`'s `uniqueSuffix()`
|
|
5
|
+
* for `path:line` code pointers, and `eess-crossvalidate`'s `resolveFeature`
|
|
6
|
+
* for `.feature` citations. Same algorithm, same three-way answer, and after
|
|
7
|
+
* bug 0254 the same remedy text; bug 0257 is that duplication.
|
|
8
|
+
*
|
|
9
|
+
* **Why the kernel.** It is pure string work over a list of paths: no
|
|
10
|
+
* `ArchProject`, no ts-morph, nothing dialect-shaped. That is exactly
|
|
11
|
+
* `path-universe.ts`'s argument for living here, and
|
|
12
|
+
* [ADR-013](../../../adr/013-the-kernel-takes-the-fact-not-the-project.md)'s
|
|
13
|
+
* test is satisfied — the kernel takes the *fact* (a list of paths), not the
|
|
14
|
+
* project that produced it. It is family plumbing rather than public API, so it
|
|
15
|
+
* is exported from `internal.ts` (ADR-011).
|
|
16
|
+
*
|
|
17
|
+
* **What it deliberately does not decide.** Whether a `none` is broken, whether
|
|
18
|
+
* an `ambiguous` fails or warns, whether to consult external roots, what the
|
|
19
|
+
* message says — all of that is the caller's policy and differs between the two
|
|
20
|
+
* dialects for good reasons. This answers one question: *which path did they
|
|
21
|
+
* mean?*
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Prepare a path set for repeated suffix lookups.
|
|
25
|
+
*
|
|
26
|
+
* Indexed by last segment, because the corpora this runs over resolve hundreds
|
|
27
|
+
* of citations against thousands of paths and a linear scan per citation was
|
|
28
|
+
* measurable in `eess-md`. The index is the reason this takes the whole set up
|
|
29
|
+
* front rather than being a plain two-argument function.
|
|
30
|
+
*/
|
|
31
|
+
export function pathSuffixIndex(paths) {
|
|
32
|
+
// Deduplicated on entry, not assumed deduplicated. `all` was always a `Set`,
|
|
33
|
+
// but the per-segment lists used to push every element of the iterable — so a
|
|
34
|
+
// path appearing twice came back as `{ kind: 'ambiguous', files: [x, x] }`:
|
|
35
|
+
// one file reported as ambiguous with itself. Unreachable through today's two
|
|
36
|
+
// callers (both hand it a set or a filesystem walk), which is exactly why it
|
|
37
|
+
// would have waited for the third — the parameter is an `Iterable<string>`
|
|
38
|
+
// and nothing in the type says the caller must have deduplicated. Found by
|
|
39
|
+
// differential fuzzing across 20,000 cases; it was the only class of
|
|
40
|
+
// disagreement with the implementations this replaced.
|
|
41
|
+
const all = new Set(paths);
|
|
42
|
+
const byLastSegment = new Map();
|
|
43
|
+
for (const rel of all) {
|
|
44
|
+
const seg = rel.slice(rel.lastIndexOf('/') + 1);
|
|
45
|
+
const list = byLastSegment.get(seg);
|
|
46
|
+
if (list)
|
|
47
|
+
list.push(rel);
|
|
48
|
+
else
|
|
49
|
+
byLastSegment.set(seg, [rel]);
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
resolve(wanted) {
|
|
53
|
+
// Exact first, and it wins outright. A citation that IS a real path is not
|
|
54
|
+
// ambiguous just because some longer path happens to end the same way —
|
|
55
|
+
// both dialects had this precedence already, and getting it backwards
|
|
56
|
+
// would turn correct citations into findings.
|
|
57
|
+
if (all.has(wanted))
|
|
58
|
+
return { kind: 'exact', file: wanted };
|
|
59
|
+
const seg = wanted.slice(wanted.lastIndexOf('/') + 1);
|
|
60
|
+
// Narrow by last segment, then confirm the FULL suffix on a `/` boundary:
|
|
61
|
+
// `x.ts` must not match `prefix-x.ts`, and `a/x.ts` must not match
|
|
62
|
+
// `b/aa/x.ts`.
|
|
63
|
+
const matches = (byLastSegment.get(seg) ?? []).filter((f) => f.endsWith('/' + wanted));
|
|
64
|
+
const only = matches[0];
|
|
65
|
+
if (matches.length === 1 && only !== undefined)
|
|
66
|
+
return { kind: 'unique', file: only };
|
|
67
|
+
if (matches.length > 1)
|
|
68
|
+
return { kind: 'ambiguous', files: matches };
|
|
69
|
+
return { kind: 'none' };
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=path-suffix.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-suffix.js","sourceRoot":"","sources":["../src/path-suffix.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAkBH;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,KAAuB;IACrD,6EAA6E;IAC7E,8EAA8E;IAC9E,4EAA4E;IAC5E,8EAA8E;IAC9E,6EAA6E;IAC7E,2EAA2E;IAC3E,2EAA2E;IAC3E,qEAAqE;IACrE,uDAAuD;IACvD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAS,KAAK,CAAC,CAAA;IAClC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAoB,CAAA;IACjD,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;QAC/C,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACnC,IAAI,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;;YACnB,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;IACpC,CAAC;IAED,OAAO;QACL,OAAO,CAAC,MAAc;YACpB,2EAA2E;YAC3E,wEAAwE;YACxE,sEAAsE;YACtE,8CAA8C;YAC9C,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;YAE3D,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;YACrD,0EAA0E;YAC1E,mEAAmE;YACnE,eAAe;YACf,MAAM,OAAO,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,GAAG,MAAM,CAAC,CAAC,CAAA;YACtF,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;YACvB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;YACrF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA;YACpE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;QACzB,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every path a glob could legitimately match in a project — the shape of the
|
|
3
|
+
* data, not how to build it.
|
|
4
|
+
*
|
|
5
|
+
* `PathUniverse` and `viewsFor` are pure: given the materialized string
|
|
6
|
+
* arrays, they need no `ArchProject`/ts-morph and stay in the kernel. Only
|
|
7
|
+
* the MATERIALIZER — walking a real project's source files into this shape —
|
|
8
|
+
* needs the dialect's own project type, and lives in that dialect (e.g.
|
|
9
|
+
* `packages/ts/src/core/path-universe.ts`'s `pathUniverse()`).
|
|
10
|
+
*/
|
|
11
|
+
export interface PathUniverse {
|
|
12
|
+
/** Absolute paths of every file in the project. */
|
|
13
|
+
readonly filePaths: readonly string[];
|
|
14
|
+
/**
|
|
15
|
+
* Immediate parent directories only.
|
|
16
|
+
*
|
|
17
|
+
* Not all ancestors. A directory-matching predicate typically tests
|
|
18
|
+
* `filePath.substring(0, filePath.lastIndexOf('/'))` — the immediate
|
|
19
|
+
* parent and nothing else — so an all-ancestors set is not a harmless
|
|
20
|
+
* over-approximation, it is a false green: many ancestors are no file's
|
|
21
|
+
* direct parent, so a glob naming one of those can never select anything
|
|
22
|
+
* while an all-ancestors universe would call it satisfiable.
|
|
23
|
+
*/
|
|
24
|
+
readonly parentDirs: readonly string[];
|
|
25
|
+
/** `filePaths` relative to the tsconfig directory, for message wording. */
|
|
26
|
+
readonly tsconfigRelativeFilePaths: readonly string[];
|
|
27
|
+
/** `parentDirs` relative to the tsconfig directory, for message wording. */
|
|
28
|
+
readonly tsconfigRelativeParentDirs: readonly string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The views a glob of this kind is matched against.
|
|
32
|
+
*
|
|
33
|
+
* Satisfiability is taken against the **union** — a glob is unsatisfiable
|
|
34
|
+
* only when nothing in any view matches it. That is deliberately generous,
|
|
35
|
+
* so that a wrong `base` cannot make a glob look unmatched by accident. It
|
|
36
|
+
* does NOT make `base` message-only: the anchor check in `syntacticFault`
|
|
37
|
+
* consults it directly, and an unanchored `base: 'absolute'` glob is dead
|
|
38
|
+
* regardless of what any view holds — see `GlobBase`.
|
|
39
|
+
*
|
|
40
|
+
* `import-target`, `specifier` and `literal` are not path kinds and have no
|
|
41
|
+
* views, so they can never be found unsatisfiable here.
|
|
42
|
+
*/
|
|
43
|
+
export declare function viewsFor(universe: PathUniverse, kind: 'file-path' | 'parent-dir' | 'import-target' | 'specifier' | 'literal'): readonly (readonly string[])[];
|
|
44
|
+
//# sourceMappingURL=path-universe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-universe.d.ts","sourceRoot":"","sources":["../src/path-universe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAY;IAC3B,mDAAmD;IACnD,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC;;;;;;;;;OASG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;IACtC,2EAA2E;IAC3E,QAAQ,CAAC,yBAAyB,EAAE,SAAS,MAAM,EAAE,CAAA;IACrD,4EAA4E;IAC5E,QAAQ,CAAC,0BAA0B,EAAE,SAAS,MAAM,EAAE,CAAA;CACvD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,WAAW,GAAG,YAAY,GAAG,eAAe,GAAG,WAAW,GAAG,SAAS,GAC3E,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAIhC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The views a glob of this kind is matched against.
|
|
3
|
+
*
|
|
4
|
+
* Satisfiability is taken against the **union** — a glob is unsatisfiable
|
|
5
|
+
* only when nothing in any view matches it. That is deliberately generous,
|
|
6
|
+
* so that a wrong `base` cannot make a glob look unmatched by accident. It
|
|
7
|
+
* does NOT make `base` message-only: the anchor check in `syntacticFault`
|
|
8
|
+
* consults it directly, and an unanchored `base: 'absolute'` glob is dead
|
|
9
|
+
* regardless of what any view holds — see `GlobBase`.
|
|
10
|
+
*
|
|
11
|
+
* `import-target`, `specifier` and `literal` are not path kinds and have no
|
|
12
|
+
* views, so they can never be found unsatisfiable here.
|
|
13
|
+
*/
|
|
14
|
+
export function viewsFor(universe, kind) {
|
|
15
|
+
if (kind === 'file-path')
|
|
16
|
+
return [universe.filePaths, universe.tsconfigRelativeFilePaths];
|
|
17
|
+
if (kind === 'parent-dir')
|
|
18
|
+
return [universe.parentDirs, universe.tsconfigRelativeParentDirs];
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=path-universe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-universe.js","sourceRoot":"","sources":["../src/path-universe.ts"],"names":[],"mappings":"AA8BA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,QAAQ,CACtB,QAAsB,EACtB,IAA4E;IAE5E,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,yBAAyB,CAAC,CAAA;IACzF,IAAI,IAAI,KAAK,YAAY;QAAE,OAAO,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,0BAA0B,CAAC,CAAA;IAC5F,OAAO,EAAE,CAAA;AACX,CAAC"}
|
package/dist/predicate.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DeclaredGlobs } from './glob-site.js';
|
|
1
2
|
/**
|
|
2
3
|
* A predicate that tests whether an architectural element matches a condition.
|
|
3
4
|
* Used in `.that()` clauses to filter elements before rule evaluation.
|
|
@@ -7,5 +8,49 @@ export interface Predicate<T> {
|
|
|
7
8
|
readonly description: string;
|
|
8
9
|
/** Returns true if the element matches this predicate. */
|
|
9
10
|
test(element: T): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* The path globs this predicate matches against, if any.
|
|
13
|
+
*
|
|
14
|
+
* Declaring them lets the builder answer "can this rule ever have subjects?"
|
|
15
|
+
* without running it (plan 0069). Optional: a predicate that matches on
|
|
16
|
+
* something other than a path — a name, a decorator, a type — declares
|
|
17
|
+
* nothing and is treated as opaque, which is never a fault.
|
|
18
|
+
*
|
|
19
|
+
* Leaves are `DeclaredGlob`, so a predicate cannot claim a `position`; the
|
|
20
|
+
* builder stamps that on according to where the predicate was registered.
|
|
21
|
+
*/
|
|
22
|
+
readonly globs?: DeclaredGlobs;
|
|
23
|
+
/**
|
|
24
|
+
* What to call this predicate's globs in a **configuration finding**, when
|
|
25
|
+
* the call the user made is not the call the predicate makes.
|
|
26
|
+
*
|
|
27
|
+
* Plan 0074, the second consequence of 0069's appendix item 4: presets must
|
|
28
|
+
* thread the option name into the site's origin (`shared: "…"`, not
|
|
29
|
+
* `resideInFolder("…")`), or the message names a call the user never made.
|
|
30
|
+
*
|
|
31
|
+
* A preset option is one name that expands to several predicates —
|
|
32
|
+
* `shared: ['…']` becomes `atPath()`, which is `or(resideInFile,
|
|
33
|
+
* resideInFolder)`. Measured before this existed, the finding read "This
|
|
34
|
+
* rule's selector reside in file matching … or reside in folder matching …
|
|
35
|
+
* can never match anything", naming two calls the author never wrote and
|
|
36
|
+
* omitting the option they did.
|
|
37
|
+
*
|
|
38
|
+
* Deliberately **not** `description`, which is overloaded: that renders the
|
|
39
|
+
* human-readable rule text, and rewriting it would change every violation
|
|
40
|
+
* message the preset produces, not just the configuration finding.
|
|
41
|
+
*/
|
|
42
|
+
readonly originLabel?: string;
|
|
10
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Record a predicate on a builder, noting it if it arrived after `.should()`.
|
|
46
|
+
*
|
|
47
|
+
* A free function for the same reason as `recordExclusions` and
|
|
48
|
+
* `selectMatching`: the two builders sit in incompatible hierarchies, so there
|
|
49
|
+
* is no common base to hold a method. The copies were 94% similar and differed
|
|
50
|
+
* only in comment wording and braces — no behaviour.
|
|
51
|
+
*
|
|
52
|
+
* `phase` is read, never written: recording a misplaced predicate is a
|
|
53
|
+
* diagnosis, not a state change.
|
|
54
|
+
*/
|
|
55
|
+
export declare function recordPredicate<T>(predicate: Predicate<T>, predicates: Predicate<T>[], misplaced: string[], phase: string): void;
|
|
11
56
|
//# sourceMappingURL=predicate.d.ts.map
|
package/dist/predicate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"predicate.d.ts","sourceRoot":"","sources":["../src/predicate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC;IAC1B,4FAA4F;IAC5F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,0DAA0D;IAC1D,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"predicate.d.ts","sourceRoot":"","sources":["../src/predicate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnD;;;GAGG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC;IAC1B,4FAA4F;IAC5F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,0DAA0D;IAC1D,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,OAAO,CAAA;IACzB;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAA;IAE9B;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAC/B,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,EACvB,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,EAC1B,SAAS,EAAE,MAAM,EAAE,EACnB,KAAK,EAAE,MAAM,GACZ,IAAI,CAON"}
|
package/dist/predicate.js
CHANGED
|
@@ -1,2 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Record a predicate on a builder, noting it if it arrived after `.should()`.
|
|
3
|
+
*
|
|
4
|
+
* A free function for the same reason as `recordExclusions` and
|
|
5
|
+
* `selectMatching`: the two builders sit in incompatible hierarchies, so there
|
|
6
|
+
* is no common base to hold a method. The copies were 94% similar and differed
|
|
7
|
+
* only in comment wording and braces — no behaviour.
|
|
8
|
+
*
|
|
9
|
+
* `phase` is read, never written: recording a misplaced predicate is a
|
|
10
|
+
* diagnosis, not a state change.
|
|
11
|
+
*/
|
|
12
|
+
export function recordPredicate(predicate, predicates, misplaced, phase) {
|
|
13
|
+
predicates.push(predicate);
|
|
14
|
+
// Bug 0155 state 2: a predicate-only method used after `.should()`. Dual-use
|
|
15
|
+
// methods dispatch to conditions in that phase and never reach here, so this is
|
|
16
|
+
// a filter written where an assertion was meant — the one state whose fix is
|
|
17
|
+
// "move it before .should()", not "add a condition".
|
|
18
|
+
if (phase === 'condition')
|
|
19
|
+
misplaced.push(predicate.description);
|
|
20
|
+
}
|
|
2
21
|
//# sourceMappingURL=predicate.js.map
|
package/dist/predicate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"predicate.js","sourceRoot":"","sources":["../src/predicate.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"predicate.js","sourceRoot":"","sources":["../src/predicate.ts"],"names":[],"mappings":"AA8CA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAC7B,SAAuB,EACvB,UAA0B,EAC1B,SAAmB,EACnB,KAAa;IAEb,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IAC1B,6EAA6E;IAC7E,gFAAgF;IAChF,6EAA6E;IAC7E,qDAAqD;IACrD,IAAI,KAAK,KAAK,WAAW;QAAE,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;AAClE,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type CollectResult } from './collect-result.js';
|
|
2
2
|
import type { RuleMetadata } from './rule-metadata.js';
|
|
3
3
|
import { type PresetReportOptions } from './report.js';
|
|
4
4
|
/** Per-rule severity within a preset. */
|
|
@@ -15,11 +15,11 @@ export interface PresetBaseOptions extends PresetReportOptions {
|
|
|
15
15
|
* Anything with `.rule()` and `.violations()` — works with both
|
|
16
16
|
* `RuleBuilder<T, P>` and `TerminalBuilder` hierarchies, across all dialects.
|
|
17
17
|
*/
|
|
18
|
-
interface Dispatchable {
|
|
18
|
+
export interface Dispatchable {
|
|
19
19
|
rule(m: RuleMetadata): {
|
|
20
|
-
violations():
|
|
20
|
+
violations(): CollectResult;
|
|
21
21
|
};
|
|
22
|
-
violations():
|
|
22
|
+
violations(): CollectResult;
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
25
|
* Dispatch a single rule within a preset.
|
|
@@ -30,19 +30,10 @@ interface Dispatchable {
|
|
|
30
30
|
*/
|
|
31
31
|
export declare function dispatchRule(builder: Dispatchable, rule: string | (RuleMetadata & {
|
|
32
32
|
id: string;
|
|
33
|
-
}), defaultSeverity: RuleSeverity, overrides: Record<string, RuleSeverity> | undefined):
|
|
33
|
+
}), defaultSeverity: RuleSeverity, overrides: Record<string, RuleSeverity> | undefined): CollectResult;
|
|
34
34
|
/**
|
|
35
35
|
* Validate override keys against known rule IDs. Warns for unrecognized keys
|
|
36
36
|
* (likely typos).
|
|
37
37
|
*/
|
|
38
|
-
export declare function validateOverrides(overrides: Record<string, RuleSeverity
|
|
39
|
-
/**
|
|
40
|
-
* Emit (stderr text) and throw a single `ArchRuleError` with all aggregated
|
|
41
|
-
* violations, if any. Kept for backward compatibility; it is now `finishPreset`
|
|
42
|
-
* in the default `throw` mode. New presets take `PresetReportOptions` and call
|
|
43
|
-
* `finishPreset` so a caller can opt into `report: 'return'` / `--format json`
|
|
44
|
-
* (plan 0070).
|
|
45
|
-
*/
|
|
46
|
-
export declare function throwIfViolations(violations: ArchViolation[]): void;
|
|
47
|
-
export {};
|
|
38
|
+
export declare function validateOverrides(overrides: Partial<Record<string, RuleSeverity>> | undefined, knownIds: readonly string[]): void;
|
|
48
39
|
//# sourceMappingURL=preset-dispatch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preset-dispatch.d.ts","sourceRoot":"","sources":["../src/preset-dispatch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"preset-dispatch.d.ts","sourceRoot":"","sources":["../src/preset-dispatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAiB,MAAM,qBAAqB,CAAA;AAEvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEtD,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAGtD,yCAAyC;AACzC,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAA;AAEnD;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,mBAAmB;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;CACzC;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,CAAC,EAAE,YAAY,GAAG;QAAE,UAAU,IAAI,aAAa,CAAA;KAAE,CAAA;IACtD,UAAU,IAAI,aAAa,CAAA;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,YAAY,EACrB,IAAI,EAAE,MAAM,GAAG,CAAC,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,EAC9C,eAAe,EAAE,YAAY,EAC7B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,SAAS,GAClD,aAAa,CA2Cf;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAM/B,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,GAAG,SAAS,EAC5D,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC1B,IAAI,CAWN"}
|
package/dist/preset-dispatch.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { collectResult } from './collect-result.js';
|
|
2
|
+
import { severityFor } from './violation.js';
|
|
1
3
|
import { formatViolations } from './format.js';
|
|
2
|
-
import {
|
|
4
|
+
import { writeStderr } from './stderr.js';
|
|
3
5
|
/**
|
|
4
6
|
* Dispatch a single rule within a preset.
|
|
5
7
|
*
|
|
@@ -14,14 +16,34 @@ export function dispatchRule(builder, rule, defaultSeverity, overrides) {
|
|
|
14
16
|
// agent`, not just the id.
|
|
15
17
|
const meta = typeof rule === 'string' ? { id: rule } : rule;
|
|
16
18
|
const effective = overrides?.[meta.id] ?? defaultSeverity;
|
|
17
|
-
if (effective === 'off')
|
|
18
|
-
|
|
19
|
+
if (effective === 'off') {
|
|
20
|
+
// A real, measured zero — and deliberately NOT `declaredEmpty`.
|
|
21
|
+
//
|
|
22
|
+
// ADR-014 §3, amended 2026-09-05: a declaration is one a caller MADE over a
|
|
23
|
+
// live instrument, never one eess infers from a configuration.
|
|
24
|
+
// `overrides: { id: 'off' }` is an instruction, and it is byte-identical
|
|
25
|
+
// whether the author meant "I have scoped this out" or "I turned this off to
|
|
26
|
+
// stop a finding" — eess is not positioned to tell those apart, so by
|
|
27
|
+
// ADR-013's rule it must not decide. Marking it declared here would mint,
|
|
28
|
+
// on the author's behalf, exactly the declaration `declaredEmptyFindings`
|
|
29
|
+
// refuses to let them write ("'off' deleted the rule, so the declaration
|
|
30
|
+
// about it is dead").
|
|
31
|
+
//
|
|
32
|
+
// The consequence is deliberate: a preset with every rule off sums to zero
|
|
33
|
+
// examined with no declaration, and the emitter reports it (bug 0261).
|
|
34
|
+
return collectResult([], { examined: 0, notRun: true });
|
|
35
|
+
}
|
|
19
36
|
const violations = builder.rule(meta).violations();
|
|
20
37
|
if (effective === 'warn') {
|
|
21
38
|
if (violations.length > 0) {
|
|
22
|
-
|
|
39
|
+
writeStderr(formatViolations(violations));
|
|
23
40
|
}
|
|
24
|
-
|
|
41
|
+
// `bypassFilters` outranks a per-rule `overrides: { id: 'warn' }` — see
|
|
42
|
+
// `severityFor`. A config finding — a zero-examined rule, or a preset that
|
|
43
|
+
// constructed nothing — is `UNSUPPRESSABLE` by its own text; silently
|
|
44
|
+
// dropping it here just because its OWN rule was downgraded is exactly the
|
|
45
|
+
// suppression path that text promises does not exist.
|
|
46
|
+
return collectResult(violations.filter((v) => severityFor(v, 'warn') === 'error'), { examined: violations.examined });
|
|
25
47
|
}
|
|
26
48
|
return violations;
|
|
27
49
|
}
|
|
@@ -29,25 +51,21 @@ export function dispatchRule(builder, rule, defaultSeverity, overrides) {
|
|
|
29
51
|
* Validate override keys against known rule IDs. Warns for unrecognized keys
|
|
30
52
|
* (likely typos).
|
|
31
53
|
*/
|
|
32
|
-
export function validateOverrides(
|
|
54
|
+
export function validateOverrides(
|
|
55
|
+
// `Partial<Record<...>>` and `readonly`, widened from the narrower shapes this
|
|
56
|
+
// signature had, so `eess-ts`'s byte-identical copy could be deleted rather
|
|
57
|
+
// than kept for its types. Both are strictly more permissive: `Partial` admits
|
|
58
|
+
// an explicit `undefined` value, `readonly` admits a frozen list. No caller
|
|
59
|
+
// loses anything.
|
|
60
|
+
overrides, knownIds) {
|
|
33
61
|
if (!overrides)
|
|
34
62
|
return;
|
|
35
63
|
const knownSet = new Set(knownIds);
|
|
36
64
|
for (const key of Object.keys(overrides)) {
|
|
37
65
|
if (!knownSet.has(key)) {
|
|
38
|
-
|
|
66
|
+
writeStderr(`[eess] Override key '${key}' does not match any rule in this preset. ` +
|
|
39
67
|
`Available rules: ${knownIds.join(', ')}`);
|
|
40
68
|
}
|
|
41
69
|
}
|
|
42
70
|
}
|
|
43
|
-
/**
|
|
44
|
-
* Emit (stderr text) and throw a single `ArchRuleError` with all aggregated
|
|
45
|
-
* violations, if any. Kept for backward compatibility; it is now `finishPreset`
|
|
46
|
-
* in the default `throw` mode. New presets take `PresetReportOptions` and call
|
|
47
|
-
* `finishPreset` so a caller can opt into `report: 'return'` / `--format json`
|
|
48
|
-
* (plan 0070).
|
|
49
|
-
*/
|
|
50
|
-
export function throwIfViolations(violations) {
|
|
51
|
-
finishPreset(violations, { report: 'throw' });
|
|
52
|
-
}
|
|
53
71
|
//# sourceMappingURL=preset-dispatch.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preset-dispatch.js","sourceRoot":"","sources":["../src/preset-dispatch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"preset-dispatch.js","sourceRoot":"","sources":["../src/preset-dispatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAE9C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAuBzC;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAqB,EACrB,IAA8C,EAC9C,eAA6B,EAC7B,SAAmD;IAEnD,8EAA8E;IAC9E,gFAAgF;IAChF,6EAA6E;IAC7E,2BAA2B;IAC3B,MAAM,IAAI,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IAC3D,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,eAAe,CAAA;IACzD,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;QACxB,gEAAgE;QAChE,EAAE;QACF,4EAA4E;QAC5E,+DAA+D;QAC/D,yEAAyE;QACzE,6EAA6E;QAC7E,sEAAsE;QACtE,0EAA0E;QAC1E,0EAA0E;QAC1E,yEAAyE;QACzE,sBAAsB;QACtB,EAAE;QACF,2EAA2E;QAC3E,uEAAuE;QACvE,OAAO,aAAa,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;IACzD,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAA;IAElD,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACzB,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,WAAW,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAA;QAC3C,CAAC;QACD,wEAAwE;QACxE,2EAA2E;QAC3E,sEAAsE;QACtE,2EAA2E;QAC3E,sDAAsD;QACtD,OAAO,aAAa,CAClB,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,OAAO,CAAC,EAC5D,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,CAClC,CAAA;IACH,CAAC;IAED,OAAO,UAAU,CAAA;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB;AAC/B,+EAA+E;AAC/E,4EAA4E;AAC5E,+EAA+E;AAC/E,4EAA4E;AAC5E,kBAAkB;AAClB,SAA4D,EAC5D,QAA2B;IAE3B,IAAI,CAAC,SAAS;QAAE,OAAM;IACtB,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAA;IAClC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,WAAW,CACT,wBAAwB,GAAG,4CAA4C;gBACrE,oBAAoB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC5C,CAAA;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a glob can already match an absolute path.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from ts-archunit's larger `project-relative.ts`, most of which
|
|
5
|
+
* (`rootOf`/`relativeToRoot`, workspace multi-root awareness) needs
|
|
6
|
+
* `ArchProject`/ts-morph and stays deferred — this one predicate is pure
|
|
7
|
+
* string syntax with no dependency on either, and `glob-diagnosis.ts` needs
|
|
8
|
+
* it to be kernel-eligible at all, so it gets its own small home here rather
|
|
9
|
+
* than waiting on the ts-morph-blocked half of the file it came from.
|
|
10
|
+
*
|
|
11
|
+
* Covers POSIX-absolute and Windows drive-absolute globs as well as an
|
|
12
|
+
* explicit globstar.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isAnchored(glob: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Does this glob name a location relative to the project root?
|
|
17
|
+
*
|
|
18
|
+
* Only an **unanchored, relative** glob is normalized. `'**\/x'` is explicitly
|
|
19
|
+
* "anywhere" and must keep meaning that; `'/abs/x'` is already absolute. So
|
|
20
|
+
* this is the same population `syntacticFault` calls `unanchored`, which is
|
|
21
|
+
* what makes the two consistent: a glob stops being reported dead for being
|
|
22
|
+
* unanchored exactly when it starts working.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isProjectRelative(glob: string): boolean;
|
|
25
|
+
//# sourceMappingURL=project-relative.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-relative.d.ts","sourceRoot":"","sources":["../src/project-relative.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAyBvD"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a glob can already match an absolute path.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from ts-archunit's larger `project-relative.ts`, most of which
|
|
5
|
+
* (`rootOf`/`relativeToRoot`, workspace multi-root awareness) needs
|
|
6
|
+
* `ArchProject`/ts-morph and stays deferred — this one predicate is pure
|
|
7
|
+
* string syntax with no dependency on either, and `glob-diagnosis.ts` needs
|
|
8
|
+
* it to be kernel-eligible at all, so it gets its own small home here rather
|
|
9
|
+
* than waiting on the ts-morph-blocked half of the file it came from.
|
|
10
|
+
*
|
|
11
|
+
* Covers POSIX-absolute and Windows drive-absolute globs as well as an
|
|
12
|
+
* explicit globstar.
|
|
13
|
+
*/
|
|
14
|
+
export function isAnchored(glob) {
|
|
15
|
+
return glob.startsWith('**/') || glob.startsWith('/') || /^[A-Za-z]:\//.test(glob);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Does this glob name a location relative to the project root?
|
|
19
|
+
*
|
|
20
|
+
* Only an **unanchored, relative** glob is normalized. `'**\/x'` is explicitly
|
|
21
|
+
* "anywhere" and must keep meaning that; `'/abs/x'` is already absolute. So
|
|
22
|
+
* this is the same population `syntacticFault` calls `unanchored`, which is
|
|
23
|
+
* what makes the two consistent: a glob stops being reported dead for being
|
|
24
|
+
* unanchored exactly when it starts working.
|
|
25
|
+
*/
|
|
26
|
+
export function isProjectRelative(glob) {
|
|
27
|
+
// A `./` segment is excluded, and that exclusion is load-bearing rather than
|
|
28
|
+
// fussy. `syntacticFault` reports `dot-segment` for a `./` anywhere in a
|
|
29
|
+
// glob, so normalizing one would make the rule MATCH at runtime while the
|
|
30
|
+
// gate still reported it dead — two derivations disagreeing about the same
|
|
31
|
+
// glob, which is the failure this project spends most of its guards on.
|
|
32
|
+
//
|
|
33
|
+
// `./` is a mistake in both worlds — it never occurs in an absolute path and
|
|
34
|
+
// it says nothing extra in a relative one — so the honest fix is to leave it
|
|
35
|
+
// failing, with advice that says to remove it.
|
|
36
|
+
// `..` is not relative-to-the-root in any usable sense: containment returns
|
|
37
|
+
// `undefined` for anything above the root, deliberately, so a `../`
|
|
38
|
+
// glob would normalize to nothing and be reported dead with three false
|
|
39
|
+
// causes. Excluded alongside `./` — both are mistakes in both readings.
|
|
40
|
+
if (/(?:^|\/)\.\.?\//.test(glob))
|
|
41
|
+
return false;
|
|
42
|
+
// Derived from `isAnchored`, not restated — two lists that disagree is the
|
|
43
|
+
// failure this file spends most of its guards on. `isAnchored` covers `/x`,
|
|
44
|
+
// `**/x` and a drive-absolute `C:/x`.
|
|
45
|
+
if (isAnchored(glob))
|
|
46
|
+
return false;
|
|
47
|
+
// `*/x/**` is deliberately NOT normalized, even though it is unanchored.
|
|
48
|
+
// Normalizing it would make it match, which sounds like an improvement until
|
|
49
|
+
// you notice it is the LAST reachable `unanchored` fault for a path glob —
|
|
50
|
+
// the anchor advice would become unreachable. Left failing, with a remedy
|
|
51
|
+
// that works: `'**/x/**'`.
|
|
52
|
+
return !glob.startsWith('*/');
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=project-relative.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-relative.js","sourceRoot":"","sources":["../src/project-relative.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACpF,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,6EAA6E;IAC7E,yEAAyE;IACzE,0EAA0E;IAC1E,2EAA2E;IAC3E,wEAAwE;IACxE,EAAE;IACF,6EAA6E;IAC7E,6EAA6E;IAC7E,+CAA+C;IAC/C,4EAA4E;IAC5E,oEAAoE;IACpE,wEAAwE;IACxE,wEAAwE;IACxE,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAA;IAC9C,2EAA2E;IAC3E,4EAA4E;IAC5E,sCAAsC;IACtC,IAAI,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAA;IAClC,yEAAyE;IACzE,6EAA6E;IAC7E,2EAA2E;IAC3E,0EAA0E;IAC1E,2BAA2B;IAC3B,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;AAC/B,CAAC"}
|
package/dist/report.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type CollectResult } from './collect-result.js';
|
|
2
2
|
import type { OutputFormat } from './check-options.js';
|
|
3
3
|
/**
|
|
4
4
|
* How a preset delivers its violations (plan 0070, ADR-008):
|
|
@@ -18,21 +18,51 @@ export interface ReportOptions {
|
|
|
18
18
|
export interface PresetReportOptions extends ReportOptions {
|
|
19
19
|
/** Delivery mode. Default `throw`. */
|
|
20
20
|
readonly report?: ReportMode;
|
|
21
|
+
/**
|
|
22
|
+
* Declare that this preset's subject legitimately does not exist here —
|
|
23
|
+
* [ADR-010](../../../adr/010-a-pass-is-constructed-from-evidence.md) §3.
|
|
24
|
+
*
|
|
25
|
+
* **On the shared options type, not on six preset interfaces**, because
|
|
26
|
+
* ADR-010 §3's second clause is about presets as a class: "A preset user does
|
|
27
|
+
* not hold the builder; if a preset option cannot carry the user's
|
|
28
|
+
* empty-declaration to the mint, their only reachable remedy is disabling the
|
|
29
|
+
* option — deleting coverage permanently (ADR-009 rule 1's trained-suppression
|
|
30
|
+
* dynamic, reproduced by this ADR's own gate if unaddressed)." A preset that
|
|
31
|
+
* examines nothing and cannot be told so leaves its user exactly one exit, and
|
|
32
|
+
* it is the wrong one.
|
|
33
|
+
*
|
|
34
|
+
* **It expires**, which is the only reason it is admissible at all: declare
|
|
35
|
+
* this and then examine something, and the emitter reports
|
|
36
|
+
* `emitter/expired-declaration`. A claim nothing can contradict is not an
|
|
37
|
+
* assertion — the property ADR-014 §3's 2026-09-05 amendment turns on when it
|
|
38
|
+
* refuses to infer a declaration from `overrides: 'off'`.
|
|
39
|
+
*
|
|
40
|
+
* Use it for a corpus with no ER diagrams, a suite with no exemptions, a
|
|
41
|
+
* project that genuinely has none of this preset's subject. Do not use it to
|
|
42
|
+
* quiet a preset whose glob is wrong: the day the glob is fixed, this reddens.
|
|
43
|
+
*/
|
|
44
|
+
readonly expectEmpty?: boolean;
|
|
21
45
|
}
|
|
22
46
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
47
|
+
* How many violations this module has actually WRITTEN, ever.
|
|
48
|
+
*
|
|
49
|
+
* Read as a delta by a caller that aggregates reporting, to answer one question it
|
|
50
|
+
* cannot otherwise answer: *did something emit while I was loading that module?*
|
|
51
|
+
*
|
|
52
|
+
* The alternative a caller might reach for — counting the writes it SUPPRESSED and
|
|
53
|
+
* inferring "then nothing was written" — is a double negative and is unsound: a
|
|
54
|
+
* module that suppresses one terminal and leaks through another satisfies it while
|
|
55
|
+
* leaking. Measured on `eess-ts`, which shipped that inference and fell into
|
|
56
|
+
* exactly that case. Count emissions, not silences.
|
|
28
57
|
*/
|
|
29
|
-
export declare function
|
|
58
|
+
export declare function violationsEmittedCount(): number;
|
|
59
|
+
export declare function reportViolations(violations: CollectResult, options?: ReportOptions): CollectResult;
|
|
30
60
|
/**
|
|
31
61
|
* Finish a preset: deliver its aggregated violations per the requested mode
|
|
32
|
-
* (plan 0070). `throw` (default) emits then throws
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
62
|
+
* (plan 0070). `throw` (default) emits then throws; `return` hands the
|
|
63
|
+
* violations back untouched (the caller owns emission and control flow);
|
|
64
|
+
* `warn` emits without throwing. Always returns the violations, so a caller can
|
|
65
|
+
* inspect them regardless of mode.
|
|
36
66
|
*/
|
|
37
|
-
export declare function finishPreset(violations:
|
|
67
|
+
export declare function finishPreset(violations: CollectResult, options?: PresetReportOptions): CollectResult;
|
|
38
68
|
//# sourceMappingURL=report.d.ts.map
|
package/dist/report.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAA8B,MAAM,qBAAqB,CAAA;AAUpF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAMtD;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEpD,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAA;IAC9B,kDAAkD;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,sEAAsE;AACtE,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,sCAAsC;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAA;IAE5B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAC/B;AAWD;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AA6HD,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,aAAa,EACzB,OAAO,GAAE,aAAkB,GAC1B,aAAa,CAqBf;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,aAAa,EACzB,OAAO,GAAE,mBAAwB,GAChC,aAAa,CAoCf"}
|