pi-lens 3.8.74 → 4.0.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/CHANGELOG.md +2440 -954
- package/README.md +13 -0
- package/dist/clients/actionable-warnings.js +73 -18
- package/dist/clients/agent-behavior-client.js +21 -4
- package/dist/clients/ast-grep-client.js +68 -16
- package/dist/clients/ast-grep-types.js +0 -1
- package/dist/clients/ast-grep-yaml-synth.js +37 -10
- package/dist/clients/atomic-write-staging.js +63 -0
- package/dist/clients/atomic-write.js +114 -14
- package/dist/clients/bash-file-access.js +193 -23
- package/dist/clients/biome-client.js +29 -25
- package/dist/clients/bootstrap.js +11 -2
- package/dist/clients/bounded-cache.js +34 -0
- package/dist/clients/bounded-pid-file-lock.js +192 -0
- package/dist/clients/bus-publish.js +10 -3
- package/dist/clients/cache/rule-cache.js +47 -5
- package/dist/clients/cache-manager.js +97 -9
- package/dist/clients/cache-observability.js +301 -14
- package/dist/clients/call-graph.js +449 -117
- package/dist/clients/child-unref.js +85 -0
- package/dist/clients/codebase-model.js +52 -23
- package/dist/clients/collateral-test-role.js +40 -0
- package/dist/clients/complexity-client.js +2 -1
- package/dist/clients/console-guard-install.js +14 -0
- package/dist/clients/cooperative-budget.js +42 -0
- package/dist/clients/dead-code-client.js +2 -1
- package/dist/clients/debug-handles.js +206 -0
- package/dist/clients/debug-heap.js +167 -0
- package/dist/clients/degradation-ledger.js +153 -0
- package/dist/clients/dependency-checker.js +347 -75
- package/dist/clients/diagnostic-dispositions.js +61 -11
- package/dist/clients/diagnostics-publish.js +10 -3
- package/dist/clients/dispatch/dispatcher.js +63 -20
- package/dist/clients/dispatch/facts/function-facts.js +23 -7
- package/dist/clients/dispatch/facts/import-facts.js +8 -18
- package/dist/clients/dispatch/facts/tree-sitter-facts.js +8 -5
- package/dist/clients/dispatch/indent-detect.js +35 -0
- package/dist/clients/dispatch/inline-suppressions.js +17 -8
- package/dist/clients/dispatch/integration.js +1085 -681
- package/dist/clients/dispatch/lazy.js +14 -0
- package/dist/clients/dispatch/plan.js +11 -1
- package/dist/clients/dispatch/rule-id-normalize.js +50 -0
- package/dist/clients/dispatch/rule-policy.js +135 -0
- package/dist/clients/dispatch/runners/ast-grep-napi.js +23 -5
- package/dist/clients/dispatch/runners/biome-check.js +5 -9
- package/dist/clients/dispatch/runners/detekt.js +3 -2
- package/dist/clients/dispatch/runners/hadolint.js +2 -1
- package/dist/clients/dispatch/runners/helm-lint.js +154 -0
- package/dist/clients/dispatch/runners/htmlhint.js +3 -2
- package/dist/clients/dispatch/runners/index.js +5 -1
- package/dist/clients/dispatch/runners/lsp.js +14 -6
- package/dist/clients/dispatch/runners/markdownlint.js +4 -9
- package/dist/clients/dispatch/runners/pyright.js +9 -5
- package/dist/clients/dispatch/runners/ruff.js +4 -8
- package/dist/clients/dispatch/runners/shellcheck.js +2 -3
- package/dist/clients/dispatch/runners/shfmt.js +2 -3
- package/dist/clients/dispatch/runners/spotbugs.js +2 -1
- package/dist/clients/dispatch/runners/taplo.js +2 -1
- package/dist/clients/dispatch/runners/terragrunt.js +163 -0
- package/dist/clients/dispatch/runners/tflint.js +37 -5
- package/dist/clients/dispatch/runners/tree-sitter.js +3 -1
- package/dist/clients/dispatch/runners/trivy-config.js +13 -7
- package/dist/clients/dispatch/runners/utils/lazy-installer.js +3 -0
- package/dist/clients/dispatch/runners/utils/runner-helpers.js +277 -26
- package/dist/clients/dispatch/runners/utils/spawn-outcome.js +22 -0
- package/dist/clients/dispatch/runners/yaml-rule-parser.js +5 -4
- package/dist/clients/disposition-publish.js +10 -3
- package/dist/clients/durable-store.js +97 -0
- package/dist/clients/event-loop-monitor.js +94 -3
- package/dist/clients/extension-log.js +139 -0
- package/dist/clients/extension-mode.js +73 -0
- package/dist/clients/file-kinds.js +57 -0
- package/dist/clients/file-role.js +18 -3
- package/dist/clients/file-utils.js +56 -34
- package/dist/clients/format-events-publish.js +16 -3
- package/dist/clients/format-service.js +24 -8
- package/dist/clients/formatters-lazy.js +8 -0
- package/dist/clients/formatters.js +358 -61
- package/dist/clients/generated-artifacts.js +148 -15
- package/dist/clients/git-guard.js +681 -11
- package/dist/clients/git-tracked-ignore.js +4 -0
- package/dist/clients/go-client.js +2 -1
- package/dist/clients/govulncheck-client.js +8 -0
- package/dist/clients/grammar-source.js +12 -4
- package/dist/clients/gzip-stage-write.js +21 -3
- package/dist/clients/host-ports.js +31 -0
- package/dist/clients/installer/index.js +390 -99
- package/dist/clients/instance-reaper.js +142 -172
- package/dist/clients/jscpd-client.js +31 -54
- package/dist/clients/knip-client.js +15 -36
- package/dist/clients/language-policy.js +14 -2
- package/dist/clients/language-profile.js +13 -7
- package/dist/clients/latency-logger.js +23 -1
- package/dist/clients/lens-config.js +12 -1
- package/dist/clients/lens-engine.js +86 -17
- package/dist/clients/lens-events.js +27 -4
- package/dist/clients/lens-flag-registry.js +8 -0
- package/dist/clients/lens-map.js +94 -19
- package/dist/clients/live-bus-emitter.js +30 -0
- package/dist/clients/log-cleanup.js +2 -1
- package/dist/clients/lsp/cascade-tier.js +1 -1
- package/dist/clients/lsp/client.js +493 -48
- package/dist/clients/lsp/config.js +13 -2
- package/dist/clients/lsp/diagnostic-binding.js +86 -0
- package/dist/clients/lsp/edits.js +1012 -121
- package/dist/clients/lsp/index.js +1807 -780
- package/dist/clients/lsp/launch.js +32 -26
- package/dist/clients/lsp/path-utils.js +1 -1
- package/dist/clients/lsp/ruby-drive-dirs.js +83 -0
- package/dist/clients/lsp/server.js +196 -32
- package/dist/clients/lsp/workspace-diagnostics-cache.js +28 -4
- package/dist/clients/lsp-lazy.js +8 -0
- package/dist/clients/lsp-mutation.js +248 -0
- package/dist/clients/mcp/analyze.js +123 -32
- package/dist/clients/mcp/ipc.js +157 -24
- package/dist/clients/mcp/session.js +216 -8
- package/dist/clients/memory-sampler.js +115 -0
- package/dist/clients/metrics-client.js +2 -1
- package/dist/clients/metrics-history.js +2 -1
- package/dist/clients/module-report-lsp.js +5 -0
- package/dist/clients/module-report.js +168 -3
- package/dist/clients/ndjson-logger.js +319 -118
- package/dist/clients/opengrep-client.js +1 -1
- package/dist/clients/partial-edit-apply.js +120 -5
- package/dist/clients/path-utils.js +110 -9
- package/dist/clients/pipeline.js +47 -13
- package/dist/clients/print-mode.js +21 -0
- package/dist/clients/project-changes.js +40 -0
- package/dist/clients/project-diagnostics/cache.js +3 -2
- package/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +8 -0
- package/dist/clients/project-diagnostics/scanner.js +21 -1
- package/dist/clients/project-lens-config.js +86 -9
- package/dist/clients/project-report.js +27 -13
- package/dist/clients/project-snapshot.js +175 -20
- package/dist/clients/project-trust.js +181 -0
- package/dist/clients/quiet-window.js +18 -4
- package/dist/clients/read-bridge.js +147 -0
- package/dist/clients/read-guard-logger.js +159 -1
- package/dist/clients/read-guard-tool-lines.js +150 -29
- package/dist/clients/read-guard.js +185 -4
- package/dist/clients/resource-sampler.js +70 -84
- package/dist/clients/review-graph/builder.js +1122 -221
- package/dist/clients/review-graph/git-identity.js +2 -1
- package/dist/clients/review-graph/import-resolvers.js +21 -10
- package/dist/clients/review-graph/symbol-id.js +46 -0
- package/dist/clients/review-graph/tsconfig-paths.js +57 -6
- package/dist/clients/review-graph/workspace-modules.js +51 -3
- package/dist/clients/review-graph-logger.js +30 -1
- package/dist/clients/ruff-client.js +27 -44
- package/dist/clients/runtime-agent-end.js +107 -73
- package/dist/clients/runtime-context.js +36 -12
- package/dist/clients/runtime-coordinator.js +74 -6
- package/dist/clients/runtime-session.js +405 -117
- package/dist/clients/runtime-tool-call.js +71 -48
- package/dist/clients/runtime-tool-result.js +218 -23
- package/dist/clients/runtime-turn.js +237 -64
- package/dist/clients/rust-client.js +2 -1
- package/dist/clients/safe-spawn.js +777 -62
- package/dist/clients/security-scan-client.js +2 -1
- package/dist/clients/session-state-store.js +3 -2
- package/dist/clients/sg-runner.js +284 -174
- package/dist/clients/slow-fs.js +2 -1
- package/dist/clients/smells-rollup.js +224 -0
- package/dist/clients/source-filter.js +184 -20
- package/dist/clients/source-walker.js +66 -10
- package/dist/clients/startup-scan.js +15 -16
- package/dist/clients/startup-timing.js +1 -1
- package/dist/clients/test-runner-client.js +38 -8
- package/dist/clients/tool-event.js +35 -0
- package/dist/clients/tool-policy.js +388 -39
- package/dist/clients/tool-render.js +155 -0
- package/dist/clients/tree-sitter-cache.js +6 -1
- package/dist/clients/tree-sitter-client.js +419 -50
- package/dist/clients/tree-sitter-logger.js +21 -0
- package/dist/clients/tree-sitter-query-loader.js +7 -1
- package/dist/clients/tree-sitter-shared.js +7 -2
- package/dist/clients/tree-sitter-symbol-extractor.js +44 -7
- package/dist/clients/user-notify.js +51 -0
- package/dist/clients/vanished-instance-marker.js +57 -0
- package/dist/clients/warm-attach.js +33 -13
- package/dist/clients/widget-state.js +300 -43
- package/dist/clients/word-index.js +391 -64
- package/dist/clients/workspace-topology.js +89 -6
- package/dist/index.js +49361 -36888
- package/dist/mcp/analyze-cli.js +182 -29
- package/dist/mcp/server.js +211 -44
- package/dist/tools/ast-grep-search.js +93 -27
- package/dist/tools/lens-diagnostics.js +200 -36
- package/dist/tools/lsp-diagnostics.js +153 -40
- package/dist/tools/lsp-navigation.js +46 -3
- package/dist/tools/module-report.js +9 -0
- package/docs/agent-guide.md +2 -2
- package/docs/agent-tools.md +21 -10
- package/docs/analysisall.md +192 -0
- package/docs/api-ports-inventory.md +165 -0
- package/docs/ast-grep_rules_catalog.md +5 -2
- package/docs/durable-store-audit-1202.md +32 -0
- package/docs/environment-variables.md +44 -0
- package/docs/fable.md +27 -0
- package/docs/features.md +31 -2
- package/docs/globalconfig.md +45 -1
- package/docs/language-coverage.md +4 -3
- package/docs/lsp-capability-matrix.md +2 -2
- package/docs/mcp.md +37 -4
- package/docs/servercapabilities.md +3 -3
- package/docs/settings.md +12 -1
- package/docs/tools.md +4 -1
- package/docs/usage.md +18 -0
- package/package.json +10 -10
- package/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +49 -0
- package/rules/ast-grep-rules/rule-tests/no-bare-host-path-in-win32-branch-test.yml +87 -0
- package/rules/ast-grep-rules/rule-tests/no-nested-links-test.yml +11 -1
- package/rules/ast-grep-rules/rule-tests/no-raw-json-store-write-test.yml +17 -0
- package/rules/ast-grep-rules/rule-tests/no-win32-isabsolute-for-qualification-test.yml +16 -0
- package/rules/ast-grep-rules/rules/no-bare-except.yml +3 -15
- package/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +25 -0
- package/rules/ast-grep-rules/rules/no-nested-links.yml +7 -0
- package/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +30 -0
- package/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +23 -0
- package/rules/tree-sitter-queries/tsx/no-nested-links.yml +4 -6
- package/rules/tree-sitter-queries/typescript/duplicate-function-arg.yml +2 -2
- package/scripts/analyze-pi-lens-logs.mjs +55 -2
- package/dist/clients/ast-grep-parser.js +0 -86
- package/dist/clients/lsp/interactive-install.js +0 -367
- package/dist/clients/lsp/lsp-index.js +0 -10
- package/dist/clients/lsp/server-strategies.js +0 -5
- package/dist/clients/project-metadata.js +0 -690
- package/dist/clients/source-groups.js +0 -96
- package/dist/clients/startup-marker.js +0 -6
- package/dist/clients/types.js +0 -11
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
id: no-bare-host-path-in-win32-branch
|
|
2
|
+
language: TypeScript
|
|
3
|
+
severity: warning
|
|
4
|
+
message: "Use win32 path operations inside a branch committed to Windows path semantics"
|
|
5
|
+
note: |
|
|
6
|
+
A branch guarded by isWindowsPath/isFullyQualifiedWin32 has committed to
|
|
7
|
+
Windows path parsing. Host-default dirname/basename/join/relative/sep
|
|
8
|
+
follows the process OS and is wrong for a Windows-shaped path on POSIX.
|
|
9
|
+
|
|
10
|
+
SCOPE (review-verified, #1339): same-function consequence only. The
|
|
11
|
+
original #1150 defect — a bare dirname inside an UNGUARDED helper that
|
|
12
|
+
the guarded branch calls (cross-function) — is NOT reachable by this
|
|
13
|
+
engine and stays review-enforced via AGENTS.md defect-shape 2. The
|
|
14
|
+
rule's fixture file encodes that miss as a documented negative; flip it
|
|
15
|
+
to a positive only if cross-function reach is ever added. What this
|
|
16
|
+
rule does catch is the in-branch shape (#1152 class).
|
|
17
|
+
rule:
|
|
18
|
+
all:
|
|
19
|
+
- kind: if_statement
|
|
20
|
+
- has:
|
|
21
|
+
field: condition
|
|
22
|
+
regex: "\\b(isWindowsPath|isFullyQualifiedWin32)\\s*\\("
|
|
23
|
+
- has:
|
|
24
|
+
field: consequence
|
|
25
|
+
regex: "(?s)\\bpath\\.(dirname|basename|join|relative)\\s*\\(|\\bpath\\.sep\\b|(^|[^.])\\b(dirname|basename|join|relative)\\s*\\("
|
|
@@ -8,6 +8,12 @@ note: |
|
|
|
8
8
|
rule:
|
|
9
9
|
all:
|
|
10
10
|
- kind: jsx_element
|
|
11
|
+
- has:
|
|
12
|
+
field: open_tag
|
|
13
|
+
kind: jsx_opening_element
|
|
14
|
+
has:
|
|
15
|
+
field: name
|
|
16
|
+
regex: "^a$"
|
|
11
17
|
- has:
|
|
12
18
|
kind: jsx_element
|
|
13
19
|
stopBy: end
|
|
@@ -20,6 +26,7 @@ rule:
|
|
|
20
26
|
not:
|
|
21
27
|
inside:
|
|
22
28
|
kind: jsx_element
|
|
29
|
+
stopBy: end
|
|
23
30
|
has:
|
|
24
31
|
field: open_tag
|
|
25
32
|
kind: jsx_opening_element
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
id: no-raw-json-store-write
|
|
2
|
+
language: TypeScript
|
|
3
|
+
severity: warning
|
|
4
|
+
message: "Use the atomic write seam for JSON stores instead of writeFileSync"
|
|
5
|
+
note: |
|
|
6
|
+
JSON-backed durable state must be committed through clients/durable-store.ts
|
|
7
|
+
when read-modify-write isolation is required; that seam publishes through
|
|
8
|
+
clients/atomic-write.ts. This rule covers the direct
|
|
9
|
+
writeFileSync(path, JSON.stringify(data)) shape. Build scripts and the
|
|
10
|
+
installer's wx lock writes are intentionally outside this rule's scope.
|
|
11
|
+
ignores:
|
|
12
|
+
- "**/clients/atomic-write.ts"
|
|
13
|
+
- "**/clients/installer/index.ts"
|
|
14
|
+
- "**/scripts/**"
|
|
15
|
+
rule:
|
|
16
|
+
any:
|
|
17
|
+
- pattern: writeFileSync($PATH, JSON.stringify($$$ARGS))
|
|
18
|
+
- pattern: $FS.writeFileSync($PATH, JSON.stringify($$$ARGS))
|
|
19
|
+
- pattern: writeFileSync($PATH, JSON.stringify($$$ARGS), $OPTS)
|
|
20
|
+
- pattern: $FS.writeFileSync($PATH, JSON.stringify($$$ARGS), $OPTS)
|
|
21
|
+
- kind: expression_statement
|
|
22
|
+
has:
|
|
23
|
+
pattern: writeFileSync($PATH, $PAYLOAD)
|
|
24
|
+
follows:
|
|
25
|
+
pattern: const $PAYLOAD = JSON.stringify($DATA)
|
|
26
|
+
- kind: expression_statement
|
|
27
|
+
has:
|
|
28
|
+
pattern: $FS.writeFileSync($PATH, $PAYLOAD)
|
|
29
|
+
follows:
|
|
30
|
+
pattern: const $PAYLOAD = JSON.stringify($DATA)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
id: no-win32-isabsolute-for-qualification
|
|
2
|
+
language: TypeScript
|
|
3
|
+
severity: warning
|
|
4
|
+
message: "Use isFullyQualified for path qualification instead of win32.isAbsolute"
|
|
5
|
+
note: |
|
|
6
|
+
Qualification must follow the input path's shape. Use clients/path-utils.ts
|
|
7
|
+
isFullyQualified(), which distinguishes drive-absolute, UNC, rooted-relative,
|
|
8
|
+
POSIX-absolute, and relative paths across host operating systems. The
|
|
9
|
+
implementation of isFullyQualified itself is excluded because it is the
|
|
10
|
+
compatibility seam that owns the win32 parser call.
|
|
11
|
+
|
|
12
|
+
SCOPE (review-verified, #1349): direct call forms only --
|
|
13
|
+
path.win32.isAbsolute(...) and a destructured win32.isAbsolute(...). An
|
|
14
|
+
ALIASED parser (const w = path.win32; w.isAbsolute(p) -- the shape the
|
|
15
|
+
actual pre-#1330 defect used) is beyond the engine's reach and stays
|
|
16
|
+
review-enforced; the fixture file encodes that miss as a documented
|
|
17
|
+
negative, matching the #1339 precedent.
|
|
18
|
+
ignores:
|
|
19
|
+
- "**/clients/path-utils.ts"
|
|
20
|
+
rule:
|
|
21
|
+
any:
|
|
22
|
+
- pattern: path.win32.isAbsolute($P)
|
|
23
|
+
- pattern: win32.isAbsolute($P)
|
|
@@ -18,15 +18,13 @@ query: |
|
|
|
18
18
|
(jsx_element
|
|
19
19
|
open_tag: (jsx_opening_element
|
|
20
20
|
(identifier) @OUTER
|
|
21
|
-
(#eq? @OUTER "a"))
|
|
22
|
-
(jsx_element
|
|
23
|
-
open_tag: (jsx_opening_element
|
|
24
|
-
(identifier) @INNER
|
|
25
|
-
(#eq? @INNER "a"))))
|
|
21
|
+
(#eq? @OUTER "a"))) @OUTER_ELEMENT
|
|
26
22
|
|
|
27
23
|
metavars:
|
|
28
24
|
- OUTER
|
|
29
|
-
-
|
|
25
|
+
- OUTER_ELEMENT
|
|
26
|
+
|
|
27
|
+
post_filter: no_nested_anchor_chain
|
|
30
28
|
|
|
31
29
|
tags:
|
|
32
30
|
- correctness
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* ~/.pi-lens/cascade*.log JSONL impact-cascade logs
|
|
9
9
|
* ~/.pi-lens/read-guard*.log JSONL read-guard friction logs
|
|
10
10
|
* ~/.pi-lens/tree-sitter*.log JSONL structural runner logs
|
|
11
|
+
* ~/.pi-lens/extension*.log JSONL extension diagnostics and console-guard telemetry
|
|
11
12
|
* ~/.pi-lens/actionable-warnings*.log JSONL advisory pipeline (inject/suppress)
|
|
12
13
|
* ~/.pi-lens/ast-grep-tools*.log JSONL MCP ast-grep search/replace telemetry
|
|
13
14
|
* ~/.pi-lens/logs/*.jsonl JSONL diagnostic findings
|
|
@@ -18,10 +19,12 @@ import os from "node:os";
|
|
|
18
19
|
import path from "node:path";
|
|
19
20
|
import readline from "node:readline";
|
|
20
21
|
import { fileURLToPath } from "node:url";
|
|
22
|
+
import { minimatch } from "minimatch";
|
|
21
23
|
|
|
22
24
|
const DEFAULT_ROOT = path.join(os.homedir(), ".pi-lens");
|
|
23
25
|
const DEFAULT_SINCE = "2d";
|
|
24
26
|
const DEFAULT_LIMIT = 12;
|
|
27
|
+
const DEFAULT_EXCLUDE_GLOBS = ["**/AppData/Local/Temp/claude/**", "**/heap-corpus*/**", "**/.plegma/work/**"];
|
|
25
28
|
|
|
26
29
|
const args = parseArgs(process.argv.slice(2));
|
|
27
30
|
const root = path.resolve(expandHome(args.root ?? DEFAULT_ROOT));
|
|
@@ -30,6 +33,10 @@ const limit =
|
|
|
30
33
|
Number.parseInt(args.limit ?? `${DEFAULT_LIMIT}`, 10) || DEFAULT_LIMIT;
|
|
31
34
|
const outputJson = Boolean(args.json);
|
|
32
35
|
const includeArchived = Boolean(args.archived);
|
|
36
|
+
const excludeGlobs = [
|
|
37
|
+
...DEFAULT_EXCLUDE_GLOBS,
|
|
38
|
+
...(Array.isArray(args.exclude) ? args.exclude : args.exclude ? [args.exclude] : []),
|
|
39
|
+
];
|
|
33
40
|
|
|
34
41
|
const thresholds = {
|
|
35
42
|
startupSlowMs: Number.parseInt(args.startupSlowMs ?? "500", 10),
|
|
@@ -83,7 +90,14 @@ function parseArgs(argv) {
|
|
|
83
90
|
const key = arg.slice(2);
|
|
84
91
|
const next = argv[i + 1];
|
|
85
92
|
if (!next || next.startsWith("--")) out[key] = "true";
|
|
86
|
-
else
|
|
93
|
+
else if (key === "exclude") {
|
|
94
|
+
const value = argv[++i];
|
|
95
|
+
out.exclude = out.exclude
|
|
96
|
+
? Array.isArray(out.exclude)
|
|
97
|
+
? [...out.exclude, value]
|
|
98
|
+
: [out.exclude, value]
|
|
99
|
+
: value;
|
|
100
|
+
} else out[key] = argv[++i];
|
|
87
101
|
}
|
|
88
102
|
}
|
|
89
103
|
return out;
|
|
@@ -158,6 +172,7 @@ function createState(files) {
|
|
|
158
172
|
window: { since: since?.toISOString() ?? "all", root },
|
|
159
173
|
files,
|
|
160
174
|
parseErrors: counter(),
|
|
175
|
+
excludedRows: 0,
|
|
161
176
|
seen: counter(),
|
|
162
177
|
projects: counter(),
|
|
163
178
|
smellTotals: counter(),
|
|
@@ -557,6 +572,10 @@ async function analyzeSessionStart(files, state) {
|
|
|
557
572
|
const ts = dateOf(match[1]);
|
|
558
573
|
if (!inWindow(ts)) return;
|
|
559
574
|
const message = match[2];
|
|
575
|
+
if (isExcludedText(message)) {
|
|
576
|
+
state.excludedRows++;
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
560
579
|
state.seen.inc("sessionstart");
|
|
561
580
|
|
|
562
581
|
const cwd = /session_start cwd:\s*(.*)$/.exec(message)?.[1];
|
|
@@ -722,13 +741,45 @@ async function forEachJsonLine(file, bucket, state, visitor) {
|
|
|
722
741
|
await forEachLine(file, async (line) => {
|
|
723
742
|
if (!line.trim()) return;
|
|
724
743
|
try {
|
|
725
|
-
|
|
744
|
+
const entry = JSON.parse(line);
|
|
745
|
+
if (isExcludedEntry(entry)) {
|
|
746
|
+
state.excludedRows++;
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
visitor(entry);
|
|
726
750
|
} catch {
|
|
727
751
|
state.parseErrors.inc(`${bucket}:${path.basename(file)}`);
|
|
728
752
|
}
|
|
729
753
|
});
|
|
730
754
|
}
|
|
731
755
|
|
|
756
|
+
function isExcludedEntry(entry) {
|
|
757
|
+
return pathValues(entry).some((value) =>
|
|
758
|
+
excludeGlobs.some((glob) =>
|
|
759
|
+
minimatch(value, glob, { nocase: true, dot: true }),
|
|
760
|
+
),
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
function pathValues(value, key = "") {
|
|
765
|
+
if (typeof value === "string") {
|
|
766
|
+
return /(file|path|cwd|root|project)/i.test(key) ? [normalizePath(value)] : [];
|
|
767
|
+
}
|
|
768
|
+
if (!value || typeof value !== "object") return [];
|
|
769
|
+
return Object.entries(value).flatMap(([childKey, child]) =>
|
|
770
|
+
pathValues(child, childKey),
|
|
771
|
+
);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
function isExcludedText(text) {
|
|
775
|
+
const cwd = /session_start cwd:\s*(.*)$/.exec(text)?.[1];
|
|
776
|
+
return cwd
|
|
777
|
+
? excludeGlobs.some((glob) =>
|
|
778
|
+
minimatch(normalizePath(cwd), glob, { nocase: true, dot: true }),
|
|
779
|
+
)
|
|
780
|
+
: false;
|
|
781
|
+
}
|
|
782
|
+
|
|
732
783
|
async function forEachLine(file, visitor) {
|
|
733
784
|
if (!fs.existsSync(file)) return;
|
|
734
785
|
const rl = readline.createInterface({
|
|
@@ -1129,6 +1180,7 @@ function buildReport(state) {
|
|
|
1129
1180
|
Object.entries(state.files).map(([key, list]) => [key, list.length]),
|
|
1130
1181
|
),
|
|
1131
1182
|
rowsSeen: state.seen.toJSON(),
|
|
1183
|
+
rowsExcluded: state.excludedRows,
|
|
1132
1184
|
parseErrors: state.parseErrors.toJSON(),
|
|
1133
1185
|
projects: state.projects.top(limit),
|
|
1134
1186
|
smells,
|
|
@@ -1232,6 +1284,7 @@ function printReport(report) {
|
|
|
1232
1284
|
.map(([k, v]) => `${k}=${v}`)
|
|
1233
1285
|
.join(", ")}`,
|
|
1234
1286
|
);
|
|
1287
|
+
console.log(`${report.rowsExcluded} rows excluded (synthetic corpora)`);
|
|
1235
1288
|
if (Object.keys(report.parseErrors).length)
|
|
1236
1289
|
console.log(`parse errors: ${JSON.stringify(report.parseErrors)}`);
|
|
1237
1290
|
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import * as path from "node:path";
|
|
2
|
-
export class AstGrepParser {
|
|
3
|
-
getRuleDescription;
|
|
4
|
-
mapSeverity;
|
|
5
|
-
constructor(getRuleDescription, mapSeverity) {
|
|
6
|
-
this.getRuleDescription = getRuleDescription;
|
|
7
|
-
this.mapSeverity = mapSeverity;
|
|
8
|
-
}
|
|
9
|
-
parseOutput(output, filterFile) {
|
|
10
|
-
const resolvedFilterFile = path.resolve(filterFile);
|
|
11
|
-
try {
|
|
12
|
-
const items = JSON.parse(output);
|
|
13
|
-
if (Array.isArray(items)) {
|
|
14
|
-
return items
|
|
15
|
-
.map((item) => this.parseDiagnostic(item, resolvedFilterFile))
|
|
16
|
-
.filter((d) => d !== null);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
catch (err) {
|
|
20
|
-
void err;
|
|
21
|
-
}
|
|
22
|
-
return output
|
|
23
|
-
.split(/\r?\n/)
|
|
24
|
-
.filter((l) => l.trim())
|
|
25
|
-
.map((line) => {
|
|
26
|
-
try {
|
|
27
|
-
return this.parseDiagnostic(JSON.parse(line), resolvedFilterFile);
|
|
28
|
-
}
|
|
29
|
-
catch (err) {
|
|
30
|
-
void err;
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
})
|
|
34
|
-
.filter((d) => d !== null);
|
|
35
|
-
}
|
|
36
|
-
parseDiagnostic(item, filterFile) {
|
|
37
|
-
if (item.labels?.length) {
|
|
38
|
-
return this.parseNewFormat(item, filterFile);
|
|
39
|
-
}
|
|
40
|
-
if (item.spans?.length) {
|
|
41
|
-
return this.parseLegacyFormat(item, filterFile);
|
|
42
|
-
}
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
parseNewFormat(item, filterFile) {
|
|
46
|
-
const label = item.labels.find((l) => l.style === "primary") || item.labels[0];
|
|
47
|
-
const filePath = path.resolve(label.file || filterFile);
|
|
48
|
-
if (filePath !== filterFile)
|
|
49
|
-
return null;
|
|
50
|
-
const start = label.range?.start || { line: 0, column: 0 };
|
|
51
|
-
const end = label.range?.end || start;
|
|
52
|
-
return {
|
|
53
|
-
line: start.line + 1,
|
|
54
|
-
column: start.column,
|
|
55
|
-
endLine: end.line + 1,
|
|
56
|
-
endColumn: end.column,
|
|
57
|
-
severity: this.mapSeverity(item.severity),
|
|
58
|
-
message: item.message || "Unknown issue",
|
|
59
|
-
rule: item.ruleId || "unknown",
|
|
60
|
-
ruleDescription: this.getRuleDescription(item.ruleId || "unknown"),
|
|
61
|
-
file: filePath,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
parseLegacyFormat(item, filterFile) {
|
|
65
|
-
const span = item.spans?.[0];
|
|
66
|
-
if (!span)
|
|
67
|
-
return null;
|
|
68
|
-
const filePath = path.resolve(span.file || filterFile);
|
|
69
|
-
if (filePath !== filterFile)
|
|
70
|
-
return null;
|
|
71
|
-
const start = span.range?.start || { line: 0, column: 0 };
|
|
72
|
-
const end = span.range?.end || start;
|
|
73
|
-
const ruleId = item.name || item.ruleId || "unknown";
|
|
74
|
-
return {
|
|
75
|
-
line: start.line + 1,
|
|
76
|
-
column: start.column,
|
|
77
|
-
endLine: end.line + 1,
|
|
78
|
-
endColumn: end.column,
|
|
79
|
-
severity: this.mapSeverity(item.severity || item.Severity || "warning"),
|
|
80
|
-
message: item.Message?.text || item.message || "Unknown issue",
|
|
81
|
-
rule: ruleId,
|
|
82
|
-
ruleDescription: this.getRuleDescription(ruleId),
|
|
83
|
-
file: filePath,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
}
|