react-doctor 0.7.6-dev.3f22fe3 → 0.7.6-dev.4fb3694

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
@@ -33194,15 +33194,13 @@ const listSourceFilesViaFilesystem = (rootDirectory) => {
33194
33194
  const listSourceFilesWithSize = (rootDirectory) => collectSizedSourceFiles(rootDirectory, (listSourceFilesViaGit(rootDirectory) ?? listSourceFilesViaFilesystem(rootDirectory)).sort());
33195
33195
  const listSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).map((entry) => entry.path);
33196
33196
  const countSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).length;
33197
- const UTF8_BOM_CHARACTER = "";
33198
- const stripUtf8Bom = (content) => content.startsWith(UTF8_BOM_CHARACTER) ? content.slice(1) : content;
33199
33197
  const cachedPackageJsons = /* @__PURE__ */ new Map();
33200
33198
  const clearPackageJsonCache = () => {
33201
33199
  cachedPackageJsons.clear();
33202
33200
  };
33203
33201
  const readPackageJsonUncached = (packageJsonPath) => {
33204
33202
  try {
33205
- return JSON.parse(stripUtf8Bom(NFS.readFileSync(packageJsonPath, "utf-8")));
33203
+ return JSON.parse(NFS.readFileSync(packageJsonPath, "utf-8"));
33206
33204
  } catch (error) {
33207
33205
  if (error instanceof SyntaxError) return {};
33208
33206
  if (isErrnoException(error)) {
@@ -36344,49 +36342,6 @@ const assignFixGroups = (diagnostics) => {
36344
36342
  };
36345
36343
  });
36346
36344
  };
36347
- const DERIVED_STATE_RULE_PRIORITY = new Map([
36348
- ["no-initialize-state", 0],
36349
- ["no-adjust-state-on-prop-change", 1],
36350
- ["no-derived-state", 2],
36351
- ["no-derived-state-effect", 3]
36352
- ]);
36353
- const buildDiagnosticSiteKey = (diagnostic) => `${diagnostic.filePath}\u0000${diagnostic.line}\u0000${diagnostic.column}`;
36354
- const isReactDoctorRulesOfHooksDiagnostic = (diagnostic) => diagnostic.plugin === "react-doctor" && diagnostic.rule === "rules-of-hooks";
36355
- const isReactCompilerHooksDiagnostic = (diagnostic) => diagnostic.plugin === "react-hooks-js" && diagnostic.rule === "hooks";
36356
- const doDiagnosticSpansOverlap = (first, second) => {
36357
- if (first.filePath !== second.filePath || first.plugin !== second.plugin) return false;
36358
- if (first.offset !== void 0 && second.offset !== void 0) {
36359
- const firstEnd = first.offset + Math.max(first.length ?? 1, 1);
36360
- const secondEnd = second.offset + Math.max(second.length ?? 1, 1);
36361
- return first.offset < secondEnd && second.offset < firstEnd;
36362
- }
36363
- const firstEndLine = first.endLine ?? first.line;
36364
- const secondEndLine = second.endLine ?? second.line;
36365
- return first.line <= secondEndLine && second.line <= firstEndLine;
36366
- };
36367
- const keepHighestSeverity = (survivingDiagnostic, collapsedDiagnostic) => collapsedDiagnostic.severity === "error" && survivingDiagnostic.severity !== "error" ? {
36368
- ...survivingDiagnostic,
36369
- severity: "error"
36370
- } : survivingDiagnostic;
36371
- const dedupeRelatedDiagnostics = (diagnostics) => {
36372
- const reactDoctorHookSites = new Set(diagnostics.filter(isReactDoctorRulesOfHooksDiagnostic).map(buildDiagnosticSiteKey));
36373
- const uniqueDiagnostics = [];
36374
- for (const diagnostic of diagnostics) {
36375
- if (isReactCompilerHooksDiagnostic(diagnostic) && reactDoctorHookSites.has(buildDiagnosticSiteKey(diagnostic))) continue;
36376
- const priority = DERIVED_STATE_RULE_PRIORITY.get(diagnostic.rule);
36377
- if (priority !== void 0) {
36378
- const overlappingDiagnosticIndex = uniqueDiagnostics.findIndex((candidate) => candidate.rule !== diagnostic.rule && DERIVED_STATE_RULE_PRIORITY.has(candidate.rule) && doDiagnosticSpansOverlap(candidate, diagnostic));
36379
- if (overlappingDiagnosticIndex >= 0) {
36380
- const existingDiagnostic = uniqueDiagnostics[overlappingDiagnosticIndex];
36381
- const existingPriority = existingDiagnostic ? DERIVED_STATE_RULE_PRIORITY.get(existingDiagnostic.rule) : void 0;
36382
- if (existingDiagnostic && existingPriority !== void 0) uniqueDiagnostics[overlappingDiagnosticIndex] = priority < existingPriority ? keepHighestSeverity(diagnostic, existingDiagnostic) : keepHighestSeverity(existingDiagnostic, diagnostic);
36383
- continue;
36384
- }
36385
- }
36386
- uniqueDiagnostics.push(diagnostic);
36387
- }
36388
- return uniqueDiagnostics;
36389
- };
36390
36345
  const compareStrings = (left, right) => left < right ? -1 : left > right ? 1 : 0;
36391
36346
  const sortDiagnosticsStable = (diagnostics) => [...diagnostics].sort((left, right) => compareStrings(left.filePath, right.filePath) || left.line - right.line || left.column - right.column || compareStrings(left.plugin, right.plugin) || compareStrings(left.rule, right.rule) || compareStrings(left.severity, right.severity) || compareStrings(left.message, right.message));
36392
36347
  const getDirectDependencyNames = (packageJson) => new Set([...Object.keys(packageJson.dependencies ?? {}), ...Object.keys(packageJson.devDependencies ?? {})]);
@@ -36812,6 +36767,7 @@ const PNPM_WORKSPACE_FILE = "pnpm-workspace.yaml";
36812
36767
  const PNPM_LOCKFILE = "pnpm-lock.yaml";
36813
36768
  const PACKAGE_JSON_FILE = "package.json";
36814
36769
  const PNPM_HARDENING_RULE_KEY = "require-pnpm-hardening";
36770
+ const UTF8_BOM_CHAR = "";
36815
36771
  const HARDENING_SETTING_KEYS = new Set([
36816
36772
  "minimumReleaseAge",
36817
36773
  "blockExoticSubdeps",
@@ -36836,11 +36792,12 @@ const stripInlineComment = (rawValue) => {
36836
36792
  return rawValue;
36837
36793
  };
36838
36794
  const unquote = (rawValue) => rawValue.replace(/^["']|["']$/g, "");
36795
+ const stripBom = (rawContent) => rawContent.startsWith(UTF8_BOM_CHAR) ? rawContent.slice(1) : rawContent;
36839
36796
  const parseHardeningSettings = (content) => {
36840
36797
  let minimumReleaseAge = null;
36841
36798
  let blockExoticSubdeps = null;
36842
36799
  let trustPolicy = null;
36843
- const lines = stripUtf8Bom(content).split(/\r?\n/);
36800
+ const lines = stripBom(content).split(/\r?\n/);
36844
36801
  for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
36845
36802
  const lineText = lines[lineIndex];
36846
36803
  if (lineText === void 0) continue;
@@ -36874,7 +36831,7 @@ const isPnpmManagedProject = (rootDirectory) => {
36874
36831
  const packageJsonPath = Path.join(rootDirectory, PACKAGE_JSON_FILE);
36875
36832
  if (!isFile(packageJsonPath)) return false;
36876
36833
  try {
36877
- const packageJsonRaw = stripUtf8Bom(NFS.readFileSync(packageJsonPath, "utf-8"));
36834
+ const packageJsonRaw = NFS.readFileSync(packageJsonPath, "utf-8");
36878
36835
  const packageJson = JSON.parse(packageJsonRaw);
36879
36836
  if (packageJson !== null && typeof packageJson === "object" && "packageManager" in packageJson && typeof packageJson.packageManager === "string" && packageJson.packageManager.startsWith("pnpm@")) return true;
36880
36837
  } catch {
@@ -38600,7 +38557,6 @@ const parseGithubViewerPermission = (stdout) => {
38600
38557
  return /^[A-Z_]+$/.test(value) ? value.toLowerCase() : null;
38601
38558
  };
38602
38559
  const splitNullSeparated = (value) => value.split("\0").filter((entry) => entry.length > 0);
38603
- const UNTRACKED_FILE_LAST_LINE = Number.MAX_SAFE_INTEGER;
38604
38560
  /**
38605
38561
  * `Git` wraps every `git`-via-subprocess call react-doctor makes
38606
38562
  * behind a `Context.Service`. The production layer (`layerNode`)
@@ -38671,14 +38627,6 @@ var Git = class Git extends Service()("react-doctor/Git") {
38671
38627
  args,
38672
38628
  directory
38673
38629
  });
38674
- const listUntrackedFilePaths = (directory, includePaths = []) => runGit(directory, [
38675
- "ls-files",
38676
- "-z",
38677
- "--others",
38678
- "--exclude-standard",
38679
- ...includePaths.length > 0 ? ["--", ...includePaths] : []
38680
- ]).pipe(map$3((result) => result.status === 0 ? splitNullSeparated(result.stdout) : null));
38681
- const mergeUntracked = (directory, trackedFilePaths, includeUntracked) => includeUntracked ? listUntrackedFilePaths(directory).pipe(map$3((untracked) => untracked === null ? trackedFilePaths : [...new Set([...trackedFilePaths, ...untracked])])) : succeed$2(trackedFilePaths);
38682
38630
  const currentBranch = (directory) => runGit(directory, [
38683
38631
  "rev-parse",
38684
38632
  "--abbrev-ref",
@@ -38801,7 +38749,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
38801
38749
  githubViewerPermission,
38802
38750
  branchExists,
38803
38751
  mergeBase,
38804
- diffSelection: ({ directory, explicitBaseBranch, includeUntracked = false }) => gen(function* () {
38752
+ diffSelection: ({ directory, explicitBaseBranch }) => gen(function* () {
38805
38753
  if (explicitBaseBranch !== void 0 && explicitBaseBranch.trim().length === 0) return yield* fail$4(new ReactDoctorError({ reason: new GitBaseBranchInvalid({ detail: "Diff base branch cannot be empty." }) }));
38806
38754
  if (explicitBaseBranch !== void 0) {
38807
38755
  const range = parseGitDiffRange(explicitBaseBranch);
@@ -38830,7 +38778,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
38830
38778
  "HEAD"
38831
38779
  ]);
38832
38780
  if (uncommitted.status !== 0) return null;
38833
- const files = yield* mergeUntracked(directory, splitNullSeparated(uncommitted.stdout), includeUntracked);
38781
+ const files = splitNullSeparated(uncommitted.stdout);
38834
38782
  if (files.length === 0) return null;
38835
38783
  return {
38836
38784
  currentBranch: resolvedCurrentBranch,
@@ -38860,7 +38808,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
38860
38808
  currentBranch: resolvedCurrentBranch,
38861
38809
  baseBranch,
38862
38810
  diffBaseRef: mergeBaseRef,
38863
- changedFiles: yield* mergeUntracked(directory, splitNullSeparated(diff.stdout), includeUntracked),
38811
+ changedFiles: splitNullSeparated(diff.stdout),
38864
38812
  isCurrentChanges: false
38865
38813
  };
38866
38814
  }).pipe(withSpan("Git.diffSelection")),
@@ -38906,7 +38854,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
38906
38854
  stdout: result.stdout
38907
38855
  };
38908
38856
  }).pipe(withSpan("Git.grep")),
38909
- changedLineRanges: ({ directory, baseRef, cached, files, includeUntracked = false }) => gen(function* () {
38857
+ changedLineRanges: ({ directory, baseRef, cached, files }) => gen(function* () {
38910
38858
  if (files.length === 0) return [];
38911
38859
  if (baseRef !== void 0 && !isSafeGitRevision(baseRef)) return null;
38912
38860
  const result = yield* runGit(directory, [
@@ -38920,14 +38868,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
38920
38868
  ...files
38921
38869
  ]);
38922
38870
  if (result.status !== 0) return null;
38923
- const changedLineRanges = parseChangedLineRanges(result.stdout);
38924
- if (cached || !includeUntracked) return changedLineRanges;
38925
- const untrackedFilePaths = yield* listUntrackedFilePaths(directory, files);
38926
- if (untrackedFilePaths === null) return changedLineRanges;
38927
- return [...changedLineRanges, ...untrackedFilePaths.map((file) => ({
38928
- file,
38929
- ranges: [[1, UNTRACKED_FILE_LAST_LINE]]
38930
- }))];
38871
+ return parseChangedLineRanges(result.stdout);
38931
38872
  }).pipe(catch_$1((error) => error.reason._tag === "GitInvocationFailed" ? succeed$2(null) : fail$4(error)), withSpan("Git.changedLineRanges"))
38932
38873
  });
38933
38874
  })).pipe(provide$2(layer$2.pipe(provide$2(mergeAll$1(layer$1, layer)))));
@@ -39512,13 +39453,13 @@ const encodeSidecarFileEntry = (entry) => ({
39512
39453
  diagnostics: entry.diagnostics
39513
39454
  });
39514
39455
  const emptyCache = () => ({
39515
- version: 2,
39456
+ version: 1,
39516
39457
  rulesets: {}
39517
39458
  });
39518
39459
  const loadRulesetEntries = (cacheFilePath, rulesetHash) => {
39519
39460
  const entries = /* @__PURE__ */ new Map();
39520
39461
  const persisted = failOpenReadJson(cacheFilePath, emptyCache());
39521
- if (persisted.version !== 2 || !isRecord(persisted.rulesets)) return entries;
39462
+ if (persisted.version !== 1 || !isRecord(persisted.rulesets)) return entries;
39522
39463
  const bucket = persisted.rulesets[rulesetHash];
39523
39464
  if (!isRecord(bucket) || !isRecord(bucket.files)) return entries;
39524
39465
  for (const [fileKey, rawEntry] of Object.entries(bucket.files)) {
@@ -39538,7 +39479,7 @@ const createSidecarLintCache = (cacheDirectory, rulesetHash) => {
39538
39479
  },
39539
39480
  persist: () => {
39540
39481
  const onDisk = failOpenReadJson(cacheFilePath, emptyCache());
39541
- const rulesets = onDisk.version === 2 && isRecord(onDisk.rulesets) ? { ...onDisk.rulesets } : {};
39482
+ const rulesets = onDisk.version === 1 && isRecord(onDisk.rulesets) ? { ...onDisk.rulesets } : {};
39542
39483
  const existingBucket = rulesets[rulesetHash];
39543
39484
  const existingFiles = isRecord(existingBucket) && isRecord(existingBucket.files) ? existingBucket.files : {};
39544
39485
  const ourFiles = {};
@@ -39552,7 +39493,7 @@ const createSidecarLintCache = (cacheDirectory, rulesetHash) => {
39552
39493
  files: Object.fromEntries(cappedEntries)
39553
39494
  };
39554
39495
  atomicWriteJson(cacheFilePath, {
39555
- version: 2,
39496
+ version: 1,
39556
39497
  rulesets: Object.fromEntries(Object.entries(rulesets).filter(([, bucket]) => isRecord(bucket) && typeof bucket.updatedAtMs === "number").sort(([, first], [, second]) => second.updatedAtMs - first.updatedAtMs).slice(0, 8))
39557
39498
  });
39558
39499
  }
@@ -39603,6 +39544,23 @@ const resolveTsConfigRelativePath = (rootDirectory) => {
39603
39544
  for (const filename of TSCONFIG_FILENAMES) if (NFS.existsSync(Path.join(rootDirectory, filename))) return `./${filename}`;
39604
39545
  return null;
39605
39546
  };
39547
+ const DERIVED_STATE_RULE_PRIORITY = new Map([
39548
+ ["no-initialize-state", 0],
39549
+ ["no-adjust-state-on-prop-change", 1],
39550
+ ["no-derived-state", 2],
39551
+ ["no-derived-state-effect", 3]
39552
+ ]);
39553
+ const doDiagnosticSpansOverlap = (first, second) => {
39554
+ if (first.filePath !== second.filePath || first.plugin !== second.plugin) return false;
39555
+ if (first.offset !== void 0 && second.offset !== void 0) {
39556
+ const firstEnd = first.offset + Math.max(first.length ?? 1, 1);
39557
+ const secondEnd = second.offset + Math.max(second.length ?? 1, 1);
39558
+ return first.offset < secondEnd && second.offset < firstEnd;
39559
+ }
39560
+ const firstEndLine = first.endLine ?? first.line;
39561
+ const secondEndLine = second.endLine ?? second.line;
39562
+ return first.line <= secondEndLine && second.line <= firstEndLine;
39563
+ };
39606
39564
  const dedupeDiagnostics = (diagnostics) => {
39607
39565
  const seenKeys = /* @__PURE__ */ new Set();
39608
39566
  const uniqueDiagnostics = [];
@@ -39610,6 +39568,16 @@ const dedupeDiagnostics = (diagnostics) => {
39610
39568
  const key = `${diagnostic.filePath}\u0000${diagnostic.line}\u0000${diagnostic.column}\u0000${diagnostic.plugin}\u0000${diagnostic.rule}\u0000${diagnostic.severity}\u0000${diagnostic.message}`;
39611
39569
  if (seenKeys.has(key)) continue;
39612
39570
  seenKeys.add(key);
39571
+ const priority = DERIVED_STATE_RULE_PRIORITY.get(diagnostic.rule);
39572
+ if (priority !== void 0) {
39573
+ const overlappingDiagnosticIndex = uniqueDiagnostics.findIndex((candidate) => candidate.rule !== diagnostic.rule && candidate.severity === diagnostic.severity && DERIVED_STATE_RULE_PRIORITY.has(candidate.rule) && doDiagnosticSpansOverlap(candidate, diagnostic));
39574
+ if (overlappingDiagnosticIndex >= 0) {
39575
+ const existingDiagnostic = uniqueDiagnostics[overlappingDiagnosticIndex];
39576
+ const existingPriority = existingDiagnostic ? DERIVED_STATE_RULE_PRIORITY.get(existingDiagnostic.rule) : void 0;
39577
+ if (existingPriority !== void 0 && priority < existingPriority) uniqueDiagnostics[overlappingDiagnosticIndex] = diagnostic;
39578
+ continue;
39579
+ }
39580
+ }
39613
39581
  uniqueDiagnostics.push(diagnostic);
39614
39582
  }
39615
39583
  return uniqueDiagnostics;
@@ -39652,12 +39620,6 @@ const mapWithConcurrency = async (items, concurrency, task) => {
39652
39620
  if (errors.length > 0) throw errors[0];
39653
39621
  return results;
39654
39622
  };
39655
- const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
39656
- let lineNumber = 1;
39657
- const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
39658
- for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === 10) lineNumber++;
39659
- return lineNumber;
39660
- };
39661
39623
  const REANIMATED_SHARED_VALUE_HINT = "If this is a Reanimated shared value, prefer its React Compiler-compatible `.get()` / `.set()` accessors over `.value` — https://docs.swmansion.com/react-native-reanimated/docs/core/useSharedValue/#react-compiler-support";
39662
39624
  const ACCESSORS_MIN_VERSION = "3.15.0";
39663
39625
  const supportsAccessors = (reanimatedVersion) => {
@@ -40229,6 +40191,13 @@ const findOutermostEnclosingFunctionRange = (sourceFile, targetLine) => {
40229
40191
  visit(sourceFile);
40230
40192
  return foundRange;
40231
40193
  };
40194
+ const NEWLINE_BYTE = 10;
40195
+ const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
40196
+ let lineNumber = 1;
40197
+ const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
40198
+ for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === NEWLINE_BYTE) lineNumber++;
40199
+ return lineNumber;
40200
+ };
40232
40201
  /**
40233
40202
  * Drops `react-doctor/react-compiler-no-manual-memoization` diagnostics
40234
40203
  * whose enclosing function also carries a `react-hooks-js` (React
@@ -40409,11 +40378,11 @@ const buildRelatedLocations = (labels, filePath) => {
40409
40378
  }
40410
40379
  return related;
40411
40380
  };
40412
- const isOxlintSpan = (value) => isRecord(value) && typeof value.offset === "number" && typeof value.length === "number" && typeof value.line === "number" && typeof value.column === "number";
40413
- const isOxlintLabel = (value) => isRecord(value) && isOxlintSpan(value.span);
40414
- const isMappableOxlintDiagnostic = (value) => isRecord(value) && typeof value.code === "string" && value.code.length > 0 && typeof value.filename === "string" && value.filename.length > 0 && (value.severity === "warning" || value.severity === "error") && Array.isArray(value.labels) && value.labels.every(isOxlintLabel);
40415
- const isEngineFailureDiagnostic = (value) => !isRecord(value) || typeof value.filename !== "string" || value.filename.length === 0;
40416
- const isOxlintOutput = (value) => isRecord(value) && Array.isArray(value.diagnostics);
40381
+ const isOxlintOutput = (value) => {
40382
+ if (typeof value !== "object" || value === null) return false;
40383
+ const candidate = value;
40384
+ return Array.isArray(candidate.diagnostics);
40385
+ };
40417
40386
  /**
40418
40387
  * Parses one oxlint subprocess's stdout into a flat `Diagnostic[]`.
40419
40388
  * Tolerates the leading-notice-line shape oxlint sometimes prints
@@ -40432,59 +40401,23 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
40432
40401
  throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
40433
40402
  }
40434
40403
  if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
40435
- const engineFailureDiagnostic = parsed.diagnostics.find(isEngineFailureDiagnostic);
40436
- if (engineFailureDiagnostic !== void 0) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: JSON.stringify(engineFailureDiagnostic).slice(0, 600) }) });
40437
40404
  const minifiedFileCache = /* @__PURE__ */ new Map();
40438
- const sourceBufferCache = /* @__PURE__ */ new Map();
40439
- const sourceLinesCache = /* @__PURE__ */ new Map();
40440
- const resolveAbsolutePath = (filename) => Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
40441
- const readSourceBuffer = (filename) => {
40442
- const absolutePath = resolveAbsolutePath(filename);
40443
- const cached = sourceBufferCache.get(absolutePath);
40444
- if (cached !== void 0) return cached;
40445
- let sourceBuffer;
40446
- try {
40447
- sourceBuffer = NFS.readFileSync(absolutePath);
40448
- } catch {
40449
- sourceBuffer = null;
40450
- }
40451
- sourceBufferCache.set(absolutePath, sourceBuffer);
40452
- return sourceBuffer;
40453
- };
40454
- const readSourceLines = (filename) => {
40455
- const absolutePath = resolveAbsolutePath(filename);
40456
- const cached = sourceLinesCache.get(absolutePath);
40457
- if (cached !== void 0) return cached;
40458
- const sourceBuffer = readSourceBuffer(filename);
40459
- const sourceLines = sourceBuffer ? sourceBuffer.toString("utf8").split("\n") : null;
40460
- sourceLinesCache.set(absolutePath, sourceLines);
40461
- return sourceLines;
40462
- };
40463
40405
  const isMinifiedDiagnosticFile = (filename) => {
40464
- const absolutePath = resolveAbsolutePath(filename);
40406
+ const absolutePath = Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
40465
40407
  const cached = minifiedFileCache.get(absolutePath);
40466
40408
  if (cached !== void 0) return cached;
40467
40409
  const minified = isMinifiedSource(absolutePath);
40468
40410
  minifiedFileCache.set(absolutePath, minified);
40469
40411
  return minified;
40470
40412
  };
40471
- return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => isMappableOxlintDiagnostic(diagnostic) && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
40413
+ return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => diagnostic.code && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
40472
40414
  const { plugin, rule } = parseRuleCode(diagnostic.code);
40473
40415
  const primaryLabel = diagnostic.labels[0];
40474
40416
  const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
40475
40417
  const normalizedFilePath = diagnostic.filename.replaceAll("\\", "/");
40476
40418
  const primarySpan = primaryLabel?.span;
40477
- const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
40478
40419
  const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
40479
40420
  const category = resolveDiagnosticCategory(plugin, rule);
40480
- const matchByOccurrence = resolveMatchByOccurrence(rule, category);
40481
- const sourceLines = primarySpan ? readSourceLines(diagnostic.filename) : null;
40482
- const primaryLineIndex = primarySpan ? primarySpan.line - 1 : -1;
40483
- const primaryLine = sourceLines?.[primaryLineIndex];
40484
- const primaryColumnIndex = primarySpan ? primarySpan.column - 1 : -1;
40485
- const isJsxTagLabel = primaryLine !== void 0 && primaryColumnIndex >= 0 && (primaryLine[primaryColumnIndex] === "<" || primaryLine[primaryColumnIndex - 1] === "<");
40486
- const jsxOpenerEndLineIndex = sourceLines && isJsxTagLabel ? findJsxOpenerSpan(sourceLines, primaryLineIndex) : null;
40487
- const primarySpanEndLine = jsxOpenerEndLineIndex !== null ? jsxOpenerEndLineIndex + 1 : primarySpan && sourceBuffer ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset + Math.max(primarySpan.length - 1, 0)) : void 0;
40488
40421
  return {
40489
40422
  filePath: normalizedFilePath,
40490
40423
  plugin,
@@ -40498,11 +40431,10 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
40498
40431
  column: primarySpan?.column ?? 0,
40499
40432
  ...primarySpan ? {
40500
40433
  offset: primarySpan.offset,
40501
- length: primarySpan.length,
40502
- ...primarySpanEndLine !== void 0 ? { endLine: primarySpanEndLine } : {}
40434
+ length: primarySpan.length
40503
40435
  } : {},
40504
40436
  category,
40505
- ...matchByOccurrence ? { matchByOccurrence: true } : {},
40437
+ ...resolveMatchByOccurrence(rule, category) ? { matchByOccurrence: true } : {},
40506
40438
  ...relatedLocations.length > 0 ? { relatedLocations } : {}
40507
40439
  };
40508
40440
  }), rootDirectory);
@@ -42303,8 +42235,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
42303
42235
  respectInlineDisables: input.respectInlineDisables,
42304
42236
  showWarnings
42305
42237
  });
42306
- const filterPerElementPipeline = (rawStream) => rawStream.pipe(filterMap(filterMapNullable(transform.apply)));
42307
- const applyPerElementPipeline = (rawStream) => filterPerElementPipeline(rawStream).pipe(tap((diagnostic) => reporterService.emit(diagnostic)));
42238
+ const applyPerElementPipeline = (rawStream) => rawStream.pipe(filterMap(filterMapNullable(transform.apply)), tap((diagnostic) => reporterService.emit(diagnostic)));
42308
42239
  const envCollected = yield* runCollect(applyPerElementPipeline(fromIterable$1(isDiffMode ? [] : [
42309
42240
  ...checkReducedMotion(scanDirectory),
42310
42241
  ...checkPnpmHardening(scanDirectory),
@@ -42433,7 +42364,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
42433
42364
  });
42434
42365
  return empty$4;
42435
42366
  }))));
42436
- const lintCollected = dedupeRelatedDiagnostics(yield* runCollect(filterPerElementPipeline(shouldOverlapDeadCode ? baseLintStream.pipe(provideService(OxlintConcurrency, lintConcurrency)) : baseLintStream)).pipe(timeoutOption(lintPhaseTimeoutMs), flatMap$2(match$3({
42367
+ const lintCollected = yield* runCollect(applyPerElementPipeline(shouldOverlapDeadCode ? baseLintStream.pipe(provideService(OxlintConcurrency, lintConcurrency)) : baseLintStream)).pipe(timeoutOption(lintPhaseTimeoutMs), flatMap$2(match$3({
42437
42368
  onNone: () => set(lintFailure, {
42438
42369
  didFail: true,
42439
42370
  reason: `Lint analysis exceeded ${lintPhaseTimeoutMs / MILLISECONDS_PER_SECOND}s and was skipped.`,
@@ -42441,8 +42372,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
42441
42372
  reasonKind: null
42442
42373
  }).pipe(as([])),
42443
42374
  onSome: succeed$2
42444
- }))));
42445
- yield* forEach$1(lintCollected, reporterService.emit, { discard: true });
42375
+ })));
42446
42376
  const lintFailureState = yield* get$2(lintFailure);
42447
42377
  yield* afterLint(lintFailureState.didFail);
42448
42378
  if (lintFailureState.didFail) yield* scanProgress.fail(formatLintFailText(lintFailureState.reasonTag, process.version));
@@ -44560,7 +44490,6 @@ const METRIC = {
44560
44490
  cliInvoked: "cli.invoked",
44561
44491
  cliError: "cli.error",
44562
44492
  cliEnvironmentError: "cli.env_error",
44563
- stagedSnapshotDivergence: "staged.snapshot_divergence",
44564
44493
  projectDetected: "project.detected",
44565
44494
  projectPathSelected: "project.path_selected",
44566
44495
  projectConfigSelected: "project.config_selected",
@@ -44915,5 +44844,5 @@ const startLanguageServer = () => {
44915
44844
  };
44916
44845
  //#endregion
44917
44846
  export { startLanguageServer };
44918
- !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]="b75c36e9-f19d-5127-be1a-89ac93910ff0")}catch(e){}}();
44919
- //# debugId=b75c36e9-f19d-5127-be1a-89ac93910ff0
44847
+ !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]="a3135dfe-cc85-5d34-adea-93f5c29d9bcb")}catch(e){}}();
44848
+ //# debugId=a3135dfe-cc85-5d34-adea-93f5c29d9bcb
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-doctor",
3
- "version": "0.7.6-dev.3f22fe3",
3
+ "version": "0.7.6-dev.4fb3694",
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
- "deslop-js": "0.7.6",
69
- "oxlint-plugin-react-doctor": "0.7.6-dev.3f22fe3"
68
+ "oxlint-plugin-react-doctor": "0.7.6-dev.4fb3694",
69
+ "deslop-js": "0.7.6"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/babel__code-frame": "^7.27.0",
@@ -75,8 +75,8 @@
75
75
  "commander": "^14.0.3",
76
76
  "ora": "^9.4.0",
77
77
  "@react-doctor/core": "0.7.6",
78
- "@react-doctor/api": "0.7.6",
79
- "@react-doctor/language-server": "0.7.6"
78
+ "@react-doctor/language-server": "0.7.6",
79
+ "@react-doctor/api": "0.7.6"
80
80
  },
81
81
  "engines": {
82
82
  "node": "^20.19.0 || >=22.13.0"