@nielspeter/eess-ts 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builders/call-rule-builder.d.ts.map +1 -1
- package/dist/builders/call-rule-builder.js +2 -1
- package/dist/builders/call-rule-builder.js.map +1 -1
- package/dist/builders/class-rule-builder.d.ts.map +1 -1
- package/dist/builders/class-rule-builder.js +7 -25
- package/dist/builders/class-rule-builder.js.map +1 -1
- package/dist/builders/correspondence-builder.d.ts.map +1 -1
- package/dist/builders/correspondence-builder.js +6 -14
- package/dist/builders/correspondence-builder.js.map +1 -1
- package/dist/builders/cross-layer-builder.d.ts.map +1 -1
- package/dist/builders/cross-layer-builder.js +7 -6
- package/dist/builders/cross-layer-builder.js.map +1 -1
- package/dist/builders/function-rule-builder.d.ts.map +1 -1
- package/dist/builders/function-rule-builder.js +4 -13
- package/dist/builders/function-rule-builder.js.map +1 -1
- package/dist/builders/module-rule-builder.d.ts.map +1 -1
- package/dist/builders/module-rule-builder.js +4 -16
- package/dist/builders/module-rule-builder.js.map +1 -1
- package/dist/builders/slice-rule-builder.d.ts.map +1 -1
- package/dist/builders/slice-rule-builder.js +4 -3
- package/dist/builders/slice-rule-builder.js.map +1 -1
- package/dist/builders/type-rule-builder.d.ts.map +1 -1
- package/dist/builders/type-rule-builder.js +4 -13
- package/dist/builders/type-rule-builder.js.map +1 -1
- package/dist/cli/commands/baseline.d.ts +5 -1
- package/dist/cli/commands/baseline.d.ts.map +1 -1
- package/dist/cli/commands/baseline.js +47 -5
- package/dist/cli/commands/baseline.js.map +1 -1
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +155 -13
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +97 -6
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/explain.d.ts.map +1 -1
- package/dist/cli/commands/explain.js +21 -2
- package/dist/cli/commands/explain.js.map +1 -1
- package/dist/cli/commands/init.js +1 -1
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/import-rule-module.d.ts +23 -4
- package/dist/cli/import-rule-module.d.ts.map +1 -1
- package/dist/cli/import-rule-module.js +30 -18
- package/dist/cli/import-rule-module.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +4 -11
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/load-rules.d.ts.map +1 -1
- package/dist/cli/load-rules.js +5 -4
- package/dist/cli/load-rules.js.map +1 -1
- package/dist/cli/resolve-config.d.ts +0 -8
- package/dist/cli/resolve-config.d.ts.map +1 -1
- package/dist/cli/resolve-config.js +18 -48
- package/dist/cli/resolve-config.js.map +1 -1
- package/dist/cli/rule-file-findings.d.ts.map +1 -1
- package/dist/cli/rule-file-findings.js +60 -2
- package/dist/cli/rule-file-findings.js.map +1 -1
- package/dist/cli/watch.d.ts +13 -43
- package/dist/cli/watch.d.ts.map +1 -1
- package/dist/cli/watch.js +8 -148
- package/dist/cli/watch.js.map +1 -1
- package/dist/conditions/call.d.ts.map +1 -1
- package/dist/conditions/call.js +4 -3
- package/dist/conditions/call.js.map +1 -1
- package/dist/conditions/cross-layer.js +2 -2
- package/dist/conditions/cross-layer.js.map +1 -1
- package/dist/conditions/dependency.js +2 -2
- package/dist/conditions/dependency.js.map +1 -1
- package/dist/conditions/exports.d.ts.map +1 -1
- package/dist/conditions/exports.js +31 -37
- package/dist/conditions/exports.js.map +1 -1
- package/dist/conditions/function.js +1 -1
- package/dist/conditions/function.js.map +1 -1
- package/dist/conditions/jsx.js +1 -1
- package/dist/conditions/jsx.js.map +1 -1
- package/dist/conditions/members.d.ts.map +1 -1
- package/dist/conditions/members.js +3 -2
- package/dist/conditions/members.js.map +1 -1
- package/dist/conditions/reverse-dependency.d.ts.map +1 -1
- package/dist/conditions/reverse-dependency.js +47 -2
- package/dist/conditions/reverse-dependency.js.map +1 -1
- package/dist/conditions/slice.js +1 -1
- package/dist/conditions/slice.js.map +1 -1
- package/dist/conditions/structural.js +1 -1
- package/dist/conditions/structural.js.map +1 -1
- package/dist/core/check-all.d.ts.map +1 -1
- package/dist/core/check-all.js +61 -7
- package/dist/core/check-all.js.map +1 -1
- package/dist/core/combinators.d.ts.map +1 -1
- package/dist/core/combinators.js +20 -27
- package/dist/core/combinators.js.map +1 -1
- package/dist/core/descendant-cache.d.ts.map +1 -1
- package/dist/core/descendant-cache.js +5 -7
- package/dist/core/descendant-cache.js.map +1 -1
- package/dist/core/diagnose.js +15 -7
- package/dist/core/diagnose.js.map +1 -1
- package/dist/core/disk-set.js +1 -1
- package/dist/core/disk-set.js.map +1 -1
- package/dist/core/element-cache.js +1 -1
- package/dist/core/element-cache.js.map +1 -1
- package/dist/core/exclusion-comments.d.ts +15 -50
- package/dist/core/exclusion-comments.d.ts.map +1 -1
- package/dist/core/exclusion-comments.js +4 -307
- package/dist/core/exclusion-comments.js.map +1 -1
- package/dist/core/execute-rule.d.ts +8 -0
- package/dist/core/execute-rule.d.ts.map +1 -1
- package/dist/core/execute-rule.js +99 -13
- package/dist/core/execute-rule.js.map +1 -1
- package/dist/core/glob-evaluator.js +2 -2
- package/dist/core/glob-evaluator.js.map +1 -1
- package/dist/core/invalidate-on-modify.d.ts +20 -0
- package/dist/core/invalidate-on-modify.d.ts.map +1 -0
- package/dist/core/invalidate-on-modify.js +26 -0
- package/dist/core/invalidate-on-modify.js.map +1 -0
- package/dist/core/line-index.d.ts.map +1 -1
- package/dist/core/line-index.js +6 -8
- package/dist/core/line-index.js.map +1 -1
- package/dist/core/metric-violation.d.ts +1 -1
- package/dist/core/module-edges.d.ts.map +1 -1
- package/dist/core/module-edges.js +26 -25
- package/dist/core/module-edges.js.map +1 -1
- package/dist/core/orphan-exclusions.d.ts.map +1 -1
- package/dist/core/orphan-exclusions.js +15 -5
- package/dist/core/orphan-exclusions.js.map +1 -1
- package/dist/core/path-universe.d.ts +10 -42
- package/dist/core/path-universe.d.ts.map +1 -1
- package/dist/core/path-universe.js +0 -20
- package/dist/core/path-universe.js.map +1 -1
- package/dist/core/project.d.ts.map +1 -1
- package/dist/core/project.js +6 -5
- package/dist/core/project.js.map +1 -1
- package/dist/core/rule-builder.d.ts +22 -1
- package/dist/core/rule-builder.d.ts.map +1 -1
- package/dist/core/rule-builder.js +38 -20
- package/dist/core/rule-builder.js.map +1 -1
- package/dist/core/rule-declaration.d.ts.map +1 -1
- package/dist/core/rule-declaration.js +14 -52
- package/dist/core/rule-declaration.js.map +1 -1
- package/dist/core/terminal-builder.d.ts +17 -13
- package/dist/core/terminal-builder.d.ts.map +1 -1
- package/dist/core/terminal-builder.js +41 -21
- package/dist/core/terminal-builder.js.map +1 -1
- package/dist/core/terminal-execution.d.ts +22 -6
- package/dist/core/terminal-execution.d.ts.map +1 -1
- package/dist/core/terminal-execution.js +39 -7
- package/dist/core/terminal-execution.js.map +1 -1
- package/dist/core/ts-comment-mask.d.ts +2 -0
- package/dist/core/ts-comment-mask.d.ts.map +1 -0
- package/dist/core/ts-comment-mask.js +102 -0
- package/dist/core/ts-comment-mask.js.map +1 -0
- package/dist/core/vacuity-diagnosis.js +1 -1
- package/dist/core/vacuity-diagnosis.js.map +1 -1
- package/dist/graphql/graphql-rule-builder.d.ts +95 -0
- package/dist/graphql/graphql-rule-builder.d.ts.map +1 -0
- package/dist/graphql/graphql-rule-builder.js +127 -0
- package/dist/graphql/graphql-rule-builder.js.map +1 -0
- package/dist/graphql/index.d.ts +1 -0
- package/dist/graphql/index.d.ts.map +1 -1
- package/dist/graphql/index.js +1 -0
- package/dist/graphql/index.js.map +1 -1
- package/dist/graphql/resolver-rule-builder.d.ts +22 -76
- package/dist/graphql/resolver-rule-builder.d.ts.map +1 -1
- package/dist/graphql/resolver-rule-builder.js +8 -130
- package/dist/graphql/resolver-rule-builder.js.map +1 -1
- package/dist/graphql/schema-loader.d.ts.map +1 -1
- package/dist/graphql/schema-loader.js +4 -3
- package/dist/graphql/schema-loader.js.map +1 -1
- package/dist/graphql/schema-predicates.d.ts.map +1 -1
- package/dist/graphql/schema-predicates.js +17 -12
- package/dist/graphql/schema-predicates.js.map +1 -1
- package/dist/graphql/schema-rule-builder.d.ts +21 -67
- package/dist/graphql/schema-rule-builder.d.ts.map +1 -1
- package/dist/graphql/schema-rule-builder.js +6 -120
- package/dist/graphql/schema-rule-builder.js.map +1 -1
- package/dist/helpers/baseline-generator.d.ts +9 -0
- package/dist/helpers/baseline-generator.d.ts.map +1 -1
- package/dist/helpers/baseline-generator.js +9 -0
- package/dist/helpers/baseline-generator.js.map +1 -1
- package/dist/helpers/baseline.d.ts.map +1 -1
- package/dist/helpers/baseline.js +4 -4
- package/dist/helpers/baseline.js.map +1 -1
- package/dist/helpers/body-traversal.d.ts.map +1 -1
- package/dist/helpers/body-traversal.js +13 -0
- package/dist/helpers/body-traversal.js.map +1 -1
- package/dist/helpers/callback-extractor.js +6 -38
- package/dist/helpers/callback-extractor.js.map +1 -1
- package/dist/helpers/complexity.d.ts +1 -1
- package/dist/helpers/complexity.js +1 -1
- package/dist/helpers/diff-aware.d.ts +11 -39
- package/dist/helpers/diff-aware.d.ts.map +1 -1
- package/dist/helpers/diff-aware.js +11 -79
- package/dist/helpers/diff-aware.js.map +1 -1
- package/dist/helpers/matchers.d.ts.map +1 -1
- package/dist/helpers/matchers.js +51 -67
- package/dist/helpers/matchers.js.map +1 -1
- package/dist/index.d.ts +15 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +37 -18
- package/dist/index.js.map +1 -1
- package/dist/models/arch-function.d.ts +26 -2
- package/dist/models/arch-function.d.ts.map +1 -1
- package/dist/models/arch-function.js +51 -17
- package/dist/models/arch-function.js.map +1 -1
- package/dist/models/arch-jsx-element.d.ts.map +1 -1
- package/dist/models/arch-jsx-element.js +16 -17
- package/dist/models/arch-jsx-element.js.map +1 -1
- package/dist/predicates/jsx.d.ts.map +1 -1
- package/dist/predicates/jsx.js +2 -1
- package/dist/predicates/jsx.js.map +1 -1
- package/dist/presets/agent-guardrails.d.ts +29 -3
- package/dist/presets/agent-guardrails.d.ts.map +1 -1
- package/dist/presets/agent-guardrails.js +185 -1
- package/dist/presets/agent-guardrails.js.map +1 -1
- package/dist/presets/boundaries.d.ts +2 -2
- package/dist/presets/boundaries.d.ts.map +1 -1
- package/dist/presets/data-layer.d.ts +2 -2
- package/dist/presets/data-layer.d.ts.map +1 -1
- package/dist/presets/index.d.ts +4 -1
- package/dist/presets/index.d.ts.map +1 -1
- package/dist/presets/index.js +11 -1
- package/dist/presets/index.js.map +1 -1
- package/dist/presets/layered.d.ts +2 -2
- package/dist/presets/layered.d.ts.map +1 -1
- package/dist/presets/recommended.d.ts +3 -3
- package/dist/presets/recommended.d.ts.map +1 -1
- package/dist/presets/shared.d.ts +8 -11
- package/dist/presets/shared.d.ts.map +1 -1
- package/dist/presets/shared.js +57 -28
- package/dist/presets/shared.js.map +1 -1
- package/dist/rules/metrics-function.d.ts.map +1 -1
- package/dist/rules/metrics-function.js +59 -62
- package/dist/rules/metrics-function.js.map +1 -1
- package/dist/rules/metrics.d.ts.map +1 -1
- package/dist/rules/metrics.js +62 -59
- package/dist/rules/metrics.js.map +1 -1
- package/dist/smells/clusters.d.ts +78 -0
- package/dist/smells/clusters.d.ts.map +1 -0
- package/dist/smells/clusters.js +124 -0
- package/dist/smells/clusters.js.map +1 -0
- package/dist/smells/duplicate-bodies.d.ts +38 -4
- package/dist/smells/duplicate-bodies.d.ts.map +1 -1
- package/dist/smells/duplicate-bodies.js +93 -44
- package/dist/smells/duplicate-bodies.js.map +1 -1
- package/dist/smells/duplicate-report.d.ts +90 -0
- package/dist/smells/duplicate-report.d.ts.map +1 -0
- package/dist/smells/duplicate-report.js +344 -0
- package/dist/smells/duplicate-report.js.map +1 -0
- package/dist/smells/fingerprint.d.ts +12 -0
- package/dist/smells/fingerprint.d.ts.map +1 -1
- package/dist/smells/fingerprint.js +8 -2
- package/dist/smells/fingerprint.js.map +1 -1
- package/dist/smells/inconsistent-siblings.js +1 -1
- package/dist/smells/inconsistent-siblings.js.map +1 -1
- package/dist/smells/similar-pairs.d.ts +9 -8
- package/dist/smells/similar-pairs.d.ts.map +1 -1
- package/dist/smells/similar-pairs.js +83 -1
- package/dist/smells/similar-pairs.js.map +1 -1
- package/dist/smells/smell-builder.d.ts.map +1 -1
- package/dist/smells/smell-builder.js +3 -2
- package/dist/smells/smell-builder.js.map +1 -1
- package/dist/smells/variation.d.ts +47 -0
- package/dist/smells/variation.d.ts.map +1 -0
- package/dist/smells/variation.js +90 -0
- package/dist/smells/variation.js.map +1 -0
- package/dist/tsconfig/tsconfig-builder.d.ts.map +1 -1
- package/dist/tsconfig/tsconfig-builder.js +3 -2
- package/dist/tsconfig/tsconfig-builder.js.map +1 -1
- package/package.json +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"disk-set.js","sourceRoot":"","sources":["../../src/core/disk-set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,SAAS,MAAM,WAAW,CAAA;AAEjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"disk-set.js","sourceRoot":"","sources":["../../src/core/disk-set.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { registerCacheReset } from '@nielspeter/eess';
|
|
1
|
+
import { registerCacheReset } from '@nielspeter/eess/internal';
|
|
2
2
|
/** A cache private to one builder module, typed to that builder's element. */
|
|
3
3
|
export function createElementCache() {
|
|
4
4
|
let perProject = new WeakMap();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element-cache.js","sourceRoot":"","sources":["../../src/core/element-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"element-cache.js","sourceRoot":"","sources":["../../src/core/element-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAuE9D,8EAA8E;AAC9E,MAAM,UAAU,kBAAkB;IAChC,IAAI,UAAU,GAAG,IAAI,OAAO,EAAiC,CAAA;IAC7D,8EAA8E;IAC9E,gFAAgF;IAChF,kEAAkE;IAClE,kBAAkB,CAAC,GAAG,EAAE;QACtB,UAAU,GAAG,IAAI,OAAO,EAAiC,CAAA;IAC3D,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,GAAG,CAAC,OAAoB,EAAE,GAAW,EAAE,OAAkB;YACvD,IAAI,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YACnC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,KAAK,GAAG,IAAI,GAAG,EAAe,CAAA;gBAC9B,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;YAChC,CAAC;YACD,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAC1B,sEAAsE;YACtE,kEAAkE;YAClE,mEAAmE;YACnE,IAAI,GAAG,KAAK,SAAS;gBAAE,OAAO,GAAG,CAAA;YACjC,MAAM,KAAK,GAAG,OAAO,EAAE,CAAA;YACvB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;YACrB,OAAO,KAAK,CAAA;QACd,CAAC;KACF,CAAA;AACH,CAAC;AAED,gFAAgF;AAChF,MAAM,CAAC,MAAM,eAAe,GAAG,SAAS,CAAA"}
|
|
@@ -1,54 +1,19 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { isExcludedByComment as isExcludedShared } from '@nielspeter/eess';
|
|
2
|
+
import type { ExclusionComment, ExclusionWarning, ParseResult } from '@nielspeter/eess';
|
|
2
3
|
/**
|
|
3
|
-
* Exclusion
|
|
4
|
+
* Exclusion comments for `eess-ts` — the kernel's parser, with this dialect's
|
|
5
|
+
* lexer.
|
|
6
|
+
*
|
|
7
|
+
* **This file used to be a second parser** (426 lines), and it drifted: bug
|
|
8
|
+
* 0158's fix landed on the kernel copy and never reached here, so a bare
|
|
9
|
+
* `eess-exclude-start` was silent in `eess-ts` and blamed the `-end` line when it
|
|
10
|
+
* did speak. That is bug 0227, and it is why ADR-012 exists.
|
|
11
|
+
*
|
|
12
|
+
* What was ever this package's own is the masker — knowing which spans of a
|
|
13
|
+
* `.ts` file are string literals needs a TypeScript parser, and the kernel
|
|
14
|
+
* cannot have one. That is now the only thing passed across.
|
|
4
15
|
*/
|
|
5
|
-
export
|
|
6
|
-
/** Rule ID being excluded */
|
|
7
|
-
ruleId: string;
|
|
8
|
-
/** Required reason for the exclusion */
|
|
9
|
-
reason: string;
|
|
10
|
-
/** File path where the comment was found */
|
|
11
|
-
file: string;
|
|
12
|
-
/** Line number of the comment */
|
|
13
|
-
line: number;
|
|
14
|
-
/** Whether this is a block exclusion (start/end) */
|
|
15
|
-
isBlock: boolean;
|
|
16
|
-
/** End line for block exclusions */
|
|
17
|
-
endLine?: number;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Validation warning for exclusion comments.
|
|
21
|
-
*/
|
|
22
|
-
export interface ExclusionWarning {
|
|
23
|
-
/** Warning message */
|
|
24
|
-
message: string;
|
|
25
|
-
/** File path */
|
|
26
|
-
file: string;
|
|
27
|
-
/** Line number */
|
|
28
|
-
line: number;
|
|
29
|
-
/**
|
|
30
|
-
* What kind of fault this is, so a caller can act on it differently.
|
|
31
|
-
*
|
|
32
|
-
* `'undocumented'` — the directive is well-formed and **applied**; it just
|
|
33
|
-
* states no reason. Since v0.38.0 this fails the build ([ts-archunit bug 0039](https://github.com/nielspeter/ts-archunit/blob/main/bugs/fixed/0039-an-undocumented-exclusion-comment-suppresses-and-only-warns.md)),
|
|
34
|
-
* because a suppression nobody justified is the marker ADR-009 rule 3's
|
|
35
|
-
* corollary warns about.
|
|
36
|
-
*
|
|
37
|
-
* `'malformed'` — the directive is broken syntax and was **not** applied. Two
|
|
38
|
-
* of the three malformed shapes therefore leave the original violation firing,
|
|
39
|
-
* so the build is already red and a stderr line is the right weight.
|
|
40
|
-
*/
|
|
41
|
-
kind: 'undocumented' | 'malformed';
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Result of parsing exclusion comments from a source file.
|
|
45
|
-
*/
|
|
46
|
-
export interface ParseResult {
|
|
47
|
-
/** Successfully parsed exclusion comments */
|
|
48
|
-
exclusions: ExclusionComment[];
|
|
49
|
-
/** Warnings about malformed comments */
|
|
50
|
-
warnings: ExclusionWarning[];
|
|
51
|
-
}
|
|
16
|
+
export type { ExclusionComment, ExclusionWarning, ParseResult };
|
|
52
17
|
export declare function parseExclusionComments(sourceText: string, filePath: string): ParseResult;
|
|
53
|
-
export declare
|
|
18
|
+
export declare const isExcludedByComment: typeof isExcludedShared;
|
|
54
19
|
//# sourceMappingURL=exclusion-comments.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exclusion-comments.d.ts","sourceRoot":"","sources":["../../src/core/exclusion-comments.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"exclusion-comments.d.ts","sourceRoot":"","sources":["../../src/core/exclusion-comments.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,mBAAmB,IAAI,gBAAgB,EACxC,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAGvF;;;;;;;;;;;;GAYG;AACH,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAA;AAE/D,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,CAExF;AAED,eAAO,MAAM,mBAAmB,yBAAmB,CAAA"}
|
|
@@ -1,310 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
// A directive must BEGIN its comment. The regexes are anchored at `^` and the
|
|
4
|
-
// caller slices each line from its first `//`, so they see the comment and
|
|
5
|
-
// nothing before it — which keeps the documented TRAILING form working
|
|
6
|
-
// (`const a = 1 // <directive>`), where the comment starts mid-line. Anchoring
|
|
7
|
-
// to the start of the LINE instead was the first attempt and broke exactly
|
|
8
|
-
// that; the guard's trailing rows caught it.
|
|
9
|
-
//
|
|
10
|
-
// It used to match anywhere in the line, which made any comment *mentioning*
|
|
11
|
-
// the syntax a live directive. This file's own grammar documentation was one:
|
|
12
|
-
// a line reading "Single-line without reason: <the directive>" declared a
|
|
13
|
-
// real, reason-less exclusion against whatever rule was being evaluated, and
|
|
14
|
-
// this repo's preset fan-out test caught it the moment comments started being
|
|
15
|
-
// read correctly. Every user documenting the feature in a code comment would
|
|
16
|
-
// have hit the same thing.
|
|
17
|
-
//
|
|
18
|
-
// A trailing directive still works — `const a = 1 // <directive>` — because
|
|
19
|
-
// there the comment itself begins with it.
|
|
20
|
-
const SINGLE_LINE_RE = /^\/\/\s*eess-exclude\s+(.+)/;
|
|
21
|
-
// Block start: // eess-exclude-start <rule-id>[, <rule-id>]: <reason>
|
|
22
|
-
const BLOCK_START_RE = /^\/\/\s*eess-exclude-start\s+(.+)/;
|
|
23
|
-
// Block end: // eess-exclude-end
|
|
24
|
-
const BLOCK_END_RE = /^\/\/\s*eess-exclude-end\b/;
|
|
25
|
-
/**
|
|
26
|
-
* Parse rule IDs and reason from the content after the directive keyword.
|
|
27
|
-
*
|
|
28
|
-
* Format: `rule-a, rule-b: reason text`
|
|
29
|
-
* If no colon is present, all content is treated as rule IDs and reason is empty.
|
|
30
|
-
*/
|
|
31
|
-
function parseRuleIdsAndReason(content) {
|
|
32
|
-
const colonIndex = content.indexOf(':');
|
|
33
|
-
if (colonIndex < 0) {
|
|
34
|
-
// No colon — all content is rule IDs, no reason
|
|
35
|
-
const ruleIds = content
|
|
36
|
-
.split(',')
|
|
37
|
-
.map((s) => s.trim())
|
|
38
|
-
.filter((s) => s.length > 0);
|
|
39
|
-
return { ruleIds, reason: '' };
|
|
40
|
-
}
|
|
41
|
-
const idsPart = content.slice(0, colonIndex);
|
|
42
|
-
const reason = content.slice(colonIndex + 1).trim();
|
|
43
|
-
const ruleIds = idsPart
|
|
44
|
-
.split(',')
|
|
45
|
-
.map((s) => s.trim())
|
|
46
|
-
.filter((s) => s.length > 0);
|
|
47
|
-
return { ruleIds, reason };
|
|
48
|
-
}
|
|
49
|
-
/** Handle a block-end directive line. */
|
|
50
|
-
function handleBlockEnd(frames, exclusions, warnings, filePath, lineNum) {
|
|
51
|
-
const innermost = frames.pop();
|
|
52
|
-
if (innermost === undefined) {
|
|
53
|
-
warnings.push({
|
|
54
|
-
message: `eess-exclude-end without matching start`,
|
|
55
|
-
file: filePath,
|
|
56
|
-
line: lineNum,
|
|
57
|
-
kind: 'malformed',
|
|
58
|
-
});
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
// Close the innermost frame only. This used to close **every** open block,
|
|
62
|
-
// which is how a nested region silently ended its parent early (bug 0039):
|
|
63
|
-
// the inner `-end` closed the outer, and everything after it was unexcluded
|
|
64
|
-
// while looking excluded in the source.
|
|
65
|
-
for (const comment of innermost) {
|
|
66
|
-
comment.endLine = lineNum;
|
|
67
|
-
exclusions.push(comment);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
/** Emit undocumented-exclusion warnings for each rule ID when no reason is given. */
|
|
71
|
-
function warnUndocumented(warnings, ruleIds, directive, filePath, lineNum) {
|
|
72
|
-
for (const ruleId of ruleIds) {
|
|
73
|
-
warnings.push({
|
|
74
|
-
message: `Undocumented exclusion at ${filePath}:${String(lineNum)} — ` +
|
|
75
|
-
`// ${directive} ${ruleId}\n` +
|
|
76
|
-
` Fix: Add a reason — // ${directive} ${ruleId}: <why>`,
|
|
77
|
-
file: filePath,
|
|
78
|
-
line: lineNum,
|
|
79
|
-
kind: 'undocumented',
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
/** Handle a block-start directive line. */
|
|
84
|
-
function handleBlockStart(content, frames, warnings, filePath, lineNum) {
|
|
85
|
-
const { ruleIds, reason } = parseRuleIdsAndReason(content);
|
|
86
|
-
if (reason === '') {
|
|
87
|
-
warnUndocumented(warnings, ruleIds, 'eess-exclude-start', filePath, lineNum);
|
|
88
|
-
}
|
|
89
|
-
// Nesting a DIFFERENT rule is legitimate and used to be refused outright —
|
|
90
|
-
// exempting `arch/no-cycles` across a module and `arch/no-any` across one
|
|
91
|
-
// function inside it is an ordinary thing to want. The old code warned and
|
|
92
|
-
// dropped the inner directive, then let the inner `-end` close the outer
|
|
93
|
-
// block, so both exemptions were wrong: the inner never applied and the outer
|
|
94
|
-
// stopped early. Frames make both work.
|
|
95
|
-
//
|
|
96
|
-
// Re-opening a rule that is ALREADY open is different — it is redundant, and
|
|
97
|
-
// the likeliest cause is a missing `-end`. Warned, but still pushed: refusing
|
|
98
|
-
// it is what produced the early-close bug.
|
|
99
|
-
const alreadyOpen = new Set(frames.flat().map((c) => c.ruleId));
|
|
100
|
-
for (const ruleId of ruleIds) {
|
|
101
|
-
if (alreadyOpen.has(ruleId)) {
|
|
102
|
-
warnings.push({
|
|
103
|
-
message: `eess-exclude-start for '${ruleId}' is already open — ` +
|
|
104
|
-
`the enclosing block covers this region. Fix: remove this directive, ` +
|
|
105
|
-
`or close the enclosing block first if the nesting was unintended.`,
|
|
106
|
-
file: filePath,
|
|
107
|
-
line: lineNum,
|
|
108
|
-
kind: 'malformed',
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
frames.push(ruleIds.map((ruleId) => ({
|
|
113
|
-
ruleId,
|
|
114
|
-
reason,
|
|
115
|
-
file: filePath,
|
|
116
|
-
line: lineNum,
|
|
117
|
-
isBlock: true,
|
|
118
|
-
})));
|
|
119
|
-
}
|
|
120
|
-
/** Handle a single-line exclude directive. */
|
|
121
|
-
function handleSingleLine(content, exclusions, warnings, filePath, lineNum) {
|
|
122
|
-
// Skip if this was a block start or end (already handled above, but guard)
|
|
123
|
-
if (content.startsWith('-start') || content.startsWith('-end'))
|
|
124
|
-
return;
|
|
125
|
-
const { ruleIds, reason } = parseRuleIdsAndReason(content);
|
|
126
|
-
if (reason === '') {
|
|
127
|
-
warnUndocumented(warnings, ruleIds, 'eess-exclude', filePath, lineNum);
|
|
128
|
-
}
|
|
129
|
-
for (const ruleId of ruleIds) {
|
|
130
|
-
exclusions.push({
|
|
131
|
-
ruleId,
|
|
132
|
-
reason,
|
|
133
|
-
file: filePath,
|
|
134
|
-
line: lineNum,
|
|
135
|
-
isBlock: false,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Scan a source file for eess-ts exclusion comments.
|
|
141
|
-
*
|
|
142
|
-
* Supported formats:
|
|
143
|
-
* // eess-exclude <rule-id>: <reason>
|
|
144
|
-
* // eess-exclude-start <rule-id>: <reason>
|
|
145
|
-
* // eess-exclude-end
|
|
146
|
-
* // eess-exclude <rule-a>, <rule-b>: <reason>
|
|
147
|
-
*/
|
|
148
|
-
/**
|
|
149
|
-
* Every string-like literal, blanked — [ts-archunit bug 0043](https://github.com/nielspeter/ts-archunit/blob/main/bugs/fixed/0043-an-exclusion-directive-inside-a-string-literal-suppresses.md).
|
|
150
|
-
*
|
|
151
|
-
* The scan below is line-based, and a line-based scan cannot tell a directive
|
|
152
|
-
* from the same characters inside a string. Measured before this existed: all
|
|
153
|
-
* three of `"…"`, `'…'` and `` `…` `` containing the directive text produced a
|
|
154
|
-
* **live exclusion** that silenced a real finding — silently, because a
|
|
155
|
-
* directive carrying a reason never triggers the undocumented-exclusion warning.
|
|
156
|
-
*
|
|
157
|
-
* **Newlines are preserved**, and that is the load-bearing part: the scan below
|
|
158
|
-
* is line-based and reports `line` on every exclusion, so a mask that dropped a
|
|
159
|
-
* newline would misreport every directive after it.
|
|
160
|
-
*
|
|
161
|
-
* Characters are replaced with spaces rather than removed, which keeps
|
|
162
|
-
* intra-line offsets stable too — but nothing downstream consumes a column, so
|
|
163
|
-
* that half is defence in depth rather than a guarded property. Measured:
|
|
164
|
-
* collapsing the blanks to `''`, and masking one character short, both leave the
|
|
165
|
-
* suite green. Recorded rather than dressed up — a sabotage row that survives
|
|
166
|
-
* for a real reason is a different thing from a missing guard.
|
|
167
|
-
*
|
|
168
|
-
* ## Why a parse, and not a scan
|
|
169
|
-
*
|
|
170
|
-
* The first attempt used `ts.createScanner`, which is the real lexer and fixed
|
|
171
|
-
* the three plain cases. It left two: `` `${x} // …` `` and JSX text. A bare
|
|
172
|
-
* scanner has no parser context, so it cannot know when to re-scan a template
|
|
173
|
-
* middle or JSX children, and both were classified as code — meaning the `//`
|
|
174
|
-
* inside them became a comment. Measured, not predicted.
|
|
175
|
-
*
|
|
176
|
-
* So: parse, and blank the literals. Everything remaining is code, where `//`
|
|
177
|
-
* genuinely does start a comment.
|
|
178
|
-
*
|
|
179
|
-
* A **ts-morph** project rather than the raw compiler API, per
|
|
180
|
-
* [ADR-002](../../../../adr/002-ts-morph-ast-engine.md), reusing one in-memory project
|
|
181
|
-
* across calls so the cost is a parse rather than a project construction. The
|
|
182
|
-
* whole scan is gated on a rule having already produced a violation in the file,
|
|
183
|
-
* so nothing is parsed for a clean run.
|
|
184
|
-
*
|
|
185
|
-
* A `TemplateExpression` is blanked **whole**, including its `${…}`
|
|
186
|
-
* substitutions. A comment is legal inside a substitution, so this can miss a
|
|
187
|
-
* real directive there — it errs toward *not* suppressing, which is the safe
|
|
188
|
-
* direction for a mechanism whose failure mode is a silent green.
|
|
189
|
-
*/
|
|
190
|
-
const LITERAL_KINDS = [
|
|
191
|
-
SyntaxKind.StringLiteral,
|
|
192
|
-
SyntaxKind.NoSubstitutionTemplateLiteral,
|
|
193
|
-
SyntaxKind.TemplateExpression,
|
|
194
|
-
SyntaxKind.RegularExpressionLiteral,
|
|
195
|
-
SyntaxKind.JsxText,
|
|
196
|
-
];
|
|
197
|
-
let scratch;
|
|
198
|
-
function withoutLiterals(sourceText, filePath) {
|
|
199
|
-
scratch ??= new Project({ useInMemoryFileSystem: true });
|
|
200
|
-
// `.tsx` so JSX parses; a `.ts` parse reads `<div>` as a type assertion and
|
|
201
|
-
// the JsxText case silently stops being covered.
|
|
202
|
-
const sourceFile = scratch.createSourceFile(`/scan/${path.basename(filePath)}.tsx`, sourceText, {
|
|
203
|
-
overwrite: true,
|
|
204
|
-
});
|
|
205
|
-
const out = sourceText.split('');
|
|
206
|
-
for (const kind of LITERAL_KINDS) {
|
|
207
|
-
for (const node of sourceFile.getDescendantsOfKind(kind)) {
|
|
208
|
-
for (let i = node.getStart(); i < node.getEnd(); i++) {
|
|
209
|
-
if (out[i] !== undefined && out[i] !== '\n')
|
|
210
|
-
out[i] = ' ';
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
const withoutLiteralText = out.join('');
|
|
215
|
-
// Block comments too, and this is not tidying — it is the difference between
|
|
216
|
-
// documenting the feature and invoking it.
|
|
217
|
-
//
|
|
218
|
-
// The grammar is `//`-only and always has been (a `/* … */` directive produced
|
|
219
|
-
// no exclusion before this fix and still produces none). But a JSDoc block
|
|
220
|
-
// that *mentions* the directive in prose puts the characters on a line, and
|
|
221
|
-
// the line scan below cannot tell prose from a directive.
|
|
222
|
-
//
|
|
223
|
-
// Found the hard way: this very file's docstring explains the bug, contains
|
|
224
|
-
// the directive text, and the moment comments started being read correctly it
|
|
225
|
-
// declared a live exclusion against `preset/boundaries/no-cross-boundary` —
|
|
226
|
-
// caught by this repo's own preset fan-out test. Any user writing a code
|
|
227
|
-
// comment about the feature would hit the same thing.
|
|
228
|
-
//
|
|
229
|
-
// Safe to do with a regex here, and only here: every string, template and
|
|
230
|
-
// regex literal has already been blanked, so a surviving `/*` is a real
|
|
231
|
-
// block-comment start.
|
|
232
|
-
return withoutLiteralText.replace(/\/\*[\s\S]*?\*\//g, (m) => m.replace(/[^\n]/g, ' '));
|
|
233
|
-
}
|
|
1
|
+
import { parseExclusionComments as parseShared, isExcludedByComment as isExcludedShared, } from '@nielspeter/eess';
|
|
2
|
+
import { maskTsLiterals } from './ts-comment-mask.js';
|
|
234
3
|
export function parseExclusionComments(sourceText, filePath) {
|
|
235
|
-
|
|
236
|
-
const lines = withoutLiterals(sourceText, filePath).split('\n');
|
|
237
|
-
const exclusions = [];
|
|
238
|
-
const warnings = [];
|
|
239
|
-
// A STACK of frames, one per `-start` line, each holding that line's rule ids.
|
|
240
|
-
// One `-end` closes one frame. A single-level block behaves exactly as before;
|
|
241
|
-
// nesting now works instead of silently mangling both regions.
|
|
242
|
-
const frames = [];
|
|
243
|
-
for (let i = 0; i < lines.length; i++) {
|
|
244
|
-
const line = lines[i];
|
|
245
|
-
if (line === undefined)
|
|
246
|
-
continue;
|
|
247
|
-
const lineNum = i + 1;
|
|
248
|
-
// Slice from the comment start. Literals are already blanked, so the first
|
|
249
|
-
// `//` on the line is a real comment opener — and anything before it is
|
|
250
|
-
// code, which cannot contain a directive.
|
|
251
|
-
const commentStart = line.indexOf('//');
|
|
252
|
-
if (commentStart === -1)
|
|
253
|
-
continue;
|
|
254
|
-
const comment = line.slice(commentStart);
|
|
255
|
-
// Check block end first (before start/single so we don't match -start as single)
|
|
256
|
-
if (BLOCK_END_RE.test(comment)) {
|
|
257
|
-
handleBlockEnd(frames, exclusions, warnings, filePath, lineNum);
|
|
258
|
-
continue;
|
|
259
|
-
}
|
|
260
|
-
// Check block start
|
|
261
|
-
const startMatch = BLOCK_START_RE.exec(comment);
|
|
262
|
-
if (startMatch?.[1]) {
|
|
263
|
-
handleBlockStart(startMatch[1], frames, warnings, filePath, lineNum);
|
|
264
|
-
continue;
|
|
265
|
-
}
|
|
266
|
-
// Check single-line exclude (must not match block directives)
|
|
267
|
-
const singleMatch = SINGLE_LINE_RE.exec(comment);
|
|
268
|
-
if (singleMatch?.[1]) {
|
|
269
|
-
handleSingleLine(singleMatch[1], exclusions, warnings, filePath, lineNum);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
// Any unclosed frame is an error, and pushes no exclusion — so an unterminated
|
|
273
|
-
// block fails closed: the violation it meant to cover still fires.
|
|
274
|
-
for (const comment of frames.flat()) {
|
|
275
|
-
warnings.push({
|
|
276
|
-
message: `eess-exclude-start without matching end for rule '${comment.ruleId}'`,
|
|
277
|
-
file: filePath,
|
|
278
|
-
line: comment.line,
|
|
279
|
-
kind: 'malformed',
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
return { exclusions, warnings };
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* Check if a violation is covered by an exclusion comment.
|
|
286
|
-
*
|
|
287
|
-
* For single-line comments: the violation must be in the same file and
|
|
288
|
-
* on the line immediately after the comment.
|
|
289
|
-
*
|
|
290
|
-
* For block comments: the violation must be in the same file and
|
|
291
|
-
* within the line range (start line, end line) inclusive.
|
|
292
|
-
*/
|
|
293
|
-
/** Check if a single comment covers the given violation. */
|
|
294
|
-
function commentCoversViolation(comment, violationLine) {
|
|
295
|
-
if (comment.isBlock) {
|
|
296
|
-
return (comment.endLine !== undefined &&
|
|
297
|
-
violationLine >= comment.line &&
|
|
298
|
-
violationLine <= comment.endLine);
|
|
299
|
-
}
|
|
300
|
-
return violationLine === comment.line + 1;
|
|
301
|
-
}
|
|
302
|
-
export function isExcludedByComment(violation, comments) {
|
|
303
|
-
const ruleId = violation.ruleId;
|
|
304
|
-
if (!ruleId)
|
|
305
|
-
return false;
|
|
306
|
-
return comments.some((comment) => comment.ruleId === ruleId &&
|
|
307
|
-
comment.file === violation.file &&
|
|
308
|
-
commentCoversViolation(comment, violation.line));
|
|
4
|
+
return parseShared(sourceText, filePath, { mask: maskTsLiterals });
|
|
309
5
|
}
|
|
6
|
+
export const isExcludedByComment = isExcludedShared;
|
|
310
7
|
//# sourceMappingURL=exclusion-comments.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exclusion-comments.js","sourceRoot":"","sources":["../../src/core/exclusion-comments.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"exclusion-comments.js","sourceRoot":"","sources":["../../src/core/exclusion-comments.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,IAAI,WAAW,EACrC,mBAAmB,IAAI,gBAAgB,GACxC,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAiBrD,MAAM,UAAU,sBAAsB,CAAC,UAAkB,EAAE,QAAgB;IACzE,OAAO,WAAW,CAAC,UAAU,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAA;AACpE,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,gBAAgB,CAAA"}
|
|
@@ -9,6 +9,14 @@ import type { EdgeCoverage } from '@nielspeter/eess';
|
|
|
9
9
|
*/
|
|
10
10
|
interface ExecuteRuleContext {
|
|
11
11
|
reason?: string;
|
|
12
|
+
/**
|
|
13
|
+
* This rule's own sentence, deferred (bug 0258).
|
|
14
|
+
*
|
|
15
|
+
* A thunk rather than a string because `filterContext()` runs on every
|
|
16
|
+
* terminal call and this is only read when an id-less rule turns out to have
|
|
17
|
+
* an exclusion comment it cannot honour.
|
|
18
|
+
*/
|
|
19
|
+
describe?: () => string;
|
|
12
20
|
metadata?: RuleMetadata;
|
|
13
21
|
exclusions?: (string | RegExp)[];
|
|
14
22
|
silentIndices?: Set<number>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute-rule.d.ts","sourceRoot":"","sources":["../../src/core/execute-rule.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAOrD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"execute-rule.d.ts","sourceRoot":"","sources":["../../src/core/execute-rule.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAOrD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAYpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAEpD;;;;GAIG;AACH,UAAU,kBAAkB;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,MAAM,CAAA;IACvB,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB,UAAU,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;IAChC,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,aAAa,EAAE,EAC3B,GAAG,EAAE,kBAAkB,GACtB,aAAa,EAAE,CAqXjB;AAeD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,aAAa,EAAE,EAC3B,MAAM,CAAC,EAAE,YAAY,EACrB,MAAM,CAAC,EAAE,MAAM;AACf,8EAA8E;AAC9E,QAAQ,GAAE,SAAS,YAAY,EAAO,GACrC,IAAI,CAoBN;AAwBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,qBAAqB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAQ/E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,aAAa,EAAE,EAC3B,GAAG,EAAE,kBAAkB,EACvB,OAAO,CAAC,EAAE,YAAY,GACrB,IAAI,CAqCN;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,aAAa,EAAE,EAC3B,GAAG,EAAE,kBAAkB,EACvB,OAAO,CAAC,EAAE,YAAY,GACrB,IAAI,CA+DN"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import { severityFor, disambiguateIdentities, byCodepoint, violationsEmittedCount, } from '@nielspeter/eess';
|
|
2
|
+
import { severityFor, disambiguateIdentities, byCodepoint, violationsEmittedCount, } from '@nielspeter/eess/internal';
|
|
3
3
|
import { ArchRuleError } from '@nielspeter/eess';
|
|
4
4
|
import { formatViolations } from '@nielspeter/eess';
|
|
5
5
|
import { formatViolationsJson } from '@nielspeter/eess';
|
|
6
|
-
import { activeNotice } from '@nielspeter/eess';
|
|
6
|
+
import { activeNotice } from '@nielspeter/eess/internal';
|
|
7
7
|
import { formatViolationsGitHub } from '@nielspeter/eess';
|
|
8
8
|
import { parseExclusionComments, isExcludedByComment } from './exclusion-comments.js';
|
|
9
|
-
import { UNSUPPRESSABLE } from '@nielspeter/eess';
|
|
10
|
-
import { recordCommentSuppression } from '@nielspeter/eess';
|
|
11
|
-
import { writeStderr } from '@nielspeter/eess';
|
|
9
|
+
import { UNSUPPRESSABLE } from '@nielspeter/eess/internal';
|
|
10
|
+
import { recordCommentSuppression } from '@nielspeter/eess/internal';
|
|
11
|
+
import { writeStderr } from '@nielspeter/eess/internal';
|
|
12
12
|
/**
|
|
13
13
|
* Complete each violation's identity, then apply `.excluding()` patterns and
|
|
14
14
|
* inline exclusion comments.
|
|
@@ -201,8 +201,17 @@ export function applyFilters(violations, ctx) {
|
|
|
201
201
|
}
|
|
202
202
|
});
|
|
203
203
|
}
|
|
204
|
-
// Scan source files for inline exclusion comments
|
|
205
|
-
|
|
204
|
+
// Scan source files for inline exclusion comments.
|
|
205
|
+
//
|
|
206
|
+
// **Not gated on `ctx.metadata?.id` (bug 0255).** A comment matches by rule
|
|
207
|
+
// id, so a chain without `.rule({ id })` can never honour one — and while the
|
|
208
|
+
// scan was gated on the id, the file was not even parsed, so nothing could
|
|
209
|
+
// say so. This is the second of the two copies: the kernel's got the same
|
|
210
|
+
// change, and review caught that landing it in one and claiming "eess now
|
|
211
|
+
// prints…" was a false green for the dialect adopters actually install
|
|
212
|
+
// (plan 0188 tracks the duplication itself; this is not the commit that
|
|
213
|
+
// fixes it, but it is not the commit that widens it either).
|
|
214
|
+
if (result.length > 0) {
|
|
206
215
|
const undocumented = [];
|
|
207
216
|
const filePaths = new Set(result.map((v) => v.file));
|
|
208
217
|
const allComments = [...filePaths].flatMap((filePath) => {
|
|
@@ -233,7 +242,10 @@ export function applyFilters(violations, ctx) {
|
|
|
233
242
|
// The malformed shapes are different — two of the three decline to
|
|
234
243
|
// create the exclusion at all, so the original violation still fires
|
|
235
244
|
// and the build is already red. A line on stderr is right for those.
|
|
236
|
-
if (warning.kind === 'undocumented') {
|
|
245
|
+
if (warning.kind === 'undocumented' && ctx.metadata?.id !== undefined) {
|
|
246
|
+
// The promotion below is keyed on the rule id; without one there is
|
|
247
|
+
// nothing to key it on, and the directive is inert anyway — which
|
|
248
|
+
// the inert report states, with a remedy. So it falls to stderr.
|
|
237
249
|
undocumented.push(warning);
|
|
238
250
|
continue;
|
|
239
251
|
}
|
|
@@ -254,7 +266,8 @@ export function applyFilters(violations, ctx) {
|
|
|
254
266
|
return [];
|
|
255
267
|
}
|
|
256
268
|
});
|
|
257
|
-
|
|
269
|
+
const ruleIdForComments = ctx.metadata?.id;
|
|
270
|
+
if (allComments.length > 0 && ruleIdForComments !== undefined) {
|
|
258
271
|
// `v.bypassFilters` explicitly, not by accident. These findings are
|
|
259
272
|
// immune today only because they carry `file: ''`, which the guard above
|
|
260
273
|
// returns no exclusions for, so `comment.file === ''` can never hold.
|
|
@@ -264,6 +277,10 @@ export function applyFilters(violations, ctx) {
|
|
|
264
277
|
// `// eess-exclude` comments ARE parsed. Without the first clause
|
|
265
278
|
// a comment in a rule file would silence the finding that says the rule
|
|
266
279
|
// enforces nothing. Pinned by tests/helpers/exclusion-comments.ts.
|
|
280
|
+
// Which comments actually did something, so the ones that did nothing can
|
|
281
|
+
// be named. Reuses `isExcludedByComment` one comment at a time rather than
|
|
282
|
+
// re-deriving the match, so it cannot drift from the real rule.
|
|
283
|
+
const spent = new Set();
|
|
267
284
|
result = result.filter((v) => {
|
|
268
285
|
if (v.bypassFilters === true)
|
|
269
286
|
return true;
|
|
@@ -272,8 +289,70 @@ export function applyFilters(violations, ctx) {
|
|
|
272
289
|
// Disclose it. Silently dropping is what made this the only filter in
|
|
273
290
|
// the pipeline a reader could not see — see `comment-suppression.ts`.
|
|
274
291
|
recordCommentSuppression(v.ruleId ?? ctx.metadata?.id ?? '(unnamed rule)', v.file);
|
|
292
|
+
for (const c of allComments)
|
|
293
|
+
if (isExcludedByComment(v, [c]))
|
|
294
|
+
spent.add(c);
|
|
275
295
|
return false;
|
|
276
296
|
});
|
|
297
|
+
// A directive naming THIS rule that suppressed nothing — the same shape
|
|
298
|
+
// and weight as the `.excluding()` "Unused exclusion" line above.
|
|
299
|
+
for (const c of allComments) {
|
|
300
|
+
if (c.ruleId !== ruleIdForComments || spent.has(c))
|
|
301
|
+
continue;
|
|
302
|
+
writeStderr(`[eess] Exclusion comment for '${ruleIdForComments}' at ${c.file}:${String(c.line)} ` +
|
|
303
|
+
`suppressed nothing. It may be stale, or out of reach: a single-line ` +
|
|
304
|
+
`directive covers only the NEXT line. eess-exclude-start/-end covers a ` +
|
|
305
|
+
`region instead.`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
else if (allComments.length > 0) {
|
|
309
|
+
// No rule id, so nothing here can match. It states the fact and names no
|
|
310
|
+
// id: a directive in this file may belong to another, working rule, and
|
|
311
|
+
// from inside one rule's run there is no way to tell (review reproduced
|
|
312
|
+
// the harm of guessing — it produced advice to collide two rules on one
|
|
313
|
+
// id). One line per file, not per comment.
|
|
314
|
+
const byFile = new Map();
|
|
315
|
+
for (const c of allComments) {
|
|
316
|
+
const lines = byFile.get(c.file);
|
|
317
|
+
if (lines)
|
|
318
|
+
lines.push(c.line);
|
|
319
|
+
else
|
|
320
|
+
byFile.set(c.file, [c.line]);
|
|
321
|
+
}
|
|
322
|
+
// Name the rule, preferring its own sentence over its reason (bug 0258).
|
|
323
|
+
//
|
|
324
|
+
// The first version used `.because()` alone, on the premise that no rule
|
|
325
|
+
// description was reachable here. Review measured that false: every
|
|
326
|
+
// builder implements `describeRule()`, `filterContext()` is a method on
|
|
327
|
+
// the class that has it, and the kernel already names an id-less rule this
|
|
328
|
+
// way for its assertion-less finding. `.because()` is optional prose — the
|
|
329
|
+
// chains this diagnostic targets often have neither an id nor a reason —
|
|
330
|
+
// so leaning on it alone was a weaker floor for the same cost.
|
|
331
|
+
//
|
|
332
|
+
// `'unnamed'` is `TerminalBuilder`'s own fallback for a rule with no id;
|
|
333
|
+
// naming a rule "unnamed" tells the reader nothing, so it counts as absent
|
|
334
|
+
// and the reason takes over. Whitespace is collapsed either way: both are
|
|
335
|
+
// prose that may wrap, and this report is one line per file.
|
|
336
|
+
// Collapse to one line, and escape the delimiter. A `.because()` reason is
|
|
337
|
+
// arbitrary prose, so one containing a quoted term rendered as
|
|
338
|
+
// `("ignore the "legacy" path")` — three quotes before the paren, and no
|
|
339
|
+
// way for a reader to see where the label ends. Escaping keeps the
|
|
340
|
+
// author's words exact where replacing them would not.
|
|
341
|
+
const oneLine = (t) => t.replace(/\s+/g, ' ').trim().replace(/"/g, '\\"');
|
|
342
|
+
const described = ctx.describe?.();
|
|
343
|
+
const label = described !== undefined && described !== 'unnamed' && described !== ''
|
|
344
|
+
? oneLine(described)
|
|
345
|
+
: ctx.reason === undefined
|
|
346
|
+
? undefined
|
|
347
|
+
: oneLine(ctx.reason);
|
|
348
|
+
const named = label === undefined || label === '' ? '' : ` ("${label}")`;
|
|
349
|
+
for (const [file, lines] of byFile) {
|
|
350
|
+
const where = lines.length === 1 ? `line ${String(lines[0])}` : `lines ${lines.join(', ')}`;
|
|
351
|
+
writeStderr(`[eess] This rule${named} declares no id, so no exclusion comment can apply to it — ` +
|
|
352
|
+
`a comment matches a violation by rule id. ${file} has a directive at ${where}. ` +
|
|
353
|
+
`If one was meant for this rule, give the rule an id with .rule({ id: '<your-id>' }); ` +
|
|
354
|
+
`directives naming other rules are not this rule's to honour.`);
|
|
355
|
+
}
|
|
277
356
|
}
|
|
278
357
|
// The exemption stands; what fails is the missing justification. That is
|
|
279
358
|
// deliberate and it is what makes the remedy remediable: add a reason and
|
|
@@ -284,16 +363,23 @@ export function applyFilters(violations, ctx) {
|
|
|
284
363
|
//
|
|
285
364
|
// Unsuppressable, because a suppression mechanism that can suppress the
|
|
286
365
|
// complaint about itself is not a mechanism.
|
|
366
|
+
//
|
|
367
|
+
// `undocumented` is only populated when the rule HAS an id (the push above
|
|
368
|
+
// is guarded on it), so this loop is unreachable without one — the local
|
|
369
|
+
// re-binding is what tells the compiler that, after bug 0255 removed the
|
|
370
|
+
// outer `ctx.metadata?.id` gate.
|
|
287
371
|
for (const warning of undocumented) {
|
|
372
|
+
if (ruleIdForComments === undefined)
|
|
373
|
+
continue;
|
|
288
374
|
result.push({
|
|
289
|
-
rule:
|
|
290
|
-
ruleId:
|
|
291
|
-
element: `${
|
|
375
|
+
rule: ruleIdForComments,
|
|
376
|
+
ruleId: ruleIdForComments,
|
|
377
|
+
element: `${ruleIdForComments}@${warning.file}:${String(warning.line)}`,
|
|
292
378
|
file: warning.file,
|
|
293
379
|
line: warning.line,
|
|
294
380
|
message: `This exclusion states no reason, so nothing records why the rule is ` +
|
|
295
381
|
`waived here — and it is silently suppressing a real finding.`,
|
|
296
|
-
suggestion: `Add a reason: // eess-exclude ${
|
|
382
|
+
suggestion: `Add a reason: // eess-exclude ${ruleIdForComments}: <why>. ` +
|
|
297
383
|
`A reason is prose and nothing verifies it, so this raises the cost of a ` +
|
|
298
384
|
`suppression rather than preventing one — the audience is the reviewer ` +
|
|
299
385
|
`reading the diff. If the exemption is not justifiable, delete it and fix ` +
|