react-doctor 0.7.4-dev.99ac4ff → 0.7.4-dev.a31f5e8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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
11
  import ts from "typescript";
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";
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
- * Versioned JsonReport schema. `JsonReport` is a `Schema.Union` so we
19394
- * can add `schemaVersion: 2` later as one new union member without
19395
- * breaking existing v1 consumers (the GitHub Action keys off the
19396
- * version literal). Today's union is single-arm; the shape is
19397
- * intentional.
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
- Union([JsonReportV1, JsonReportV2]);
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) => {
@@ -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,
@@ -37212,6 +37287,12 @@ const CLIENT_ONLY_FRAMEWORKS = new Set([
37212
37287
  "react-native",
37213
37288
  "expo"
37214
37289
  ]);
37290
+ const SSR_FRAMEWORKS = new Set([
37291
+ "nextjs",
37292
+ "remix",
37293
+ "gatsby",
37294
+ "tanstack-start"
37295
+ ]);
37215
37296
  const addMajorLadder = (capabilities, name, major, earliest, latest) => {
37216
37297
  if (major === null) return;
37217
37298
  const cappedMajor = Math.min(major, latest);
@@ -37224,6 +37305,7 @@ const buildCapabilities = (project) => {
37224
37305
  if (project.framework === "expo" || project.framework === "react-native" || project.hasReactNativeWorkspace) capabilities.add("react-native");
37225
37306
  if (project.expoVersion !== null) capabilities.add("expo");
37226
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");
37227
37309
  if (CLIENT_ONLY_FRAMEWORKS.has(project.framework)) capabilities.add("client-only");
37228
37310
  if (project.isStaticExport) capabilities.add("nextjs:static-export");
37229
37311
  if (project.nextjsMajorVersion !== null && project.nextjsMajorVersion >= 15) capabilities.add("nextjs:15");
@@ -40628,6 +40710,8 @@ const spawnLintBatches = async (input) => {
40628
40710
  const reasonHint = firstDropReason ? ` — first failure: ${firstDropReason}` : "";
40629
40711
  reportSkippedFiles(droppedFiles, (fileListPreview) => `${droppedFiles.length} file(s) failed to lint and were skipped (${fileListPreview})${reasonHint}`);
40630
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());
40631
40715
  return dedupeDiagnostics(diagnostics);
40632
40716
  };
40633
40717
  let didValidate = false;
@@ -40884,12 +40968,18 @@ const reactHooksJsPluginDropNote = (error) => {
40884
40968
  * 6. always restore disable directives + clean up the temp dir
40885
40969
  */
40886
40970
  const runOxlint = async (options) => {
40887
- 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;
40888
40972
  const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
40889
40973
  const severityControls = buildRuleSeverityControls(userConfig);
40890
40974
  validateRuleRegistration();
40891
40975
  resetManifestCaches();
40892
- if (includePaths !== void 0 && includePaths.length === 0) return [];
40976
+ if (includePaths !== void 0 && includePaths.length === 0) {
40977
+ onFileCoverage?.({
40978
+ candidateFiles: [],
40979
+ analyzedFiles: []
40980
+ });
40981
+ return [];
40982
+ }
40893
40983
  const pluginPath = resolvePluginPath();
40894
40984
  const extendsPaths = (adoptExistingLintConfig && !customRulesOnly ? detectUserLintConfigPaths(rootDirectory) : []).filter(canOxlintExtendConfig);
40895
40985
  const userPlugins = resolveUserPlugins(userConfig?.plugins, configSourceDirectory);
@@ -40950,6 +41040,7 @@ const runOxlint = async (options) => {
40950
41040
  const runConfigOverFiles = async (buildConfigForPass, configFileName, files, fileProgress) => {
40951
41041
  if (files.length === 0) return {
40952
41042
  diagnostics: [],
41043
+ analyzedFiles: [],
40953
41044
  didDropReactHooksJsPlugin: false,
40954
41045
  hadPartialFailure: false
40955
41046
  };
@@ -40961,24 +41052,32 @@ const runOxlint = async (options) => {
40961
41052
  const passConfigPath = Path.join(configDirectory, configFileName);
40962
41053
  const passBaseArgs = makeBaseArgs(passConfigPath);
40963
41054
  const passFileBatches = buildFileBatches(passBaseArgs, files);
40964
- const spawnPass = () => spawnLintBatches({
40965
- baseArgs: passBaseArgs,
40966
- fileBatches: passFileBatches,
40967
- rootDirectory,
40968
- nodeBinaryPath,
40969
- project,
40970
- onPartialFailure: reportPartialFailure,
40971
- onFileProgress: fileProgress,
40972
- spawnTimeoutMs,
40973
- outputMaxBytes,
40974
- concurrency: options.concurrency,
40975
- signal: options.signal,
40976
- deadlineEpochMs: options.deadlineEpochMs
40977
- });
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
+ };
40978
41076
  writeOxlintConfig(passConfigPath, buildConfigForPass({}));
40979
41077
  try {
40980
41078
  return {
40981
41079
  diagnostics: await spawnPass(),
41080
+ analyzedFiles,
40982
41081
  didDropReactHooksJsPlugin: false,
40983
41082
  hadPartialFailure
40984
41083
  };
@@ -40990,6 +41089,7 @@ const runOxlint = async (options) => {
40990
41089
  reportPartialFailure(reactHooksJsDropNote);
40991
41090
  return {
40992
41091
  diagnostics,
41092
+ analyzedFiles,
40993
41093
  didDropReactHooksJsPlugin: true,
40994
41094
  hadPartialFailure
40995
41095
  };
@@ -41065,6 +41165,7 @@ const runOxlint = async (options) => {
41065
41165
  const missFileSet = new Set(missFiles);
41066
41166
  const hitFiles = candidateFiles.filter((candidateFile) => !missFileSet.has(candidateFile));
41067
41167
  const sidecarReplayedDiagnostics = [];
41168
+ const sidecarReplayedFiles = [];
41068
41169
  const sidecarLintFiles = [];
41069
41170
  if (sidecarCache === null) sidecarLintFiles.push(...hitFiles);
41070
41171
  else {
@@ -41072,8 +41173,10 @@ const runOxlint = async (options) => {
41072
41173
  for (const hitFile of hitFiles) {
41073
41174
  const cacheKey = cacheKeyByFile.get(hitFile);
41074
41175
  const entry = cacheKey === void 0 ? null : sidecarCache.lookup(cacheKey);
41075
- if (entry !== null && entry.probes.every((probe) => probeAnswers.answerFor(probe.kind, probe.path) === probe.answer)) sidecarReplayedDiagnostics.push(...entry.diagnostics);
41076
- else sidecarLintFiles.push(hitFile);
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);
41077
41180
  if (performance.now() - verifySliceStartedAt >= 12) {
41078
41181
  await yieldToEventLoop();
41079
41182
  verifySliceStartedAt = performance.now();
@@ -41099,6 +41202,7 @@ const runOxlint = async (options) => {
41099
41202
  sidecarRuleIdFilter: new Set(unboundedSidecarRuleIds)
41100
41203
  }), "oxlintrc.sidecar-unbounded.json", hitFiles, void 0) : {
41101
41204
  diagnostics: [],
41205
+ analyzedFiles: [],
41102
41206
  didDropReactHooksJsPlugin: false,
41103
41207
  hadPartialFailure: false
41104
41208
  };
@@ -41129,6 +41233,15 @@ const runOxlint = async (options) => {
41129
41233
  probesByFile: await missProbesTask
41130
41234
  }]
41131
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
+ });
41132
41245
  return dedupeDiagnostics([
41133
41246
  ...replayedDiagnostics,
41134
41247
  ...fullResult.diagnostics,
@@ -41139,6 +41252,7 @@ const runOxlint = async (options) => {
41139
41252
  }
41140
41253
  const baseArgs = makeBaseArgs(configPath);
41141
41254
  const fileBatches = buildFileBatches(baseArgs, candidateFiles);
41255
+ let analyzedFiles = [];
41142
41256
  const runBatches = () => spawnLintBatches({
41143
41257
  baseArgs,
41144
41258
  fileBatches,
@@ -41146,6 +41260,9 @@ const runOxlint = async (options) => {
41146
41260
  nodeBinaryPath,
41147
41261
  project,
41148
41262
  onPartialFailure,
41263
+ onAnalyzedFiles: (filePaths) => {
41264
+ analyzedFiles = filePaths;
41265
+ },
41149
41266
  onFileProgress: options.onFileProgress,
41150
41267
  spawnTimeoutMs,
41151
41268
  outputMaxBytes,
@@ -41155,7 +41272,12 @@ const runOxlint = async (options) => {
41155
41272
  });
41156
41273
  writeOxlintConfig(configPath, buildConfig({ extendsPaths }));
41157
41274
  try {
41158
- return await runBatches();
41275
+ const diagnostics = await runBatches();
41276
+ onFileCoverage?.({
41277
+ candidateFiles,
41278
+ analyzedFiles
41279
+ });
41280
+ return diagnostics;
41159
41281
  } catch (error) {
41160
41282
  const reactHooksJsDropNote = reactHooksJsPluginDropNote(error);
41161
41283
  if (reactHooksJsDropNote !== null) {
@@ -41165,11 +41287,20 @@ const runOxlint = async (options) => {
41165
41287
  }));
41166
41288
  const diagnostics = await runBatches();
41167
41289
  onPartialFailure?.(reactHooksJsDropNote);
41290
+ onFileCoverage?.({
41291
+ candidateFiles,
41292
+ analyzedFiles
41293
+ });
41168
41294
  return diagnostics;
41169
41295
  }
41170
41296
  if (extendsPaths.length === 0) throw error;
41171
41297
  writeOxlintConfig(configPath, buildConfig({ extendsPaths: [] }));
41172
- return await runBatches();
41298
+ const diagnostics = await runBatches();
41299
+ onFileCoverage?.({
41300
+ candidateFiles,
41301
+ analyzedFiles
41302
+ });
41303
+ return diagnostics;
41173
41304
  }
41174
41305
  } finally {
41175
41306
  restoreDisableDirectives();
@@ -41249,6 +41380,7 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
41249
41380
  onPartialFailure: (reason) => {
41250
41381
  collectedFailures.push(reason);
41251
41382
  },
41383
+ onFileCoverage: input.onFileCoverage,
41252
41384
  onFileProgress: input.onFileProgress,
41253
41385
  perFileLintCacheEnabled,
41254
41386
  sidecarLintCacheEnabled,
@@ -41956,6 +42088,7 @@ const resolveGithubActionsScoreMetadata = (environment = process.env) => {
41956
42088
  ...actorAssociation !== void 0 ? { githubActorAssociation: actorAssociation } : {}
41957
42089
  };
41958
42090
  };
42091
+ const toNormalizedRelativePath = (filePath, rootDirectory) => Path.relative(Path.resolve(rootDirectory), Path.resolve(rootDirectory, filePath)).replaceAll("\\", "/") || ".";
41959
42092
  const NO_HOOKS = {
41960
42093
  beforeLint: () => void_,
41961
42094
  afterLint: () => void_
@@ -42054,7 +42187,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
42054
42187
  repo
42055
42188
  }).pipe(orElseSucceed(() => null)) : succeed$2(null));
42056
42189
  const lintIncludePaths = (input.skipJsxIncludeFilter ? input.includePaths.length > 0 ? [...input.includePaths] : void 0 : computeExplicitLintIncludePaths([...input.includePaths], project)) ?? resolveLintIncludePaths(scanDirectory, resolvedConfig.config, project);
42057
- const scannedFilePaths = input.suppressScanSummary ? (lintIncludePaths ?? (yield* filesService.listSourceFiles(scanDirectory))).map((relativePath) => Path.resolve(scanDirectory, relativePath)) : [];
42190
+ const fallbackScannedFilePaths = input.suppressScanSummary ? (lintIncludePaths ?? (yield* filesService.listSourceFiles(scanDirectory))).map((relativePath) => Path.resolve(scanDirectory, relativePath)) : [];
42058
42191
  const beforeLint = hooks.beforeLint ?? NO_HOOKS.beforeLint;
42059
42192
  const afterLint = hooks.afterLint ?? NO_HOOKS.afterLint;
42060
42193
  yield* beforeLint(project, lintIncludePaths ?? void 0);
@@ -42159,6 +42292,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
42159
42292
  let deadCodeCacheHit = null;
42160
42293
  let deadCodeSummaryCacheHits = null;
42161
42294
  let deadCodeSummaryCacheMisses = null;
42295
+ const lintFileCoverageState = { value: null };
42162
42296
  const baseLintStream = linterService.run({
42163
42297
  rootDirectory: scanDirectory,
42164
42298
  project,
@@ -42174,6 +42308,9 @@ const runInspect = (input, hooks = {}) => gen(function* () {
42174
42308
  lastReportedTotalFileCount = totalFileCount;
42175
42309
  runSync(scanProgress.update(`Scanning files (${scannedFileCount}/${totalFileCount})${workerCountSuffix}...`));
42176
42310
  },
42311
+ onFileCoverage: (coverage) => {
42312
+ lintFileCoverageState.value = coverage;
42313
+ },
42177
42314
  onCacheStats: (cacheHitFileCount, totalConsideredFileCount) => {
42178
42315
  lintCacheHitFileCount = cacheHitFileCount;
42179
42316
  lintCacheTotalFileCount = totalConsideredFileCount;
@@ -42204,7 +42341,10 @@ const runInspect = (input, hooks = {}) => gen(function* () {
42204
42341
  const lintFailureState = yield* get$2(lintFailure);
42205
42342
  yield* afterLint(lintFailureState.didFail);
42206
42343
  if (lintFailureState.didFail) yield* scanProgress.fail(formatLintFailText(lintFailureState.reasonTag, process.version));
42207
- const totalFileCount = lastReportedTotalFileCount || (lintIncludePaths?.length ?? project.sourceFileCount);
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 : [];
42208
42348
  const scannedFilesLabel = `${totalFileCount} ${totalFileCount === 1 ? "file" : "files"}`;
42209
42349
  let deadCodeCollected = [];
42210
42350
  if (lintFailureState.didFail) {
@@ -42286,6 +42426,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
42286
42426
  deadCodeOverlapped: shouldOverlapDeadCode,
42287
42427
  scannedFileCount: totalFileCount,
42288
42428
  scannedFilePaths,
42429
+ analyzedFiles,
42289
42430
  scanElapsedMilliseconds,
42290
42431
  scanConcurrency,
42291
42432
  supplyChainOverlapTimedOut: supplyChainResult.timedOut,
@@ -44675,5 +44816,5 @@ const startLanguageServer = () => {
44675
44816
  };
44676
44817
  //#endregion
44677
44818
  export { startLanguageServer };
44678
- !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]="d2e32daa-f348-51ee-b9ac-760655d4ae8f")}catch(e){}}();
44679
- //# debugId=d2e32daa-f348-51ee-b9ac-760655d4ae8f
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]="c686dc30-13d8-539e-acb4-e8b997f967e6")}catch(e){}}();
44820
+ //# debugId=c686dc30-13d8-539e-acb4-e8b997f967e6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-doctor",
3
- "version": "0.7.4-dev.99ac4ff",
3
+ "version": "0.7.4-dev.a31f5e8",
4
4
  "description": "Your agent writes bad React. This catches it",
5
5
  "keywords": [
6
6
  "accessibility",
@@ -66,7 +66,7 @@
66
66
  "vscode-uri": "^3.1.0",
67
67
  "yaml": "^2.9.0",
68
68
  "deslop-js": "0.7.4",
69
- "oxlint-plugin-react-doctor": "0.7.4-dev.99ac4ff"
69
+ "oxlint-plugin-react-doctor": "0.7.4-dev.a31f5e8"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/babel__code-frame": "^7.27.0",