react-doctor 0.7.4 → 0.7.5-dev.0f07133
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 +8 -0
- package/dist/cli.js +291 -82
- package/dist/index.d.ts +55 -6
- package/dist/index.js +266 -67
- package/dist/lsp.js +190 -37
- package/package.json +6 -6
package/dist/lsp.js
CHANGED
|
@@ -5,10 +5,10 @@ import * as OS from "node:os";
|
|
|
5
5
|
import os from "node:os";
|
|
6
6
|
import * as Path from "node:path";
|
|
7
7
|
import path from "node:path";
|
|
8
|
+
import reactDoctorPlugin, { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_DEPENDENCY_COLLECTORS, CROSS_FILE_RULE_IDS, FRAMEWORK_SPECIFIC_RULE_KEYS, FRAMEWORK_TOKENS, MOTION_LIBRARY_PACKAGES, REACT_COMPILER_RULES, REACT_DOCTOR_RULES, classifySecurityScanFile, collectCrossFileDependencyProbes, resetManifestCaches, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor";
|
|
8
9
|
import * as NodeChildProcess from "node:child_process";
|
|
9
10
|
import { execFileSync, spawn, spawnSync } from "node:child_process";
|
|
10
|
-
import
|
|
11
|
-
import reactDoctorPlugin, { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_DEPENDENCY_COLLECTORS, CROSS_FILE_RULE_IDS, FRAMEWORK_SPECIFIC_RULE_KEYS, MOTION_LIBRARY_PACKAGES, REACT_COMPILER_RULES, REACT_DOCTOR_RULES, classifySecurityScanFile, collectCrossFileDependencyProbes, resetManifestCaches, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor";
|
|
11
|
+
import ts from "typescript";
|
|
12
12
|
import { parseJSON5 } from "confbox";
|
|
13
13
|
import * as NodeUrl from "node:url";
|
|
14
14
|
import { fileURLToPath } from "node:url";
|
|
@@ -19339,6 +19339,31 @@ var Diagnostic = class extends Class("Diagnostic")({
|
|
|
19339
19339
|
relatedLocations: optional(ArraySchema(DiagnosticRelatedLocation)),
|
|
19340
19340
|
fixGroupId: optional(String$1)
|
|
19341
19341
|
}) {};
|
|
19342
|
+
var JsonReportDiagnosticV3 = class extends Class("JsonReportDiagnosticV3")({
|
|
19343
|
+
id: String$1,
|
|
19344
|
+
normalizedFilePath: String$1,
|
|
19345
|
+
filePath: String$1,
|
|
19346
|
+
plugin: String$1,
|
|
19347
|
+
rule: String$1,
|
|
19348
|
+
severity: Severity,
|
|
19349
|
+
tags: ArraySchema(String$1),
|
|
19350
|
+
title: optional(String$1),
|
|
19351
|
+
message: String$1,
|
|
19352
|
+
help: String$1,
|
|
19353
|
+
url: optional(String$1),
|
|
19354
|
+
line: Number$1,
|
|
19355
|
+
column: Number$1,
|
|
19356
|
+
offset: optional(Number$1),
|
|
19357
|
+
length: optional(Number$1),
|
|
19358
|
+
endLine: optional(Number$1),
|
|
19359
|
+
endColumn: optional(Number$1),
|
|
19360
|
+
category: String$1,
|
|
19361
|
+
matchByOccurrence: optional(Boolean$1),
|
|
19362
|
+
fileContext: optional(Literals(["test", "story"])),
|
|
19363
|
+
suppressionHint: optional(String$1),
|
|
19364
|
+
relatedLocations: optional(ArraySchema(DiagnosticRelatedLocation)),
|
|
19365
|
+
fixGroupId: optional(String$1)
|
|
19366
|
+
}) {};
|
|
19342
19367
|
/**
|
|
19343
19368
|
* Deterministic identity string for a diagnostic. Same diagnostic
|
|
19344
19369
|
* across two scans yields the same identity; lets baselines,
|
|
@@ -19352,6 +19377,7 @@ const JsonReportMode = Literals([
|
|
|
19352
19377
|
"staged",
|
|
19353
19378
|
"baseline"
|
|
19354
19379
|
]);
|
|
19380
|
+
const Framework = Literals(FRAMEWORK_TOKENS);
|
|
19355
19381
|
var JsonReportSummary = class extends Class("JsonReportSummary")({
|
|
19356
19382
|
errorCount: Number$1,
|
|
19357
19383
|
warningCount: Number$1,
|
|
@@ -19389,13 +19415,22 @@ var JsonReportProjectEntry = class extends Class("JsonReportProjectEntry")({
|
|
|
19389
19415
|
scannedFileCount: optional(Number$1),
|
|
19390
19416
|
elapsedMilliseconds: Number$1
|
|
19391
19417
|
}) {};
|
|
19392
|
-
|
|
19393
|
-
|
|
19394
|
-
|
|
19395
|
-
|
|
19396
|
-
|
|
19397
|
-
|
|
19398
|
-
|
|
19418
|
+
var JsonReportProjectEntryV3 = class extends Class("JsonReportProjectEntryV3")({
|
|
19419
|
+
directory: String$1,
|
|
19420
|
+
packageRoot: String$1,
|
|
19421
|
+
framework: Framework,
|
|
19422
|
+
project: Unknown,
|
|
19423
|
+
diagnostics: ArraySchema(JsonReportDiagnosticV3),
|
|
19424
|
+
score: Unknown,
|
|
19425
|
+
skippedChecks: ArraySchema(String$1),
|
|
19426
|
+
skippedCheckReasons: optional(Record$1(String$1, String$1)),
|
|
19427
|
+
analyzedFiles: ArraySchema(String$1),
|
|
19428
|
+
analyzedFileCount: Number$1,
|
|
19429
|
+
complete: Boolean$1,
|
|
19430
|
+
scannedFileCount: optional(Number$1),
|
|
19431
|
+
elapsedMilliseconds: Number$1
|
|
19432
|
+
}) {};
|
|
19433
|
+
/** Original full, diff, and staged report contract. */
|
|
19399
19434
|
var JsonReportV1 = class extends Class("JsonReportV1")({
|
|
19400
19435
|
schemaVersion: Literal(1),
|
|
19401
19436
|
version: String$1,
|
|
@@ -19456,7 +19491,27 @@ var JsonReportV2 = class extends Class("JsonReportV2")({
|
|
|
19456
19491
|
elapsedMilliseconds: Number$1,
|
|
19457
19492
|
error: NullOr(JsonReportError)
|
|
19458
19493
|
}) {};
|
|
19459
|
-
|
|
19494
|
+
var JsonReportV3 = class extends Class("JsonReportV3")({
|
|
19495
|
+
schemaVersion: Literal(3),
|
|
19496
|
+
version: String$1,
|
|
19497
|
+
ok: Boolean$1,
|
|
19498
|
+
directory: String$1,
|
|
19499
|
+
mode: JsonReportMode,
|
|
19500
|
+
baselineDegraded: optional(Boolean$1),
|
|
19501
|
+
reactDetected: optional(Boolean$1),
|
|
19502
|
+
diff: NullOr(JsonReportDiffInfo),
|
|
19503
|
+
baseline: optional(JsonReportBaseline),
|
|
19504
|
+
projects: ArraySchema(JsonReportProjectEntryV3),
|
|
19505
|
+
diagnostics: ArraySchema(JsonReportDiagnosticV3),
|
|
19506
|
+
summary: JsonReportSummary,
|
|
19507
|
+
elapsedMilliseconds: Number$1,
|
|
19508
|
+
error: NullOr(JsonReportError)
|
|
19509
|
+
}) {};
|
|
19510
|
+
Union([
|
|
19511
|
+
JsonReportV1,
|
|
19512
|
+
JsonReportV2,
|
|
19513
|
+
JsonReportV3
|
|
19514
|
+
]);
|
|
19460
19515
|
//#endregion
|
|
19461
19516
|
//#region ../../node_modules/.pnpm/semver@7.7.4/node_modules/semver/internal/constants.js
|
|
19462
19517
|
var require_constants$1 = /* @__PURE__ */ __commonJSMin$1(((exports, module) => {
|
|
@@ -33037,7 +33092,7 @@ const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
|
|
|
33037
33092
|
const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
|
|
33038
33093
|
const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
|
|
33039
33094
|
const SIDECAR_LINT_CACHE_FILENAME = "sidecar-lint-cache.json";
|
|
33040
|
-
const CORE_PACKAGE_VERSION = "0.7.
|
|
33095
|
+
const CORE_PACKAGE_VERSION = "0.7.5";
|
|
33041
33096
|
const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
|
|
33042
33097
|
const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
|
|
33043
33098
|
const SUPPLY_CHAIN_PLUGIN = "socket";
|
|
@@ -33949,6 +34004,22 @@ const isPackageJsonReanimatedAware = (packageJson) => {
|
|
|
33949
34004
|
};
|
|
33950
34005
|
return Object.hasOwn(allDependencies, REANIMATED_DEPENDENCY_NAME$1);
|
|
33951
34006
|
};
|
|
34007
|
+
const SSR_DEPENDENCY_NAMES = new Set([
|
|
34008
|
+
"@react-router/cloudflare",
|
|
34009
|
+
"@react-router/node",
|
|
34010
|
+
"@react-router/serve",
|
|
34011
|
+
"vike",
|
|
34012
|
+
"vite-plugin-ssr"
|
|
34013
|
+
]);
|
|
34014
|
+
const isPackageJsonSsrAware = (packageJson) => {
|
|
34015
|
+
const allDependencies = {
|
|
34016
|
+
...packageJson.peerDependencies,
|
|
34017
|
+
...packageJson.dependencies,
|
|
34018
|
+
...packageJson.devDependencies,
|
|
34019
|
+
...packageJson.optionalDependencies
|
|
34020
|
+
};
|
|
34021
|
+
return Object.keys(allDependencies).some((packageName) => SSR_DEPENDENCY_NAMES.has(packageName));
|
|
34022
|
+
};
|
|
33952
34023
|
const getWorkspacePatterns = (rootDirectory, packageJson) => {
|
|
33953
34024
|
const pnpmPatterns = parsePnpmWorkspacePatterns(rootDirectory);
|
|
33954
34025
|
if (pnpmPatterns.length > 0) return pnpmPatterns;
|
|
@@ -34089,6 +34160,7 @@ const evaluateManifestFacts = (facts, packageJson, directory) => {
|
|
|
34089
34160
|
}
|
|
34090
34161
|
facts.hasReactNativeAwarePackage = facts.hasReactNativeAwarePackage || isPackageJsonReactNativeAware(packageJson);
|
|
34091
34162
|
facts.hasReanimatedAwarePackage = facts.hasReanimatedAwarePackage || isPackageJsonReanimatedAware(packageJson);
|
|
34163
|
+
facts.hasSsrDependency = facts.hasSsrDependency || isPackageJsonSsrAware(packageJson);
|
|
34092
34164
|
};
|
|
34093
34165
|
const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGroup }) => {
|
|
34094
34166
|
const facts = {
|
|
@@ -34110,6 +34182,7 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
|
|
|
34110
34182
|
},
|
|
34111
34183
|
hasReactNativeAwarePackage: false,
|
|
34112
34184
|
hasReanimatedAwarePackage: false,
|
|
34185
|
+
hasSsrDependency: false,
|
|
34113
34186
|
reanimatedVersion: null
|
|
34114
34187
|
};
|
|
34115
34188
|
evaluateManifestFacts(facts, rootPackageJson, rootDirectory);
|
|
@@ -34349,6 +34422,7 @@ const discoverProjectWithoutPackageJson = (directory) => {
|
|
|
34349
34422
|
hasTypeScript: hasOwnTsConfig,
|
|
34350
34423
|
hasReactCompiler: false,
|
|
34351
34424
|
hasTanStackQuery: false,
|
|
34425
|
+
hasSsrDependency: false,
|
|
34352
34426
|
preactVersion: null,
|
|
34353
34427
|
preactMajorVersion: null,
|
|
34354
34428
|
hasReactNativeWorkspace: false,
|
|
@@ -34468,6 +34542,7 @@ const discoverProject = (directory) => {
|
|
|
34468
34542
|
hasTypeScript,
|
|
34469
34543
|
hasReactCompiler: detectReactCompiler(directory, packageJson),
|
|
34470
34544
|
hasTanStackQuery: hasTanStackQuery(packageJson),
|
|
34545
|
+
hasSsrDependency: workspaceFacts.hasSsrDependency,
|
|
34471
34546
|
preactVersion,
|
|
34472
34547
|
preactMajorVersion: parseReactMajor(preactVersion),
|
|
34473
34548
|
hasReactNativeWorkspace,
|
|
@@ -35543,6 +35618,14 @@ var AmbiguousProject = class extends TaggedErrorClass()("AmbiguousProject", {
|
|
|
35543
35618
|
return `Ambiguous project at ${this.directory}: found ${this.candidates.length} candidates (${this.candidates.join(", ")})`;
|
|
35544
35619
|
}
|
|
35545
35620
|
};
|
|
35621
|
+
var ProjectDiscoveryFailed = class extends TaggedErrorClass()("ProjectDiscoveryFailed", {
|
|
35622
|
+
directory: String$1,
|
|
35623
|
+
cause: Unknown
|
|
35624
|
+
}) {
|
|
35625
|
+
get message() {
|
|
35626
|
+
return `Project discovery failed for ${this.directory}: ${pretty(fail$6(this.cause))}`;
|
|
35627
|
+
}
|
|
35628
|
+
};
|
|
35546
35629
|
var DeadCodeAnalysisFailed = class extends TaggedErrorClass()("DeadCodeAnalysisFailed", { cause: Unknown }) {
|
|
35547
35630
|
get message() {
|
|
35548
35631
|
return `Dead-code analysis failed: ${pretty(fail$6(this.cause))}`;
|
|
@@ -35577,6 +35660,7 @@ const ReactDoctorErrorReason = Union([
|
|
|
35577
35660
|
ProjectNotFound,
|
|
35578
35661
|
NoReactDependency,
|
|
35579
35662
|
AmbiguousProject,
|
|
35663
|
+
ProjectDiscoveryFailed,
|
|
35580
35664
|
DeadCodeAnalysisFailed,
|
|
35581
35665
|
GitInvocationFailed,
|
|
35582
35666
|
GitBaseBranchMissing,
|
|
@@ -37203,6 +37287,12 @@ const CLIENT_ONLY_FRAMEWORKS = new Set([
|
|
|
37203
37287
|
"react-native",
|
|
37204
37288
|
"expo"
|
|
37205
37289
|
]);
|
|
37290
|
+
const SSR_FRAMEWORKS = new Set([
|
|
37291
|
+
"nextjs",
|
|
37292
|
+
"remix",
|
|
37293
|
+
"gatsby",
|
|
37294
|
+
"tanstack-start"
|
|
37295
|
+
]);
|
|
37206
37296
|
const addMajorLadder = (capabilities, name, major, earliest, latest) => {
|
|
37207
37297
|
if (major === null) return;
|
|
37208
37298
|
const cappedMajor = Math.min(major, latest);
|
|
@@ -37215,6 +37305,7 @@ const buildCapabilities = (project) => {
|
|
|
37215
37305
|
if (project.framework === "expo" || project.framework === "react-native" || project.hasReactNativeWorkspace) capabilities.add("react-native");
|
|
37216
37306
|
if (project.expoVersion !== null) capabilities.add("expo");
|
|
37217
37307
|
if ((project.framework === "nextjs" || project.framework === "tanstack-start" || project.framework === "remix") && !project.isStaticExport) capabilities.add("server-actions");
|
|
37308
|
+
if (SSR_FRAMEWORKS.has(project.framework) || project.hasSsrDependency) capabilities.add("ssr");
|
|
37218
37309
|
if (CLIENT_ONLY_FRAMEWORKS.has(project.framework)) capabilities.add("client-only");
|
|
37219
37310
|
if (project.isStaticExport) capabilities.add("nextjs:static-export");
|
|
37220
37311
|
if (project.nextjsMajorVersion !== null && project.nextjsMajorVersion >= 15) capabilities.add("nextjs:15");
|
|
@@ -40619,6 +40710,8 @@ const spawnLintBatches = async (input) => {
|
|
|
40619
40710
|
const reasonHint = firstDropReason ? ` — first failure: ${firstDropReason}` : "";
|
|
40620
40711
|
reportSkippedFiles(droppedFiles, (fileListPreview) => `${droppedFiles.length} file(s) failed to lint and were skipped (${fileListPreview})${reasonHint}`);
|
|
40621
40712
|
reportSkippedFiles(outcome.deadlineSkippedFiles, (fileListPreview) => `${outcome.deadlineSkippedFiles.length} file(s) skipped — max scan duration reached before they were linted (${fileListPreview})`);
|
|
40713
|
+
const unavailableFiles = new Set([...droppedFiles, ...outcome.deadlineSkippedFiles]);
|
|
40714
|
+
input.onAnalyzedFiles?.([...new Set(fileBatches.flat().filter((filePath) => !unavailableFiles.has(filePath)))].sort());
|
|
40622
40715
|
return dedupeDiagnostics(diagnostics);
|
|
40623
40716
|
};
|
|
40624
40717
|
let didValidate = false;
|
|
@@ -40875,12 +40968,18 @@ const reactHooksJsPluginDropNote = (error) => {
|
|
|
40875
40968
|
* 6. always restore disable directives + clean up the temp dir
|
|
40876
40969
|
*/
|
|
40877
40970
|
const runOxlint = async (options) => {
|
|
40878
|
-
const { rootDirectory, project, includePaths, nodeBinaryPath = process.execPath, customRulesOnly = false, respectInlineDisables = true, adoptExistingLintConfig = true, ignoredTags = /* @__PURE__ */ new Set(), userConfig, configSourceDirectory = rootDirectory, onPartialFailure, perFileLintCacheEnabled = false, sidecarLintCacheEnabled = false, onCacheStats, onSidecarStats, spawnTimeoutMs, outputMaxBytes, lintBatchOrdering = "cost" } = options;
|
|
40971
|
+
const { rootDirectory, project, includePaths, nodeBinaryPath = process.execPath, customRulesOnly = false, respectInlineDisables = true, adoptExistingLintConfig = true, ignoredTags = /* @__PURE__ */ new Set(), userConfig, configSourceDirectory = rootDirectory, onPartialFailure, onFileCoverage, perFileLintCacheEnabled = false, sidecarLintCacheEnabled = false, onCacheStats, onSidecarStats, spawnTimeoutMs, outputMaxBytes, lintBatchOrdering = "cost" } = options;
|
|
40879
40972
|
const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
|
|
40880
40973
|
const severityControls = buildRuleSeverityControls(userConfig);
|
|
40881
40974
|
validateRuleRegistration();
|
|
40882
40975
|
resetManifestCaches();
|
|
40883
|
-
if (includePaths !== void 0 && includePaths.length === 0)
|
|
40976
|
+
if (includePaths !== void 0 && includePaths.length === 0) {
|
|
40977
|
+
onFileCoverage?.({
|
|
40978
|
+
candidateFiles: [],
|
|
40979
|
+
analyzedFiles: []
|
|
40980
|
+
});
|
|
40981
|
+
return [];
|
|
40982
|
+
}
|
|
40884
40983
|
const pluginPath = resolvePluginPath();
|
|
40885
40984
|
const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
|
|
40886
40985
|
const userPlugins = resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
|
|
@@ -40941,6 +41040,7 @@ const runOxlint = async (options) => {
|
|
|
40941
41040
|
const runConfigOverFiles = async (buildConfigForPass, configFileName, files, fileProgress) => {
|
|
40942
41041
|
if (files.length === 0) return {
|
|
40943
41042
|
diagnostics: [],
|
|
41043
|
+
analyzedFiles: [],
|
|
40944
41044
|
didDropReactHooksJsPlugin: false,
|
|
40945
41045
|
hadPartialFailure: false
|
|
40946
41046
|
};
|
|
@@ -40952,24 +41052,32 @@ const runOxlint = async (options) => {
|
|
|
40952
41052
|
const passConfigPath = Path.join(configDirectory, configFileName);
|
|
40953
41053
|
const passBaseArgs = makeBaseArgs(passConfigPath);
|
|
40954
41054
|
const passFileBatches = buildFileBatches(passBaseArgs, files);
|
|
40955
|
-
|
|
40956
|
-
|
|
40957
|
-
|
|
40958
|
-
|
|
40959
|
-
|
|
40960
|
-
|
|
40961
|
-
|
|
40962
|
-
|
|
40963
|
-
|
|
40964
|
-
|
|
40965
|
-
|
|
40966
|
-
|
|
40967
|
-
|
|
40968
|
-
|
|
41055
|
+
let analyzedFiles = [];
|
|
41056
|
+
const spawnPass = () => {
|
|
41057
|
+
analyzedFiles = [];
|
|
41058
|
+
return spawnLintBatches({
|
|
41059
|
+
baseArgs: passBaseArgs,
|
|
41060
|
+
fileBatches: passFileBatches,
|
|
41061
|
+
rootDirectory,
|
|
41062
|
+
nodeBinaryPath,
|
|
41063
|
+
project,
|
|
41064
|
+
onPartialFailure: reportPartialFailure,
|
|
41065
|
+
onAnalyzedFiles: (filePaths) => {
|
|
41066
|
+
analyzedFiles = filePaths;
|
|
41067
|
+
},
|
|
41068
|
+
onFileProgress: fileProgress,
|
|
41069
|
+
spawnTimeoutMs,
|
|
41070
|
+
outputMaxBytes,
|
|
41071
|
+
concurrency: options.concurrency,
|
|
41072
|
+
signal: options.signal,
|
|
41073
|
+
deadlineEpochMs: options.deadlineEpochMs
|
|
41074
|
+
});
|
|
41075
|
+
};
|
|
40969
41076
|
writeOxlintConfig(passConfigPath, buildConfigForPass({}));
|
|
40970
41077
|
try {
|
|
40971
41078
|
return {
|
|
40972
41079
|
diagnostics: await spawnPass(),
|
|
41080
|
+
analyzedFiles,
|
|
40973
41081
|
didDropReactHooksJsPlugin: false,
|
|
40974
41082
|
hadPartialFailure
|
|
40975
41083
|
};
|
|
@@ -40981,6 +41089,7 @@ const runOxlint = async (options) => {
|
|
|
40981
41089
|
reportPartialFailure(reactHooksJsDropNote);
|
|
40982
41090
|
return {
|
|
40983
41091
|
diagnostics,
|
|
41092
|
+
analyzedFiles,
|
|
40984
41093
|
didDropReactHooksJsPlugin: true,
|
|
40985
41094
|
hadPartialFailure
|
|
40986
41095
|
};
|
|
@@ -41056,6 +41165,7 @@ const runOxlint = async (options) => {
|
|
|
41056
41165
|
const missFileSet = new Set(missFiles);
|
|
41057
41166
|
const hitFiles = candidateFiles.filter((candidateFile) => !missFileSet.has(candidateFile));
|
|
41058
41167
|
const sidecarReplayedDiagnostics = [];
|
|
41168
|
+
const sidecarReplayedFiles = [];
|
|
41059
41169
|
const sidecarLintFiles = [];
|
|
41060
41170
|
if (sidecarCache === null) sidecarLintFiles.push(...hitFiles);
|
|
41061
41171
|
else {
|
|
@@ -41063,8 +41173,10 @@ const runOxlint = async (options) => {
|
|
|
41063
41173
|
for (const hitFile of hitFiles) {
|
|
41064
41174
|
const cacheKey = cacheKeyByFile.get(hitFile);
|
|
41065
41175
|
const entry = cacheKey === void 0 ? null : sidecarCache.lookup(cacheKey);
|
|
41066
|
-
if (entry !== null && entry.probes.every((probe) => probeAnswers.answerFor(probe.kind, probe.path) === probe.answer))
|
|
41067
|
-
|
|
41176
|
+
if (entry !== null && entry.probes.every((probe) => probeAnswers.answerFor(probe.kind, probe.path) === probe.answer)) {
|
|
41177
|
+
sidecarReplayedFiles.push(hitFile);
|
|
41178
|
+
sidecarReplayedDiagnostics.push(...entry.diagnostics);
|
|
41179
|
+
} else sidecarLintFiles.push(hitFile);
|
|
41068
41180
|
if (performance.now() - verifySliceStartedAt >= 12) {
|
|
41069
41181
|
await yieldToEventLoop();
|
|
41070
41182
|
verifySliceStartedAt = performance.now();
|
|
@@ -41090,6 +41202,7 @@ const runOxlint = async (options) => {
|
|
|
41090
41202
|
sidecarRuleIdFilter: new Set(unboundedSidecarRuleIds)
|
|
41091
41203
|
}), "oxlintrc.sidecar-unbounded.json", hitFiles, void 0) : {
|
|
41092
41204
|
diagnostics: [],
|
|
41205
|
+
analyzedFiles: [],
|
|
41093
41206
|
didDropReactHooksJsPlugin: false,
|
|
41094
41207
|
hadPartialFailure: false
|
|
41095
41208
|
};
|
|
@@ -41120,6 +41233,15 @@ const runOxlint = async (options) => {
|
|
|
41120
41233
|
probesByFile: await missProbesTask
|
|
41121
41234
|
}]
|
|
41122
41235
|
});
|
|
41236
|
+
const analyzedFileSet = new Set(fullResult.analyzedFiles);
|
|
41237
|
+
const boundedSidecarAnalyzedFileSet = new Set(boundedSidecarResult.analyzedFiles);
|
|
41238
|
+
const unboundedSidecarAnalyzedFileSet = new Set(unboundedSidecarResult.analyzedFiles);
|
|
41239
|
+
const sidecarReplayedFileSet = new Set(sidecarReplayedFiles);
|
|
41240
|
+
for (const hitFile of hitFiles) if (useSidecarCache ? (sidecarReplayedFileSet.has(hitFile) || boundedSidecarAnalyzedFileSet.has(hitFile)) && (unboundedSidecarRuleIds.length === 0 || unboundedSidecarAnalyzedFileSet.has(hitFile)) : boundedSidecarAnalyzedFileSet.has(hitFile)) analyzedFileSet.add(hitFile);
|
|
41241
|
+
onFileCoverage?.({
|
|
41242
|
+
candidateFiles,
|
|
41243
|
+
analyzedFiles: candidateFiles.filter((candidateFile) => analyzedFileSet.has(candidateFile))
|
|
41244
|
+
});
|
|
41123
41245
|
return dedupeDiagnostics([
|
|
41124
41246
|
...replayedDiagnostics,
|
|
41125
41247
|
...fullResult.diagnostics,
|
|
@@ -41130,6 +41252,7 @@ const runOxlint = async (options) => {
|
|
|
41130
41252
|
}
|
|
41131
41253
|
const baseArgs = makeBaseArgs(configPath);
|
|
41132
41254
|
const fileBatches = buildFileBatches(baseArgs, candidateFiles);
|
|
41255
|
+
let analyzedFiles = [];
|
|
41133
41256
|
const runBatches = () => spawnLintBatches({
|
|
41134
41257
|
baseArgs,
|
|
41135
41258
|
fileBatches,
|
|
@@ -41137,6 +41260,9 @@ const runOxlint = async (options) => {
|
|
|
41137
41260
|
nodeBinaryPath,
|
|
41138
41261
|
project,
|
|
41139
41262
|
onPartialFailure,
|
|
41263
|
+
onAnalyzedFiles: (filePaths) => {
|
|
41264
|
+
analyzedFiles = filePaths;
|
|
41265
|
+
},
|
|
41140
41266
|
onFileProgress: options.onFileProgress,
|
|
41141
41267
|
spawnTimeoutMs,
|
|
41142
41268
|
outputMaxBytes,
|
|
@@ -41146,7 +41272,12 @@ const runOxlint = async (options) => {
|
|
|
41146
41272
|
});
|
|
41147
41273
|
writeOxlintConfig(configPath, buildConfig({ extendsPaths }));
|
|
41148
41274
|
try {
|
|
41149
|
-
|
|
41275
|
+
const diagnostics = await runBatches();
|
|
41276
|
+
onFileCoverage?.({
|
|
41277
|
+
candidateFiles,
|
|
41278
|
+
analyzedFiles
|
|
41279
|
+
});
|
|
41280
|
+
return diagnostics;
|
|
41150
41281
|
} catch (error) {
|
|
41151
41282
|
const reactHooksJsDropNote = reactHooksJsPluginDropNote(error);
|
|
41152
41283
|
if (reactHooksJsDropNote !== null) {
|
|
@@ -41156,11 +41287,20 @@ const runOxlint = async (options) => {
|
|
|
41156
41287
|
}));
|
|
41157
41288
|
const diagnostics = await runBatches();
|
|
41158
41289
|
onPartialFailure?.(reactHooksJsDropNote);
|
|
41290
|
+
onFileCoverage?.({
|
|
41291
|
+
candidateFiles,
|
|
41292
|
+
analyzedFiles
|
|
41293
|
+
});
|
|
41159
41294
|
return diagnostics;
|
|
41160
41295
|
}
|
|
41161
41296
|
if (extendsPaths.length === 0) throw error;
|
|
41162
41297
|
writeOxlintConfig(configPath, buildConfig({ extendsPaths: [] }));
|
|
41163
|
-
|
|
41298
|
+
const diagnostics = await runBatches();
|
|
41299
|
+
onFileCoverage?.({
|
|
41300
|
+
candidateFiles,
|
|
41301
|
+
analyzedFiles
|
|
41302
|
+
});
|
|
41303
|
+
return diagnostics;
|
|
41164
41304
|
}
|
|
41165
41305
|
} finally {
|
|
41166
41306
|
restoreDisableDirectives();
|
|
@@ -41240,6 +41380,7 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
|
|
|
41240
41380
|
onPartialFailure: (reason) => {
|
|
41241
41381
|
collectedFailures.push(reason);
|
|
41242
41382
|
},
|
|
41383
|
+
onFileCoverage: input.onFileCoverage,
|
|
41243
41384
|
onFileProgress: input.onFileProgress,
|
|
41244
41385
|
perFileLintCacheEnabled,
|
|
41245
41386
|
sidecarLintCacheEnabled,
|
|
@@ -41332,7 +41473,10 @@ const translateProjectInfoError = (cause, directory) => {
|
|
|
41332
41473
|
directory: cause.directory,
|
|
41333
41474
|
candidates: cause.candidates
|
|
41334
41475
|
}) });
|
|
41335
|
-
return new ReactDoctorError({ reason: new
|
|
41476
|
+
return new ReactDoctorError({ reason: new ProjectDiscoveryFailed({
|
|
41477
|
+
directory,
|
|
41478
|
+
cause
|
|
41479
|
+
}) });
|
|
41336
41480
|
};
|
|
41337
41481
|
var Project = class Project extends Service()("react-doctor/Project") {
|
|
41338
41482
|
static layerNode = succeed$3(Project, Project.of({ discover: fn("Project.discover")(function* (directory) {
|
|
@@ -41944,6 +42088,7 @@ const resolveGithubActionsScoreMetadata = (environment = process.env) => {
|
|
|
41944
42088
|
...actorAssociation !== void 0 ? { githubActorAssociation: actorAssociation } : {}
|
|
41945
42089
|
};
|
|
41946
42090
|
};
|
|
42091
|
+
const toNormalizedRelativePath = (filePath, rootDirectory) => Path.relative(Path.resolve(rootDirectory), Path.resolve(rootDirectory, filePath)).replaceAll("\\", "/") || ".";
|
|
41947
42092
|
const NO_HOOKS = {
|
|
41948
42093
|
beforeLint: () => void_,
|
|
41949
42094
|
afterLint: () => void_
|
|
@@ -42042,7 +42187,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
42042
42187
|
repo
|
|
42043
42188
|
}).pipe(orElseSucceed(() => null)) : succeed$2(null));
|
|
42044
42189
|
const lintIncludePaths = (input.skipJsxIncludeFilter ? input.includePaths.length > 0 ? [...input.includePaths] : void 0 : computeExplicitLintIncludePaths([...input.includePaths], project)) ?? resolveLintIncludePaths(scanDirectory, resolvedConfig.config, project);
|
|
42045
|
-
const
|
|
42190
|
+
const fallbackScannedFilePaths = input.suppressScanSummary ? (lintIncludePaths ?? (yield* filesService.listSourceFiles(scanDirectory))).map((relativePath) => Path.resolve(scanDirectory, relativePath)) : [];
|
|
42046
42191
|
const beforeLint = hooks.beforeLint ?? NO_HOOKS.beforeLint;
|
|
42047
42192
|
const afterLint = hooks.afterLint ?? NO_HOOKS.afterLint;
|
|
42048
42193
|
yield* beforeLint(project, lintIncludePaths ?? void 0);
|
|
@@ -42147,6 +42292,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
42147
42292
|
let deadCodeCacheHit = null;
|
|
42148
42293
|
let deadCodeSummaryCacheHits = null;
|
|
42149
42294
|
let deadCodeSummaryCacheMisses = null;
|
|
42295
|
+
const lintFileCoverageState = { value: null };
|
|
42150
42296
|
const baseLintStream = linterService.run({
|
|
42151
42297
|
rootDirectory: scanDirectory,
|
|
42152
42298
|
project,
|
|
@@ -42162,6 +42308,9 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
42162
42308
|
lastReportedTotalFileCount = totalFileCount;
|
|
42163
42309
|
runSync(scanProgress.update(`Scanning files (${scannedFileCount}/${totalFileCount})${workerCountSuffix}...`));
|
|
42164
42310
|
},
|
|
42311
|
+
onFileCoverage: (coverage) => {
|
|
42312
|
+
lintFileCoverageState.value = coverage;
|
|
42313
|
+
},
|
|
42165
42314
|
onCacheStats: (cacheHitFileCount, totalConsideredFileCount) => {
|
|
42166
42315
|
lintCacheHitFileCount = cacheHitFileCount;
|
|
42167
42316
|
lintCacheTotalFileCount = totalConsideredFileCount;
|
|
@@ -42192,7 +42341,10 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
42192
42341
|
const lintFailureState = yield* get$2(lintFailure);
|
|
42193
42342
|
yield* afterLint(lintFailureState.didFail);
|
|
42194
42343
|
if (lintFailureState.didFail) yield* scanProgress.fail(formatLintFailText(lintFailureState.reasonTag, process.version));
|
|
42195
|
-
const
|
|
42344
|
+
const candidateFiles = lintFileCoverageState.value === null ? [] : [...new Set(lintFileCoverageState.value.candidateFiles.map((filePath) => toNormalizedRelativePath(filePath, scanDirectory)))];
|
|
42345
|
+
const analyzedFiles = lintFileCoverageState.value === null ? [] : [...new Set(lintFileCoverageState.value.analyzedFiles.map((filePath) => toNormalizedRelativePath(filePath, scanDirectory)))].sort();
|
|
42346
|
+
const totalFileCount = candidateFiles.length || lastReportedTotalFileCount || (lintIncludePaths?.length ?? project.sourceFileCount);
|
|
42347
|
+
const scannedFilePaths = input.suppressScanSummary ? candidateFiles.length > 0 ? candidateFiles.map((filePath) => Path.resolve(scanDirectory, filePath)) : fallbackScannedFilePaths : [];
|
|
42196
42348
|
const scannedFilesLabel = `${totalFileCount} ${totalFileCount === 1 ? "file" : "files"}`;
|
|
42197
42349
|
let deadCodeCollected = [];
|
|
42198
42350
|
if (lintFailureState.didFail) {
|
|
@@ -42274,6 +42426,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
42274
42426
|
deadCodeOverlapped: shouldOverlapDeadCode,
|
|
42275
42427
|
scannedFileCount: totalFileCount,
|
|
42276
42428
|
scannedFilePaths,
|
|
42429
|
+
analyzedFiles,
|
|
42277
42430
|
scanElapsedMilliseconds,
|
|
42278
42431
|
scanConcurrency,
|
|
42279
42432
|
supplyChainOverlapTimedOut: supplyChainResult.timedOut,
|
|
@@ -42612,7 +42765,7 @@ const computeConfigFingerprint = (projectDirectory, version) => {
|
|
|
42612
42765
|
/** Display name used in client-facing messages and progress titles. */
|
|
42613
42766
|
const SERVER_DISPLAY_NAME = "React Doctor";
|
|
42614
42767
|
/** Server version reported in `serverInfo`; injected at build, `dev` from source. */
|
|
42615
|
-
const SERVER_VERSION = "0.7.
|
|
42768
|
+
const SERVER_VERSION = "0.7.5";
|
|
42616
42769
|
/** `Diagnostic.source` shown next to every published diagnostic. */
|
|
42617
42770
|
const DIAGNOSTIC_SOURCE = "react-doctor";
|
|
42618
42771
|
/**
|
|
@@ -44663,5 +44816,5 @@ const startLanguageServer = () => {
|
|
|
44663
44816
|
};
|
|
44664
44817
|
//#endregion
|
|
44665
44818
|
export { startLanguageServer };
|
|
44666
|
-
!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]="
|
|
44667
|
-
//# debugId=
|
|
44819
|
+
!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]="c7260006-9441-53b6-807e-078a5823b211")}catch(e){}}();
|
|
44820
|
+
//# debugId=c7260006-9441-53b6-807e-078a5823b211
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-doctor",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5-dev.0f07133",
|
|
4
4
|
"description": "Your agent writes bad React. This catches it",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"accessibility",
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
"vscode-languageserver-textdocument": "^1.0.12",
|
|
66
66
|
"vscode-uri": "^3.1.0",
|
|
67
67
|
"yaml": "^2.9.0",
|
|
68
|
-
"
|
|
69
|
-
"
|
|
68
|
+
"deslop-js": "0.7.5",
|
|
69
|
+
"oxlint-plugin-react-doctor": "0.7.5-dev.0f07133"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/babel__code-frame": "^7.27.0",
|
|
@@ -74,9 +74,9 @@
|
|
|
74
74
|
"@xterm/headless": "^6.0.0",
|
|
75
75
|
"commander": "^14.0.3",
|
|
76
76
|
"ora": "^9.4.0",
|
|
77
|
-
"@react-doctor/
|
|
78
|
-
"@react-doctor/
|
|
79
|
-
"@react-doctor/language-server": "0.7.
|
|
77
|
+
"@react-doctor/api": "0.7.5",
|
|
78
|
+
"@react-doctor/core": "0.7.5",
|
|
79
|
+
"@react-doctor/language-server": "0.7.5"
|
|
80
80
|
},
|
|
81
81
|
"engines": {
|
|
82
82
|
"node": "^20.19.0 || >=22.13.0"
|