react-doctor 0.9.11 → 0.9.12-dev.8c2f03a
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 +1 -1
- package/bin/react-doctor.js +1 -9
- package/dist/{build-section-divider-sLcWe1hO.js → build-section-divider-DuozMmwU.js} +9 -10
- package/dist/{ci-DsrrD52i.js → ci-Bwd2LJZC.js} +12 -12
- package/dist/cli.js +29 -30
- package/dist/{design-CP25gyyg.js → design-Q4Umr_4T.js} +4 -4
- package/dist/{devtools-DPRVRu3S.js → devtools-D8NTVj81.js} +4 -4
- package/dist/{exit-gracefully-CVVkBxDS.js → exit-gracefully-vUI1H1zC.js} +6 -6
- package/dist/index.d.ts +36 -59
- package/dist/index.js +54539 -54310
- package/dist/{inspect-D6y8oLtg.js → inspect-RxIsB8bi.js} +20 -20
- package/dist/{install-afMFGeTB.js → install-CI0nvC_v.js} +8 -8
- package/dist/{install-doctor-script-Be7Mv3-l.js → install-doctor-script-BAmTZygh.js} +4 -4
- package/dist/{install-github-workflow-Dev2F6Ea.js → install-github-workflow-Dg2sosDx.js} +6 -6
- package/dist/{install-react-doctor-DIPVunY4.js → install-react-doctor-CIJcnTik.js} +8 -8
- package/dist/{print-branded-header-D5jLdo4p.js → print-branded-header-kwnSGrfR.js} +4 -4
- package/dist/project-analysis-worker.d.ts +1 -0
- package/dist/project-analysis-worker.js +51900 -0
- package/dist/{read-object-file-CEh1CqnD.js → read-object-file-m5uVvcBp.js} +4 -4
- package/dist/{record-metric-CJxSHfJD.js → record-metric-DospZkfP.js} +3093 -6149
- package/dist/{report-error-CAEixMg1.js → report-error-CAp5cil9.js} +5 -5
- package/dist/{report-workflow-result-C0jbKH8p.js → report-workflow-result-D0GvvJtT.js} +5 -5
- package/dist/{resolve-scope-DS7rcRRz.js → resolve-scope-eXawiGEH.js} +6 -6
- package/dist/{rules-BJynymuU.js → rules-C_xYDSz8.js} +6 -6
- package/dist/{run-scan-app-BGzlyiIB.js → run-scan-app-CeNk17wq.js} +189 -145
- package/dist/{scan-CgPRG6_z.js → scan-DIwsgV6M.js} +8 -8
- package/dist/semver-DFtnEmN-.js +3219 -0
- package/dist/{should-fail-scan-gate-4jf7ZRdL.js → should-fail-scan-gate-BWTNIU5h.js} +186 -91
- package/dist/{should-skip-prompts-C78r7Ww7.js → should-skip-prompts-oK3MwWyB.js} +4 -4
- package/dist/{unref-stdin-Dc8ipkaw.js → unref-stdin-BGZVK4sJ.js} +6 -12
- package/dist/{version-DDrwsTas.js → version-9-2T2YQf.js} +4 -4
- package/dist/{why-BRNrKY1b.js → why-BOiuB_qy.js} +4 -4
- package/package.json +6 -12
- package/dist/chunk-q7NCDQ7-.js +0 -28
- package/dist/lsp.js +0 -81114
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
-
import { $
|
|
4
|
-
import { a as setActiveRunTrace, i as recordRunTraceId, o as getTelemetryContext } from "./unref-stdin-
|
|
5
|
-
import { n as buildFooterLinkLines, r as activeScanAbortRegistry, t as buildSectionDivider } from "./build-section-divider-
|
|
6
|
-
import { D as getPackageJsonPath, L as cliLogger, O as isRecord, P as runGit, a as installReactDoctorScriptStep, c as spinner, n as findNearestPackageDirectory, o as isSpinnerSilent, s as setSpinnerSilent } from "./install-doctor-script-
|
|
7
|
-
import { d as detectDefaultBranch, l as prompts, r as installReactDoctorWorkflow, u as isCommandAvailable } from "./install-github-workflow-
|
|
8
|
-
import { a as isValidBlockingLevel, c as openWorkflowPullRequest, l as stageWorkflowFile, o as pickBlockingLevel, u as toForwardSlashes } from "./resolve-scope-
|
|
9
|
-
import { h as detectAvailableAgents, t as reportWorkflowResult } from "./report-workflow-result-
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="73ec5086-9c15-5ede-ba70-0f5b26bd0ed2")}catch(e){}}();
|
|
3
|
+
import { $ as Maintainability, $t as listSourceFiles, An as makeSpan, At as filterDiagnosticsForSurface, Bn as try_, Ct as computeConfigFingerprint, Dn as decodeUnknownSync, Dt as createOxlintSpawnSlots, E as NANOSECONDS_PER_MILLISECOND, En as Diagnostic, Et as createNodeReadFileLinesSync, Fn as provideContext, G as isCiOrCodingAgentEnvironment, Gn as succeed, Gt as highlighter, H as ACTION_INPUT_ENVIRONMENT_VARIABLES, Ht as hasPublishedFixRecipe, In as provideService, J as Files, Jn as fail, Kt as isMonorepoRoot, Ln as runPromise, Mn as orElseSucceed, Mt as filterSourceFiles, Nn as promise, Pn as provide, Q as Linter, R as CliInputError, Rn as runSync, Rt as getDiagnosticRuleIdentity, Sn as error, St as collectSourceFileCountsByDirectory, Tn as warn, Tt as countOptInProjectRuleSelections, U as detectRunnerOs, Un as mergeAll, Vt as groupBy, W as isCiEnvironment, Wt as hashFileContents, Xn as ParentSpan, Y as Git, Yn as void_, Yt as isReactDoctorError, Z as LintPartialFailures, Zt as isScanComplete, _ as makeNoopConsole, _n as summarizeDiagnostics, _t as buildSkippedChecks, an as mergeReactDoctorConfigs, at as Project, bn as yieldToEventLoop, br as isFile, bt as classifyFileContext, c as setSentryProjectInfo, cn as resolveLintBatchOrdering, cr as GIT_SHOW_MAX_BUFFER_BYTES, ct as SidecarLintCacheEnabled, d as isJsonModeActive, dn as resolveScanTarget, dr as JSX_FILE_PATTERN, en as listSourceFilesCooperative, er as CI_URL, et as NodeResolver, fn as restoreLegacyThrow, fr as MILLISECONDS_PER_SECOND, g as VERSION, gn as shouldUseMaintainabilityLayer, gt as buildRuleSeverityControls, ht as buildRuleDocsUrl, in as materializeSourceTree, ir as DIAGNOSTIC_CATEGORY_BUCKETS, it as Progress, jn as map, jt as filterPathsOutsideDirectories, k as SCAN_RESULT_CACHE_FILENAME, kn as gen, kt as discoverReactSubprojects, l as getRunId, ln as resolveReactDoctorCacheDir, lr as HTML_FILE_PATTERN, mr as SHARE_BASE_URL, n as recordDistribution, nt as OxlintSpawnSlots, o as buildSentryScope, on as remainingDeadlineBudgetMs, or as ENTERPRISE_CONTACT_URL, ot as Reporter, pn as runInspect, pr as OXLINT_NODE_REQUIREMENT, pt as atomicWriteJson, q as Config, qt as isPathInsideDirectory, r as toSpanAttributes, rn as mapWithConcurrency, rt as PerFileLintCacheEnabled, s as buildSentryProjectContext, sn as resolveGithubActionsScoreMetadata, st as Score, t as recordCount, tn as listWorkspacePackages, tt as OxlintConcurrency, un as resolveScanConcurrency, ur as JSX_DUPLICATION_SOURCE_FILE_PATTERN, ut as SupplyChain, vr as isDirectory, vt as calculateScore, w as METRIC, wn as log, wt as computeDiagnosticDelta, x as BASELINE_FILES_TEMP_DIR_PREFIX, xn as Console, yt as canonicalizeUserRuleKey, z as isNonInteractiveEnvironment, zn as sync } from "./record-metric-DospZkfP.js";
|
|
4
|
+
import { a as setActiveRunTrace, i as recordRunTraceId, o as getTelemetryContext } from "./unref-stdin-BGZVK4sJ.js";
|
|
5
|
+
import { n as buildFooterLinkLines, r as activeScanAbortRegistry, t as buildSectionDivider } from "./build-section-divider-DuozMmwU.js";
|
|
6
|
+
import { D as getPackageJsonPath, L as cliLogger, O as isRecord, P as runGit, a as installReactDoctorScriptStep, c as spinner, n as findNearestPackageDirectory, o as isSpinnerSilent, s as setSpinnerSilent } from "./install-doctor-script-BAmTZygh.js";
|
|
7
|
+
import { d as detectDefaultBranch, l as prompts, r as installReactDoctorWorkflow, u as isCommandAvailable } from "./install-github-workflow-Dg2sosDx.js";
|
|
8
|
+
import { a as isValidBlockingLevel, c as openWorkflowPullRequest, l as stageWorkflowFile, o as pickBlockingLevel, u as toForwardSlashes } from "./resolve-scope-eXawiGEH.js";
|
|
9
|
+
import { h as detectAvailableAgents, t as reportWorkflowResult } from "./report-workflow-result-D0GvvJtT.js";
|
|
10
10
|
import { createRequire } from "node:module";
|
|
11
11
|
import { spawn } from "node:child_process";
|
|
12
12
|
import * as path$1 from "node:path";
|
|
13
13
|
import path from "node:path";
|
|
14
|
-
import * as fs$
|
|
14
|
+
import * as fs$2 from "node:fs";
|
|
15
15
|
import fs, { mkdtempSync, rmSync } from "node:fs";
|
|
16
|
-
import crypto, { randomUUID } from "node:crypto";
|
|
17
16
|
import ts from "typescript";
|
|
17
|
+
import crypto, { randomUUID } from "node:crypto";
|
|
18
18
|
import { tmpdir } from "node:os";
|
|
19
|
+
import * as fs$1 from "node:fs/promises";
|
|
19
20
|
import { performance } from "node:perf_hooks";
|
|
20
|
-
import { codeFrameColumns } from "@babel/code-frame";
|
|
21
21
|
//#region src/cli/utils/apply-observability.ts
|
|
22
22
|
/**
|
|
23
23
|
* Installs the tracing backend for the inspect program.
|
|
@@ -84,7 +84,10 @@ const buildSpinnerProgressHandle = (text) => {
|
|
|
84
84
|
*/
|
|
85
85
|
const buildRuntimeLayers = (input) => {
|
|
86
86
|
const linterLayer = input.shouldSkipLint ? Linter.layerOf([]) : Linter.layerOxlint;
|
|
87
|
-
const
|
|
87
|
+
const maintainabilityLayer = shouldUseMaintainabilityLayer({
|
|
88
|
+
shouldRunDuplicateJsx: input.shouldRunDeadCode,
|
|
89
|
+
userConfig: input.userConfig
|
|
90
|
+
}) ? Maintainability.layerNode : Maintainability.layerOf([]);
|
|
88
91
|
const scoreLayer = input.shouldComputeScore ? Score.layerHttp : Score.layerOf(null);
|
|
89
92
|
const supplyChainLayer = input.shouldRunSupplyChain ? SupplyChain.layerNode : SupplyChain.layerOf([]);
|
|
90
93
|
const projectLayer = input.projectInfoOverride === void 0 ? Project.layerNode : Project.layerOf(input.projectInfoOverride);
|
|
@@ -94,7 +97,7 @@ const buildRuntimeLayers = (input) => {
|
|
|
94
97
|
config: input.userConfig,
|
|
95
98
|
resolvedDirectory: input.directory,
|
|
96
99
|
configSourceDirectory: input.configSourceDirectory
|
|
97
|
-
}) : Config.layerNode, Files.layerNode, Git.layerNode, linterLayer, LintPartialFailures.layerLive,
|
|
100
|
+
}) : Config.layerNode, Files.layerNode, Git.layerNode, linterLayer, LintPartialFailures.layerLive, maintainabilityLayer, progressLayer, reporterLayer, scoreLayer, supplyChainLayer);
|
|
98
101
|
const layersWithConcurrency = input.oxlintConcurrency === void 0 ? baseLayers : mergeAll(baseLayers, succeed(OxlintConcurrency, input.oxlintConcurrency));
|
|
99
102
|
return input.oxlintSpawnSlots === void 0 ? layersWithConcurrency : mergeAll(layersWithConcurrency, succeed(OxlintSpawnSlots, input.oxlintSpawnSlots));
|
|
100
103
|
};
|
|
@@ -310,7 +313,7 @@ const recordScanMetrics = (input) => {
|
|
|
310
313
|
recordCount(METRIC.scanCompleted, 1, {
|
|
311
314
|
mode: input.mode,
|
|
312
315
|
lint: input.lint,
|
|
313
|
-
|
|
316
|
+
maintainability: input.deadCode,
|
|
314
317
|
parallel: input.parallel,
|
|
315
318
|
scoreOnly: input.scoreOnly,
|
|
316
319
|
didLintFail: input.didLintFail,
|
|
@@ -350,7 +353,7 @@ const recordScanMetrics = (input) => {
|
|
|
350
353
|
else if (!input.noScore && !input.didLintFail && !input.didDeadCodeFail) recordCount(METRIC.scoreUnavailable, 1, { mode: input.mode });
|
|
351
354
|
if (input.baselineDegraded) recordCount(METRIC.baselineDegraded, 1);
|
|
352
355
|
if (input.didLintFail) recordCount(METRIC.lintFailed, 1, { reasonKind: input.lintFailureReasonKind });
|
|
353
|
-
if (input.didDeadCodeFail) recordCount(METRIC.
|
|
356
|
+
if (input.didDeadCodeFail) recordCount(METRIC.maintainabilityFailed, 1);
|
|
354
357
|
for (const check of result.skippedChecks) recordCount(METRIC.scanCheckSkipped, 1, {
|
|
355
358
|
check,
|
|
356
359
|
reason: result.skippedCheckReasons?.[check] ?? null
|
|
@@ -494,7 +497,6 @@ const CACHE_DISABLED_VALUES = new Set(["1", "true"]);
|
|
|
494
497
|
const TOOLCHAIN_PACKAGE_SPECIFIERS = [
|
|
495
498
|
"oxlint/package.json",
|
|
496
499
|
"oxlint-plugin-react-doctor/package.json",
|
|
497
|
-
"deslop-js/package.json",
|
|
498
500
|
"eslint-plugin-react-hooks/package.json"
|
|
499
501
|
];
|
|
500
502
|
const bundledRequire = createRequire(import.meta.url);
|
|
@@ -633,12 +635,12 @@ const resolveCacheFilePath = (projectDirectory) => path.join(resolveReactDoctorC
|
|
|
633
635
|
const readPersistedCache = (cacheFilePath) => {
|
|
634
636
|
try {
|
|
635
637
|
const parsed = JSON.parse(fs.readFileSync(cacheFilePath, "utf8"));
|
|
636
|
-
if (!isRecord(parsed) || parsed.version !==
|
|
637
|
-
version:
|
|
638
|
+
if (!isRecord(parsed) || parsed.version !== 7) return {
|
|
639
|
+
version: 7,
|
|
638
640
|
entries: []
|
|
639
641
|
};
|
|
640
642
|
if (!Array.isArray(parsed.entries)) return {
|
|
641
|
-
version:
|
|
643
|
+
version: 7,
|
|
642
644
|
entries: []
|
|
643
645
|
};
|
|
644
646
|
const entries = [];
|
|
@@ -653,12 +655,12 @@ const readPersistedCache = (cacheFilePath) => {
|
|
|
653
655
|
});
|
|
654
656
|
}
|
|
655
657
|
return {
|
|
656
|
-
version:
|
|
658
|
+
version: 7,
|
|
657
659
|
entries
|
|
658
660
|
};
|
|
659
661
|
} catch {
|
|
660
662
|
return {
|
|
661
|
-
version:
|
|
663
|
+
version: 7,
|
|
662
664
|
entries: []
|
|
663
665
|
};
|
|
664
666
|
}
|
|
@@ -666,7 +668,7 @@ const readPersistedCache = (cacheFilePath) => {
|
|
|
666
668
|
/**
|
|
667
669
|
* The global cache off-switch (`REACT_DOCTOR_NO_CACHE`), which disables every
|
|
668
670
|
* cache subsystem: this whole-repo scan cache plus core's per-file lint,
|
|
669
|
-
* sidecar
|
|
671
|
+
* sidecar caches (their `Context.Reference` defaults read the
|
|
670
672
|
* same variable). Exported for the wide event's `cache.temperature`
|
|
671
673
|
* derivation, which reports `"disabled"` instead of `"cold"` when the switch
|
|
672
674
|
* is on. Granular knobs (`REACT_DOCTOR_NO_FILE_CACHE`, …) are deliberately
|
|
@@ -708,7 +710,7 @@ const buildScanResultCacheKey = (input) => {
|
|
|
708
710
|
if (repositoryIdentity === null) return null;
|
|
709
711
|
if (stringifyStableJson(input.userConfig) === null) return null;
|
|
710
712
|
const cacheKeyJson = stringifyStableJson({
|
|
711
|
-
schemaVersion:
|
|
713
|
+
schemaVersion: 7,
|
|
712
714
|
projectIdentity: resolveProjectIdentity(input.projectDirectory),
|
|
713
715
|
headSha: repositoryIdentity.headSha,
|
|
714
716
|
worktreeFingerprint: repositoryIdentity.worktreeFingerprint,
|
|
@@ -756,7 +758,7 @@ const createScanResultCache = (projectDirectory) => {
|
|
|
756
758
|
for (const entry of readPersistedCache(cacheFilePath).entries) mergedEntries.set(entry.key, entry);
|
|
757
759
|
for (const entry of entries.values()) mergedEntries.set(entry.key, entry);
|
|
758
760
|
atomicWriteJson(cacheFilePath, {
|
|
759
|
-
version:
|
|
761
|
+
version: 7,
|
|
760
762
|
entries: [...mergedEntries.values()].sort((firstEntry, secondEntry) => secondEntry.createdAtMs - firstEntry.createdAtMs).slice(0, 20)
|
|
761
763
|
});
|
|
762
764
|
};
|
|
@@ -791,8 +793,7 @@ const shouldBlockCi = (diagnostics, blockingLevel) => {
|
|
|
791
793
|
/**
|
|
792
794
|
* Lowercase, key-safe form of a rule category for the `diag.category.*`
|
|
793
795
|
* telemetry attribute namespace (categories carry spaces / capitals, e.g.
|
|
794
|
-
* "Performance" → `performance`, "Dead Code" → `dead_code`).
|
|
795
|
-
* CLI run event and the editor LSP wide event so both namespace identically.
|
|
796
|
+
* "Performance" → `performance`, "Dead Code" → `dead_code`).
|
|
796
797
|
*/
|
|
797
798
|
const toCategoryKey = (category) => category.toLowerCase().replace(/[^a-z0-9]+/g, "_");
|
|
798
799
|
//#endregion
|
|
@@ -822,12 +823,6 @@ const readEnvBoolean = (name) => {
|
|
|
822
823
|
return value.toLowerCase() === "true" || value === "1";
|
|
823
824
|
};
|
|
824
825
|
const ratioOf = (numerator, denominator) => denominator != null && denominator > 0 ? (numerator ?? 0) / denominator : null;
|
|
825
|
-
const resolveDeadCodeReuseRatio = (result) => {
|
|
826
|
-
if (result.deadCodeCacheHit === true) return 1;
|
|
827
|
-
const summaryTotal = (result.deadCodeSummaryCacheHits ?? 0) + (result.deadCodeSummaryCacheMisses ?? 0);
|
|
828
|
-
if (summaryTotal > 0) return (result.deadCodeSummaryCacheHits ?? 0) / summaryTotal;
|
|
829
|
-
return result.deadCodeCacheHit === false ? 0 : null;
|
|
830
|
-
};
|
|
831
826
|
/**
|
|
832
827
|
* One queryable cache temperature per scan, derived from the whole stack:
|
|
833
828
|
*
|
|
@@ -835,8 +830,7 @@ const resolveDeadCodeReuseRatio = (result) => {
|
|
|
835
830
|
* `wholeRepoCacheHit` flag from the CLI's cachedPayload
|
|
836
831
|
* branch; no scan work ran).
|
|
837
832
|
* - `"warm"` — any incremental reuse: per-file lint hits, sidecar
|
|
838
|
-
* replays
|
|
839
|
-
* summary-cache hits.
|
|
833
|
+
* replays.
|
|
840
834
|
* - `"disabled"` — zero reuse because the global `REACT_DOCTOR_NO_CACHE`
|
|
841
835
|
* off-switch is on. Granular per-cache opt-outs
|
|
842
836
|
* (`REACT_DOCTOR_NO_FILE_CACHE`, …) still read warm/cold,
|
|
@@ -845,7 +839,7 @@ const resolveDeadCodeReuseRatio = (result) => {
|
|
|
845
839
|
*
|
|
846
840
|
* `cache.warmth` is the headline reuse magnitude in [0, 1]: the plain mean of
|
|
847
841
|
* the subsystem reuse fractions known this run (lint hit ratio, sidecar
|
|
848
|
-
* replay ratio
|
|
842
|
+
* replay ratio), skipping subsystems that never consulted a
|
|
849
843
|
* cache; `1` on turbo, dropped when nothing consulted any cache. Deliberately
|
|
850
844
|
* unweighted — the per-subsystem dims stay the precise signal; warmth is the
|
|
851
845
|
* p50/p90-able summary. Emitted only on the success path.
|
|
@@ -858,11 +852,7 @@ const buildCacheAttributes = (input) => {
|
|
|
858
852
|
warmth: 1
|
|
859
853
|
});
|
|
860
854
|
const result = input.result;
|
|
861
|
-
const subsystemReuseRatios = [
|
|
862
|
-
ratioOf(result.lintCacheHitFileCount, result.lintCacheTotalFileCount),
|
|
863
|
-
ratioOf(result.lintSidecarReplayedFileCount, result.lintSidecarTotalFileCount),
|
|
864
|
-
resolveDeadCodeReuseRatio(result)
|
|
865
|
-
];
|
|
855
|
+
const subsystemReuseRatios = [ratioOf(result.lintCacheHitFileCount, result.lintCacheTotalFileCount), ratioOf(result.lintSidecarReplayedFileCount, result.lintSidecarTotalFileCount)];
|
|
866
856
|
let knownSubsystemCount = 0;
|
|
867
857
|
let reuseRatioSum = 0;
|
|
868
858
|
for (const reuseRatio of subsystemReuseRatios) {
|
|
@@ -1014,13 +1004,7 @@ const buildOutcomeAttributes = (input) => {
|
|
|
1014
1004
|
sidecarTotalFiles: result.lintSidecarTotalFileCount,
|
|
1015
1005
|
sidecarReplayRatio: ratioOf(result.lintSidecarReplayedFileCount, result.lintSidecarTotalFileCount)
|
|
1016
1006
|
}),
|
|
1017
|
-
...withNamespace("
|
|
1018
|
-
failed: input.didDeadCodeFail,
|
|
1019
|
-
overlapped: input.deadCodeOverlapped,
|
|
1020
|
-
cacheHit: result.deadCodeCacheHit,
|
|
1021
|
-
summaryCacheHits: result.deadCodeSummaryCacheHits,
|
|
1022
|
-
summaryCacheMisses: result.deadCodeSummaryCacheMisses
|
|
1023
|
-
}),
|
|
1007
|
+
...withNamespace("maintainability", { failed: input.didDeadCodeFail }),
|
|
1024
1008
|
...withNamespace("supplyChain", { overlapTimedOut: input.supplyChainOverlapTimedOut }),
|
|
1025
1009
|
...withNamespace("securityScan", { failed: input.securityScanFailed }),
|
|
1026
1010
|
...withNamespace("timing", {
|
|
@@ -1063,7 +1047,7 @@ const buildScanAttributes = (input) => {
|
|
|
1063
1047
|
workerCount: input.workerCount,
|
|
1064
1048
|
maxDurationMs: input.maxDurationMs,
|
|
1065
1049
|
lint: input.lint,
|
|
1066
|
-
|
|
1050
|
+
maintainability: input.deadCode,
|
|
1067
1051
|
supplyChain: input.supplyChain,
|
|
1068
1052
|
scoreOnly: input.scoreOnly,
|
|
1069
1053
|
noScore: input.noScore,
|
|
@@ -1074,6 +1058,7 @@ const buildScanAttributes = (input) => {
|
|
|
1074
1058
|
hasCustomConfig: input.hasCustomConfig,
|
|
1075
1059
|
rulesConfigured: ruleKeys.length,
|
|
1076
1060
|
rulesDisabled: ruleKeys.filter((key) => ruleOverrides[key] === "off").length,
|
|
1061
|
+
projectAnalysisRuleCount: countOptInProjectRuleSelections(buildRuleSeverityControls(input.userConfig)),
|
|
1077
1062
|
fileCount: input.result?.scannedFileCount,
|
|
1078
1063
|
nonJsxFileCount: input.result?.analyzedFiles?.filter((filePath) => !JSX_FILE_PATTERN.test(filePath)).length,
|
|
1079
1064
|
htmlFileCount: input.result?.analyzedFiles?.filter((filePath) => HTML_FILE_PATTERN.test(filePath)).length,
|
|
@@ -1084,7 +1069,7 @@ const buildScanAttributes = (input) => {
|
|
|
1084
1069
|
* Projects a scan into the namespaced attribute set for its root span — the
|
|
1085
1070
|
* canonical per-scan "wide event". Every attribute carries a dotted namespace
|
|
1086
1071
|
* that groups it by concept (`scan.*` config, `action.*` CI knobs, `outcome.*`
|
|
1087
|
-
* verdict, `diag.*` findings, `score.*`, `lint.*`, `
|
|
1072
|
+
* verdict, `diag.*` findings, `score.*`, `lint.*`, `maintainability.*`, `cache.*`,
|
|
1088
1073
|
* `supplyChain.*`, `timing.*`, `migration.*`, `baseline.*`) so the attributes
|
|
1089
1074
|
* tree up in Sentry's attribute browser and stay filter-/group-/aggregate-able
|
|
1090
1075
|
* in the Spans dataset. Pure and exported so the projection (outcome
|
|
@@ -1323,7 +1308,7 @@ const buildNoScoreMessage = (input) => {
|
|
|
1323
1308
|
reason = input.disabledMessage ?? "Score disabled by --no-score.";
|
|
1324
1309
|
break;
|
|
1325
1310
|
case "analysis-incomplete":
|
|
1326
|
-
reason = "Score not shown because lint or
|
|
1311
|
+
reason = "Score not shown because lint or maintainability analysis could not complete.";
|
|
1327
1312
|
break;
|
|
1328
1313
|
case "api-unavailable":
|
|
1329
1314
|
reason = "Score unavailable (could not reach the score API).";
|
|
@@ -1371,7 +1356,7 @@ const formatRuleSummary = (ruleKey, ruleDiagnostics) => {
|
|
|
1371
1356
|
const ruleDumpFileName = (ruleKey) => ruleKey.replace(/\//g, "--") + ".txt";
|
|
1372
1357
|
const readPreviousRuleDumpFileNames = (directory) => {
|
|
1373
1358
|
try {
|
|
1374
|
-
const previous = JSON.parse(fs$
|
|
1359
|
+
const previous = JSON.parse(fs$2.readFileSync(path$1.join(directory, "diagnostics.json"), "utf8"));
|
|
1375
1360
|
return new Set(previous.filter((d) => typeof d?.plugin === "string" && typeof d?.rule === "string").map((d) => ruleDumpFileName(`${d.plugin}/${d.rule}`)));
|
|
1376
1361
|
} catch {
|
|
1377
1362
|
return /* @__PURE__ */ new Set();
|
|
@@ -1379,10 +1364,10 @@ const readPreviousRuleDumpFileNames = (directory) => {
|
|
|
1379
1364
|
};
|
|
1380
1365
|
const writeDiagnosticsDirectory = (diagnostics, outputDirectory) => {
|
|
1381
1366
|
const directory = outputDirectory ? path$1.resolve(outputDirectory) : path$1.join(tmpdir(), `react-doctor-${randomUUID()}`);
|
|
1382
|
-
if (outputDirectory) for (const fileName of readPreviousRuleDumpFileNames(directory)) fs$
|
|
1383
|
-
fs$
|
|
1384
|
-
for (const [ruleKey, ruleDiagnostics] of buildSortedRuleGroups(diagnostics)) fs$
|
|
1385
|
-
fs$
|
|
1367
|
+
if (outputDirectory) for (const fileName of readPreviousRuleDumpFileNames(directory)) fs$2.rmSync(path$1.join(directory, fileName), { force: true });
|
|
1368
|
+
fs$2.mkdirSync(directory, { recursive: true });
|
|
1369
|
+
for (const [ruleKey, ruleDiagnostics] of buildSortedRuleGroups(diagnostics)) fs$2.writeFileSync(path$1.join(directory, ruleDumpFileName(ruleKey)), formatRuleSummary(ruleKey, ruleDiagnostics));
|
|
1370
|
+
fs$2.writeFileSync(path$1.join(directory, "diagnostics.json"), JSON.stringify(diagnostics));
|
|
1386
1371
|
return directory;
|
|
1387
1372
|
};
|
|
1388
1373
|
//#endregion
|
|
@@ -1426,6 +1411,9 @@ const formatElapsedTime = (elapsedMilliseconds) => {
|
|
|
1426
1411
|
return `${(elapsedMilliseconds / MILLISECONDS_PER_SECOND).toFixed(1)}s`;
|
|
1427
1412
|
};
|
|
1428
1413
|
//#endregion
|
|
1414
|
+
//#region src/cli/utils/format-skipped-check-label.ts
|
|
1415
|
+
const formatSkippedCheckLabel = (skippedCheck) => skippedCheck === "dead-code" ? "maintainability" : skippedCheck;
|
|
1416
|
+
//#endregion
|
|
1429
1417
|
//#region src/cli/utils/pluralize.ts
|
|
1430
1418
|
const pluralize = (count, singularNoun) => `${count} ${singularNoun}${count === 1 ? "" : "s"}`;
|
|
1431
1419
|
//#endregion
|
|
@@ -1474,7 +1462,7 @@ const printHeadlessReport = (input) => gen(function* () {
|
|
|
1474
1462
|
}
|
|
1475
1463
|
if (input.skippedChecks.length > 0) {
|
|
1476
1464
|
yield* log("");
|
|
1477
|
-
yield* warn(highlighter.warn(`Results are incomplete: ${input.skippedChecks.join(" and ")} checks failed.`));
|
|
1465
|
+
yield* warn(highlighter.warn(`Results are incomplete: ${input.skippedChecks.map(formatSkippedCheckLabel).join(" and ")} checks failed.`));
|
|
1478
1466
|
}
|
|
1479
1467
|
});
|
|
1480
1468
|
//#endregion
|
|
@@ -1674,12 +1662,39 @@ const renderAndRecordScan = async (input) => {
|
|
|
1674
1662
|
didDeadCodeFail: input.payload.didDeadCodeFail,
|
|
1675
1663
|
supplyChainOverlapTimedOut: input.payload.supplyChainOverlapTimedOut,
|
|
1676
1664
|
securityScanFailed: input.payload.securityScanFailed,
|
|
1677
|
-
deadCodeOverlapped: input.payload.deadCodeOverlapped,
|
|
1678
1665
|
suppressedRuleCounts: input.payload.suppressedRuleCounts ?? []
|
|
1679
1666
|
});
|
|
1680
1667
|
return result;
|
|
1681
1668
|
};
|
|
1682
1669
|
//#endregion
|
|
1670
|
+
//#region src/cli/utils/copy-unchanged-baseline-sources.ts
|
|
1671
|
+
const copyUnchangedBaselineSources = async (input) => {
|
|
1672
|
+
const baseMaterializedFiles = new Set(input.baseMaterializedFiles.map(toForwardSlashes));
|
|
1673
|
+
const headChangedFiles = new Set(input.headChangedFiles.map(toForwardSlashes));
|
|
1674
|
+
const untrackedFiles = new Set(input.untrackedFiles.map(toForwardSlashes));
|
|
1675
|
+
const sourceDirectory = path$1.resolve(input.directory);
|
|
1676
|
+
const targetDirectory = path$1.resolve(input.tempDirectory);
|
|
1677
|
+
return (await mapWithConcurrency(input.sourceFiles.filter((filePath) => {
|
|
1678
|
+
const normalizedPath = toForwardSlashes(filePath);
|
|
1679
|
+
return !baseMaterializedFiles.has(normalizedPath) && !headChangedFiles.has(normalizedPath) && !untrackedFiles.has(normalizedPath);
|
|
1680
|
+
}), 32, async (filePath) => {
|
|
1681
|
+
input.signal?.throwIfAborted();
|
|
1682
|
+
if (input.deadlineEpochMs !== null && Date.now() >= input.deadlineEpochMs) return false;
|
|
1683
|
+
const sourcePath = path$1.resolve(sourceDirectory, filePath);
|
|
1684
|
+
const targetPath = path$1.resolve(targetDirectory, filePath);
|
|
1685
|
+
if (!isPathInsideDirectory(sourcePath, sourceDirectory) || !isPathInsideDirectory(targetPath, targetDirectory)) return false;
|
|
1686
|
+
try {
|
|
1687
|
+
if (!(await fs$1.lstat(sourcePath)).isFile()) return false;
|
|
1688
|
+
await fs$1.mkdir(path$1.dirname(targetPath), { recursive: true });
|
|
1689
|
+
await fs$1.copyFile(sourcePath, targetPath);
|
|
1690
|
+
return true;
|
|
1691
|
+
} catch {
|
|
1692
|
+
input.signal?.throwIfAborted();
|
|
1693
|
+
return false;
|
|
1694
|
+
}
|
|
1695
|
+
})).every(Boolean);
|
|
1696
|
+
};
|
|
1697
|
+
//#endregion
|
|
1683
1698
|
//#region src/cli/utils/read-diagnostic-evidence.ts
|
|
1684
1699
|
const SOURCE_EXTENSIONS = [
|
|
1685
1700
|
".ts",
|
|
@@ -2097,7 +2112,6 @@ const resolveMergeBaseRef = async (directory, ref) => {
|
|
|
2097
2112
|
const silentConsole$1 = makeNoopConsole();
|
|
2098
2113
|
const countIncompleteLintFiles = (lintPartialFailures) => countDroppedLintFiles(lintPartialFailures) + countDeadlineSkippedFiles(lintPartialFailures);
|
|
2099
2114
|
const runBaselineComparison = async (input) => {
|
|
2100
|
-
const temporaryDirectory = mkdtempSync(path.join(tmpdir(), BASELINE_FILES_TEMP_DIR_PREFIX));
|
|
2101
2115
|
const baselineIncludePaths = filterPathsOutsideDirectories({
|
|
2102
2116
|
rootDirectory: input.directory,
|
|
2103
2117
|
relativePaths: input.options.includePaths,
|
|
@@ -2113,12 +2127,24 @@ const runBaselineComparison = async (input) => {
|
|
|
2113
2127
|
relativePaths: input.headFiles,
|
|
2114
2128
|
excludedDirectories: input.options.excludedProjectDirectories
|
|
2115
2129
|
}) : void 0;
|
|
2130
|
+
const remainingBaselineBudgetMs = input.deadlineEpochMs === null ? null : remainingDeadlineBudgetMs(input.deadlineEpochMs);
|
|
2131
|
+
if (remainingBaselineBudgetMs === 0) return null;
|
|
2132
|
+
const baselineDeadlineSignal = remainingBaselineBudgetMs === null ? void 0 : AbortSignal.timeout(remainingBaselineBudgetMs);
|
|
2133
|
+
const baselineListingSignal = baselineDeadlineSignal === void 0 ? input.oxlintRuntime.abortSignal : input.oxlintRuntime.abortSignal === void 0 ? baselineDeadlineSignal : AbortSignal.any([input.oxlintRuntime.abortSignal, baselineDeadlineSignal]);
|
|
2134
|
+
let maintainabilitySourceFiles = [];
|
|
2135
|
+
if (input.options.deadCode) try {
|
|
2136
|
+
maintainabilitySourceFiles = (await listSourceFilesCooperative(input.directory, baselineListingSignal)).filter((filePath) => JSX_DUPLICATION_SOURCE_FILE_PATTERN.test(filePath) && classifyFileContext(filePath) === "production");
|
|
2137
|
+
} catch (error) {
|
|
2138
|
+
if (baselineDeadlineSignal?.aborted) return null;
|
|
2139
|
+
throw error;
|
|
2140
|
+
}
|
|
2141
|
+
const temporaryDirectory = mkdtempSync(path.join(tmpdir(), BASELINE_FILES_TEMP_DIR_PREFIX));
|
|
2116
2142
|
const snapshot = await materializeBaselineFiles({
|
|
2117
2143
|
directory: input.directory,
|
|
2118
2144
|
ref: input.baselineRef,
|
|
2119
|
-
files: baselineIncludePaths,
|
|
2120
|
-
baseFiles: baselineBaseFiles,
|
|
2121
|
-
headFiles: baselineHeadFiles,
|
|
2145
|
+
files: input.options.deadCode ? input.options.includePaths : baselineIncludePaths,
|
|
2146
|
+
baseFiles: input.options.deadCode ? input.baseFiles : baselineBaseFiles,
|
|
2147
|
+
headFiles: input.options.deadCode ? input.headFiles : baselineHeadFiles,
|
|
2122
2148
|
tempDirectory: temporaryDirectory
|
|
2123
2149
|
}).catch((error) => {
|
|
2124
2150
|
rmSync(temporaryDirectory, {
|
|
@@ -2136,22 +2162,47 @@ const runBaselineComparison = async (input) => {
|
|
|
2136
2162
|
}
|
|
2137
2163
|
try {
|
|
2138
2164
|
if (!snapshot.isComplete) return null;
|
|
2165
|
+
if (input.options.deadCode && !await copyUnchangedBaselineSources({
|
|
2166
|
+
directory: input.directory,
|
|
2167
|
+
sourceFiles: maintainabilitySourceFiles,
|
|
2168
|
+
baseMaterializedFiles: snapshot.materializedFiles,
|
|
2169
|
+
headChangedFiles: snapshot.headFiles,
|
|
2170
|
+
untrackedFiles: snapshot.untrackedFiles,
|
|
2171
|
+
tempDirectory: snapshot.tempDirectory,
|
|
2172
|
+
deadlineEpochMs: input.deadlineEpochMs,
|
|
2173
|
+
signal: input.oxlintRuntime.abortSignal
|
|
2174
|
+
})) return null;
|
|
2175
|
+
const filteredSnapshotBaseFiles = filterPathsOutsideDirectories({
|
|
2176
|
+
rootDirectory: input.directory,
|
|
2177
|
+
relativePaths: snapshot.baseFiles,
|
|
2178
|
+
excludedDirectories: input.options.excludedProjectDirectories
|
|
2179
|
+
});
|
|
2180
|
+
const filteredSnapshotHeadFiles = filterPathsOutsideDirectories({
|
|
2181
|
+
rootDirectory: input.directory,
|
|
2182
|
+
relativePaths: snapshot.headFiles,
|
|
2183
|
+
excludedDirectories: input.options.excludedProjectDirectories
|
|
2184
|
+
});
|
|
2139
2185
|
const analyzedHeadFiles = new Set(input.headAnalyzedFiles.map(toForwardSlashes));
|
|
2140
|
-
const baseFiles = new Set(
|
|
2141
|
-
const expectedHeadFiles = new Set(
|
|
2186
|
+
const baseFiles = new Set((baselineBaseFiles ?? filteredSnapshotBaseFiles).map(toForwardSlashes));
|
|
2187
|
+
const expectedHeadFiles = new Set((baselineHeadFiles ?? filteredSnapshotHeadFiles).map(toForwardSlashes));
|
|
2142
2188
|
for (const filePath of baselineIncludePaths) {
|
|
2143
2189
|
const normalizedFilePath = toForwardSlashes(filePath);
|
|
2144
2190
|
if (!baseFiles.has(normalizedFilePath)) expectedHeadFiles.add(normalizedFilePath);
|
|
2145
2191
|
}
|
|
2146
|
-
if (filterSourceFiles([...expectedHeadFiles]).some((filePath) => !analyzedHeadFiles.has(filePath))) return null;
|
|
2192
|
+
if (input.options.lint && filterSourceFiles([...expectedHeadFiles]).some((filePath) => !analyzedHeadFiles.has(filePath))) return null;
|
|
2193
|
+
const baselineLintPaths = new Set([...baselineIncludePaths, ...filteredSnapshotBaseFiles].map(toForwardSlashes));
|
|
2194
|
+
const materializedLintPaths = snapshot.materializedFiles.filter((filePath) => baselineLintPaths.has(toForwardSlashes(filePath)));
|
|
2195
|
+
const maintainabilityFocusPaths = [...new Set([...input.options.includePaths, ...snapshot.baseFiles].map(toForwardSlashes))];
|
|
2196
|
+
const baselineExcludedProjectDirectories = input.options.excludedProjectDirectories.map((excludedDirectory) => path.resolve(excludedDirectory)).filter((excludedDirectory) => isPathInsideDirectory(excludedDirectory, input.directory)).map((excludedDirectory) => path.resolve(snapshot.tempDirectory, path.relative(input.directory, excludedDirectory)));
|
|
2197
|
+
const baseIncludePaths = materializedLintPaths.length > 0 ? materializedLintPaths : maintainabilityFocusPaths;
|
|
2147
2198
|
const runtimeLayers = buildRuntimeLayers({
|
|
2148
2199
|
directory: snapshot.tempDirectory,
|
|
2149
2200
|
hasConfigOverride: true,
|
|
2150
2201
|
userConfig: input.userConfig,
|
|
2151
2202
|
configSourceDirectory: input.configSourceDirectory,
|
|
2152
2203
|
projectInfoOverride: input.headProjectInfo,
|
|
2153
|
-
shouldSkipLint: !input.options.lint || !input.resolvedNodeBinaryPath,
|
|
2154
|
-
shouldRunDeadCode:
|
|
2204
|
+
shouldSkipLint: !input.options.lint || !input.resolvedNodeBinaryPath || materializedLintPaths.length === 0,
|
|
2205
|
+
shouldRunDeadCode: input.options.deadCode,
|
|
2155
2206
|
shouldRunSupplyChain: input.options.supplyChain,
|
|
2156
2207
|
shouldComputeScore: false,
|
|
2157
2208
|
shouldShowProgressSpinners: false,
|
|
@@ -2160,7 +2211,8 @@ const runBaselineComparison = async (input) => {
|
|
|
2160
2211
|
});
|
|
2161
2212
|
const baseOutput = await runPromise(restoreLegacyThrow(runInspect({
|
|
2162
2213
|
directory: snapshot.tempDirectory,
|
|
2163
|
-
includePaths:
|
|
2214
|
+
includePaths: baseIncludePaths,
|
|
2215
|
+
maintainabilityFocusPaths,
|
|
2164
2216
|
customRulesOnly: input.options.customRulesOnly,
|
|
2165
2217
|
respectInlineDisables: input.options.respectInlineDisables,
|
|
2166
2218
|
warnings: input.options.warnings,
|
|
@@ -2169,7 +2221,7 @@ const runBaselineComparison = async (input) => {
|
|
|
2169
2221
|
includedTags: input.options.includedTags,
|
|
2170
2222
|
includeTagDefaults: input.options.includeTagDefaults,
|
|
2171
2223
|
nodeBinaryPath: input.resolvedNodeBinaryPath ?? void 0,
|
|
2172
|
-
runDeadCode:
|
|
2224
|
+
runDeadCode: input.options.deadCode,
|
|
2173
2225
|
isCi: input.options.isCi,
|
|
2174
2226
|
doctorVersion: VERSION,
|
|
2175
2227
|
runId: getRunId(),
|
|
@@ -2177,10 +2229,16 @@ const runBaselineComparison = async (input) => {
|
|
|
2177
2229
|
suppressScanSummary: true,
|
|
2178
2230
|
supplyChainManifestChanged: input.options.supplyChainManifestChanged,
|
|
2179
2231
|
deadlineEpochMs: input.deadlineEpochMs ?? void 0,
|
|
2180
|
-
signal: input.oxlintRuntime.abortSignal
|
|
2232
|
+
signal: input.oxlintRuntime.abortSignal,
|
|
2233
|
+
excludedProjectDirectories: baselineExcludedProjectDirectories,
|
|
2234
|
+
retainExcludedProjectDeadCodeDiagnostics: input.options.retainExcludedProjectDeadCodeDiagnostics
|
|
2181
2235
|
}, {}).pipe(provide(runtimeLayers), provideService(PerFileLintCacheEnabled, false), provideService(SidecarLintCacheEnabled, false), provideService(Console, silentConsole$1))), { signal: input.oxlintRuntime.abortSignal });
|
|
2182
|
-
if (baseOutput.didLintFail || countIncompleteLintFiles(baseOutput.lintPartialFailures) > 0) return null;
|
|
2183
|
-
const hasUnscannedUntrackedSourceFiles = filterSourceFiles(
|
|
2236
|
+
if (baseOutput.didLintFail || baseOutput.didDeadCodeFail || countIncompleteLintFiles(baseOutput.lintPartialFailures) > 0) return null;
|
|
2237
|
+
const hasUnscannedUntrackedSourceFiles = filterSourceFiles(filterPathsOutsideDirectories({
|
|
2238
|
+
rootDirectory: input.directory,
|
|
2239
|
+
relativePaths: snapshot.untrackedFiles,
|
|
2240
|
+
excludedDirectories: input.options.excludedProjectDirectories
|
|
2241
|
+
}).map(toForwardSlashes)).some((filePath) => !analyzedHeadFiles.has(filePath));
|
|
2184
2242
|
const diagnosticDelta = computeDiagnosticDelta({
|
|
2185
2243
|
headDiagnostics: input.headDiagnostics,
|
|
2186
2244
|
baseDiagnostics: baseOutput.diagnostics,
|
|
@@ -2353,6 +2411,7 @@ const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOv
|
|
|
2353
2411
|
directory,
|
|
2354
2412
|
precomputedSourceFileCount: options.precomputedSourceFileCount,
|
|
2355
2413
|
includePaths: options.includePaths,
|
|
2414
|
+
changedLineRanges: options.changedLineRanges ?? void 0,
|
|
2356
2415
|
customRulesOnly: options.customRulesOnly,
|
|
2357
2416
|
respectInlineDisables: options.respectInlineDisables,
|
|
2358
2417
|
warnings: options.warnings,
|
|
@@ -2383,7 +2442,7 @@ const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOv
|
|
|
2383
2442
|
else runSync(error(highlighter.error(lintFailureReason)));
|
|
2384
2443
|
let inspectDiagnostics = output.diagnostics;
|
|
2385
2444
|
let baselineDelta;
|
|
2386
|
-
if (options.baseline && isDiffMode && !didLintFail && countIncompleteLintFiles(output.lintPartialFailures) === 0) {
|
|
2445
|
+
if (options.baseline && isDiffMode && !didLintFail && !output.didDeadCodeFail && countIncompleteLintFiles(output.lintPartialFailures) === 0) {
|
|
2387
2446
|
const comparison = await runBaselineComparison({
|
|
2388
2447
|
directory,
|
|
2389
2448
|
options,
|
|
@@ -2536,13 +2595,13 @@ const resolveCursorBundledNode = () => {
|
|
|
2536
2595
|
if (!localAppData) return null;
|
|
2537
2596
|
const cursorAgentRoot = path$1.join(localAppData, "cursor-agent", "versions");
|
|
2538
2597
|
try {
|
|
2539
|
-
const versions = fs$
|
|
2598
|
+
const versions = fs$2.readdirSync(cursorAgentRoot);
|
|
2540
2599
|
if (versions.length === 0) return null;
|
|
2541
2600
|
const sortedVersions = versions.sort((a, b) => b.localeCompare(a, void 0, { numeric: true }));
|
|
2542
2601
|
for (const version of sortedVersions) try {
|
|
2543
2602
|
const bundledNodePath = path$1.join(cursorAgentRoot, version, "node.exe");
|
|
2544
2603
|
const entryScriptPath = path$1.join(cursorAgentRoot, version, "index.js");
|
|
2545
|
-
if (fs$
|
|
2604
|
+
if (fs$2.statSync(bundledNodePath).isFile() && fs$2.statSync(entryScriptPath).isFile()) return {
|
|
2546
2605
|
command: bundledNodePath,
|
|
2547
2606
|
args: [entryScriptPath]
|
|
2548
2607
|
};
|
|
@@ -2556,15 +2615,15 @@ const resolveWindowsCmdEntryScript = (command) => {
|
|
|
2556
2615
|
for (const directory of pathDirectories) {
|
|
2557
2616
|
const cmdFilePath = path$1.join(directory, `${command}.cmd`);
|
|
2558
2617
|
try {
|
|
2559
|
-
if (!fs$
|
|
2618
|
+
if (!fs$2.statSync(cmdFilePath).isFile()) continue;
|
|
2560
2619
|
} catch {
|
|
2561
2620
|
continue;
|
|
2562
2621
|
}
|
|
2563
2622
|
try {
|
|
2564
|
-
const entryScriptMatch = fs$
|
|
2623
|
+
const entryScriptMatch = fs$2.readFileSync(cmdFilePath, "utf8").match(/"%(?:~dp0|dp0%)\\([^"]+\.(?:m?js|cjs))"/);
|
|
2565
2624
|
if (!entryScriptMatch) continue;
|
|
2566
2625
|
const resolvedScriptPath = path$1.resolve(directory, entryScriptMatch[1]);
|
|
2567
|
-
if (fs$
|
|
2626
|
+
if (fs$2.statSync(resolvedScriptPath).isFile()) return resolvedScriptPath;
|
|
2568
2627
|
} catch {}
|
|
2569
2628
|
}
|
|
2570
2629
|
return null;
|
|
@@ -2829,6 +2888,45 @@ const resolveProjectScan = async (rootScanTarget, projectDirectory) => {
|
|
|
2829
2888
|
};
|
|
2830
2889
|
};
|
|
2831
2890
|
//#endregion
|
|
2891
|
+
//#region src/cli/utils/highlight-code-line.ts
|
|
2892
|
+
const CODE_TOKEN_PATTERN = /\/\/.*|\/\*.*?\*\/|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`|\b(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|export|extends|false|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|type|typeof|undefined|var|void|while|with|yield)\b|\b(?:0[xob][\da-f]+|\d+(?:\.\d+)?)\b/giu;
|
|
2893
|
+
const highlightCodeLine = (codeLine) => codeLine.replace(CODE_TOKEN_PATTERN, (token) => {
|
|
2894
|
+
if (token.startsWith("/")) return highlighter.gray(token);
|
|
2895
|
+
if (token.startsWith("\"") || token.startsWith("'") || token.startsWith("`")) return highlighter.success(token);
|
|
2896
|
+
if (/^\d|^0[xob]/i.test(token)) return highlighter.warn(token);
|
|
2897
|
+
return highlighter.info(token);
|
|
2898
|
+
});
|
|
2899
|
+
//#endregion
|
|
2900
|
+
//#region src/cli/utils/render-code-frame.ts
|
|
2901
|
+
const SOURCE_LINE_BREAK_PATTERN = /\r\n|[\n\r\u2028\u2029]/;
|
|
2902
|
+
const renderCodeFrame = ({ source, line, column, endLine, message, linesAbove, linesBelow, maximumLineLength }) => {
|
|
2903
|
+
const sourceLines = source.split(SOURCE_LINE_BREAK_PATTERN);
|
|
2904
|
+
if (line < 1 || line > sourceLines.length) return null;
|
|
2905
|
+
const offendingLine = sourceLines[line - 1];
|
|
2906
|
+
if (offendingLine === void 0 || offendingLine.length > maximumLineLength) return null;
|
|
2907
|
+
const lastMarkedLine = Math.min(Math.max(endLine ?? line, line), sourceLines.length);
|
|
2908
|
+
const firstDisplayedLine = Math.max(line - linesAbove, 1);
|
|
2909
|
+
const lastDisplayedLine = Math.min(lastMarkedLine + linesBelow, sourceLines.length);
|
|
2910
|
+
const lineNumberWidth = String(lastDisplayedLine).length;
|
|
2911
|
+
const hasCaret = lastMarkedLine === line && column !== void 0;
|
|
2912
|
+
const outputLines = [];
|
|
2913
|
+
if (message && !hasCaret) outputLines.push(`${" ".repeat(lineNumberWidth + 2)}${highlighter.error(message)}`);
|
|
2914
|
+
for (let displayedLineNumber = firstDisplayedLine; displayedLineNumber <= lastDisplayedLine; displayedLineNumber += 1) {
|
|
2915
|
+
const sourceLine = sourceLines[displayedLineNumber - 1] ?? "";
|
|
2916
|
+
const isMarked = displayedLineNumber >= line && displayedLineNumber <= lastMarkedLine;
|
|
2917
|
+
const gutter = ` ${String(displayedLineNumber).padStart(lineNumberWidth)} |`;
|
|
2918
|
+
const marker = isMarked ? highlighter.error(">") : " ";
|
|
2919
|
+
outputLines.push(`${marker}${highlighter.dim(gutter)}${sourceLine.length > 0 ? ` ${highlightCodeLine(sourceLine)}` : ""}`);
|
|
2920
|
+
if (isMarked && hasCaret) {
|
|
2921
|
+
const markerSpacing = sourceLine.slice(0, Math.max(column - 1, 0)).replace(/[^\t]/g, " ");
|
|
2922
|
+
const emptyGutter = gutter.replace(/\d/g, " ");
|
|
2923
|
+
const markerMessage = message ? ` ${highlighter.error(message)}` : "";
|
|
2924
|
+
outputLines.push(` ${highlighter.dim(emptyGutter)} ${markerSpacing}${highlighter.error("^")}${markerMessage}`);
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
return outputLines.join("\n");
|
|
2928
|
+
};
|
|
2929
|
+
//#endregion
|
|
2832
2930
|
//#region src/cli/utils/resolve-absolute-path.ts
|
|
2833
2931
|
/**
|
|
2834
2932
|
* Resolves a diagnostic's `filePath` (relative to its project root, or
|
|
@@ -2851,23 +2949,20 @@ const buildCodeFrame = (input) => {
|
|
|
2851
2949
|
const absolutePath = resolveAbsolutePath(input.filePath, input.rootDirectory);
|
|
2852
2950
|
let source;
|
|
2853
2951
|
try {
|
|
2854
|
-
source = fs$
|
|
2952
|
+
source = fs$2.readFileSync(absolutePath, "utf8");
|
|
2855
2953
|
} catch {
|
|
2856
2954
|
return null;
|
|
2857
2955
|
}
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
end: { line: input.endLine }
|
|
2862
|
-
} : { start: {
|
|
2956
|
+
const endLine = input.endLine != null && input.endLine > input.line ? input.endLine : void 0;
|
|
2957
|
+
return renderCodeFrame({
|
|
2958
|
+
source,
|
|
2863
2959
|
line: input.line,
|
|
2864
|
-
column: input.column > 0 ? input.column : void 0
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
highlightCode: true,
|
|
2960
|
+
column: endLine === void 0 && input.column > 0 ? input.column : void 0,
|
|
2961
|
+
endLine,
|
|
2962
|
+
message: input.message,
|
|
2868
2963
|
linesAbove: 1,
|
|
2869
2964
|
linesBelow: 1,
|
|
2870
|
-
|
|
2965
|
+
maximumLineLength: 200
|
|
2871
2966
|
});
|
|
2872
2967
|
};
|
|
2873
2968
|
//#endregion
|
|
@@ -2991,7 +3086,7 @@ const shouldFailScanGate = (input) => {
|
|
|
2991
3086
|
return shouldBlockCi(filterScansForSurface(input.scans, "ciFailure"), input.blockingLevel);
|
|
2992
3087
|
};
|
|
2993
3088
|
//#endregion
|
|
2994
|
-
export { resolveMergeBaseRef as A,
|
|
3089
|
+
export { resolveMergeBaseRef as A, buildNoScoreMessage as B, copyToClipboard as C, deduplicateProjectScans as D, collectProjectSourceFileCounts as E, printFooter as F, formatFixRecipeLine as G, hasLintHardFailure as H, printDiagnosticsDump as I, formatLearnMoreLine as K, formatDiagnosticSite as L, pluralize as M, formatSkippedCheckLabel as N, createInvocationInspect as O, formatElapsedTime as P, hasIncompleteScoreAnalysis as R, CLI_AGENT_BINARIES as S, buildHandoffPayload as T, buildRulePriorityMap as U, buildEmptyReportMessage as V, buildSortedRuleGroups as W, resolveCliInspectOptions as _, projectManifestChanged as a, setUpGitHubActions as b, selectProjects as c, resolveProjectChangedLineRanges as d, resolveProjectDiffIncludePaths as f, resolveWorkspaceDeadCodeOwner as g, retryMissingProjectScores as h, validateModeFlags as i, printHeadlessReport as j, inspect as k, buildCodeFrame as l, resolveProjectRelativeDirectory as m, formatSkippedProjectsMessage as n, partitionProjectScanOutcomes as o, resolveProjectSourceFilePaths as p, validateIncludeUntrackedScope as r, discoverWorkspacePackages as s, shouldFailScanGate as t, resolveProjectScan as u, filterScansForSurface as v, launchCliAgent as w, detectLaunchableAgents as x, countUniqueScannedFiles as y, filterDiagnosticsByCategories as z };
|
|
2995
3090
|
|
|
2996
|
-
//# sourceMappingURL=should-fail-scan-gate-
|
|
2997
|
-
//# debugId=
|
|
3091
|
+
//# sourceMappingURL=should-fail-scan-gate-BWTNIU5h.js.map
|
|
3092
|
+
//# debugId=73ec5086-9c15-5ede-ba70-0f5b26bd0ed2
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
-
import { z as isNonInteractiveEnvironment } from "./record-metric-
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="4a59485c-bb47-54f4-8b34-a6dd3a7d7831")}catch(e){}}();
|
|
3
|
+
import { z as isNonInteractiveEnvironment } from "./record-metric-DospZkfP.js";
|
|
4
4
|
//#region src/cli/utils/should-skip-prompts.ts
|
|
5
5
|
const shouldSkipPrompts = (input = {}) => Boolean(input.yes) || Boolean(input.json) || isNonInteractiveEnvironment() || !process.stdin.isTTY;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { shouldSkipPrompts as t };
|
|
8
8
|
|
|
9
|
-
//# sourceMappingURL=should-skip-prompts-
|
|
10
|
-
//# debugId=
|
|
9
|
+
//# sourceMappingURL=should-skip-prompts-oK3MwWyB.js.map
|
|
10
|
+
//# debugId=4a59485c-bb47-54f4-8b34-a6dd3a7d7831
|