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/index.d.ts CHANGED
@@ -10256,7 +10256,7 @@ declare const buildJsonReport: (input: BuildJsonReportInput) => JsonReportV3$1;
10256
10256
  * render diff-base mistakes (`GitBaseBranchInvalid` /
10257
10257
  * `GitBaseBranchMissing`) as clean user errors instead of crashes.
10258
10258
  */
10259
- declare const getDiffInfo: (directory: string, explicitBaseBranch?: string, includeUntracked?: boolean) => Promise<DiffInfo | null>;
10259
+ declare const getDiffInfo: (directory: string, explicitBaseBranch?: string) => Promise<DiffInfo | null>;
10260
10260
  declare const filterSourceFiles: (filePaths: string[]) => string[];
10261
10261
  /**
10262
10262
  * Programmatic façade over `Git.changedLineRanges` (the `lines` scope). Diffs
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
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]="4da79386-f10f-5bae-95ac-7333b2d6c4e8")}catch(e){}}();
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]="3e7262c1-34a6-5fd7-a4a2-5e7a15ca735d")}catch(e){}}();
3
3
  import { r as __toESM$1, t as __commonJSMin$1 } from "./chunk-N93fKeF6.js";
4
4
  import { createRequire } from "node:module";
5
5
  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";
@@ -33142,15 +33142,13 @@ const listSourceFilesViaFilesystem = (rootDirectory) => {
33142
33142
  const listSourceFilesWithSize = (rootDirectory) => collectSizedSourceFiles(rootDirectory, (listSourceFilesViaGit(rootDirectory) ?? listSourceFilesViaFilesystem(rootDirectory)).sort());
33143
33143
  const listSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).map((entry) => entry.path);
33144
33144
  const countSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).length;
33145
- const UTF8_BOM_CHARACTER = "";
33146
- const stripUtf8Bom = (content) => content.startsWith(UTF8_BOM_CHARACTER) ? content.slice(1) : content;
33147
33145
  const cachedPackageJsons = /* @__PURE__ */ new Map();
33148
33146
  const clearPackageJsonCache = () => {
33149
33147
  cachedPackageJsons.clear();
33150
33148
  };
33151
33149
  const readPackageJsonUncached = (packageJsonPath) => {
33152
33150
  try {
33153
- return JSON.parse(stripUtf8Bom(NFS.readFileSync(packageJsonPath, "utf-8")));
33151
+ return JSON.parse(NFS.readFileSync(packageJsonPath, "utf-8"));
33154
33152
  } catch (error) {
33155
33153
  if (error instanceof SyntaxError) return {};
33156
33154
  if (isErrnoException(error)) {
@@ -36366,49 +36364,6 @@ const assignFixGroups = (diagnostics) => {
36366
36364
  };
36367
36365
  });
36368
36366
  };
36369
- const DERIVED_STATE_RULE_PRIORITY = new Map([
36370
- ["no-initialize-state", 0],
36371
- ["no-adjust-state-on-prop-change", 1],
36372
- ["no-derived-state", 2],
36373
- ["no-derived-state-effect", 3]
36374
- ]);
36375
- const buildDiagnosticSiteKey = (diagnostic) => `${diagnostic.filePath}\u0000${diagnostic.line}\u0000${diagnostic.column}`;
36376
- const isReactDoctorRulesOfHooksDiagnostic = (diagnostic) => diagnostic.plugin === "react-doctor" && diagnostic.rule === "rules-of-hooks";
36377
- const isReactCompilerHooksDiagnostic = (diagnostic) => diagnostic.plugin === "react-hooks-js" && diagnostic.rule === "hooks";
36378
- const doDiagnosticSpansOverlap = (first, second) => {
36379
- if (first.filePath !== second.filePath || first.plugin !== second.plugin) return false;
36380
- if (first.offset !== void 0 && second.offset !== void 0) {
36381
- const firstEnd = first.offset + Math.max(first.length ?? 1, 1);
36382
- const secondEnd = second.offset + Math.max(second.length ?? 1, 1);
36383
- return first.offset < secondEnd && second.offset < firstEnd;
36384
- }
36385
- const firstEndLine = first.endLine ?? first.line;
36386
- const secondEndLine = second.endLine ?? second.line;
36387
- return first.line <= secondEndLine && second.line <= firstEndLine;
36388
- };
36389
- const keepHighestSeverity = (survivingDiagnostic, collapsedDiagnostic) => collapsedDiagnostic.severity === "error" && survivingDiagnostic.severity !== "error" ? {
36390
- ...survivingDiagnostic,
36391
- severity: "error"
36392
- } : survivingDiagnostic;
36393
- const dedupeRelatedDiagnostics = (diagnostics) => {
36394
- const reactDoctorHookSites = new Set(diagnostics.filter(isReactDoctorRulesOfHooksDiagnostic).map(buildDiagnosticSiteKey));
36395
- const uniqueDiagnostics = [];
36396
- for (const diagnostic of diagnostics) {
36397
- if (isReactCompilerHooksDiagnostic(diagnostic) && reactDoctorHookSites.has(buildDiagnosticSiteKey(diagnostic))) continue;
36398
- const priority = DERIVED_STATE_RULE_PRIORITY.get(diagnostic.rule);
36399
- if (priority !== void 0) {
36400
- const overlappingDiagnosticIndex = uniqueDiagnostics.findIndex((candidate) => candidate.rule !== diagnostic.rule && DERIVED_STATE_RULE_PRIORITY.has(candidate.rule) && doDiagnosticSpansOverlap(candidate, diagnostic));
36401
- if (overlappingDiagnosticIndex >= 0) {
36402
- const existingDiagnostic = uniqueDiagnostics[overlappingDiagnosticIndex];
36403
- const existingPriority = existingDiagnostic ? DERIVED_STATE_RULE_PRIORITY.get(existingDiagnostic.rule) : void 0;
36404
- if (existingDiagnostic && existingPriority !== void 0) uniqueDiagnostics[overlappingDiagnosticIndex] = priority < existingPriority ? keepHighestSeverity(diagnostic, existingDiagnostic) : keepHighestSeverity(existingDiagnostic, diagnostic);
36405
- continue;
36406
- }
36407
- }
36408
- uniqueDiagnostics.push(diagnostic);
36409
- }
36410
- return uniqueDiagnostics;
36411
- };
36412
36367
  const compareStrings = (left, right) => left < right ? -1 : left > right ? 1 : 0;
36413
36368
  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));
36414
36369
  const getDirectDependencyNames = (packageJson) => new Set([...Object.keys(packageJson.dependencies ?? {}), ...Object.keys(packageJson.devDependencies ?? {})]);
@@ -36834,6 +36789,7 @@ const PNPM_WORKSPACE_FILE = "pnpm-workspace.yaml";
36834
36789
  const PNPM_LOCKFILE = "pnpm-lock.yaml";
36835
36790
  const PACKAGE_JSON_FILE = "package.json";
36836
36791
  const PNPM_HARDENING_RULE_KEY = "require-pnpm-hardening";
36792
+ const UTF8_BOM_CHAR = "";
36837
36793
  const HARDENING_SETTING_KEYS = new Set([
36838
36794
  "minimumReleaseAge",
36839
36795
  "blockExoticSubdeps",
@@ -36858,11 +36814,12 @@ const stripInlineComment = (rawValue) => {
36858
36814
  return rawValue;
36859
36815
  };
36860
36816
  const unquote = (rawValue) => rawValue.replace(/^["']|["']$/g, "");
36817
+ const stripBom = (rawContent) => rawContent.startsWith(UTF8_BOM_CHAR) ? rawContent.slice(1) : rawContent;
36861
36818
  const parseHardeningSettings = (content) => {
36862
36819
  let minimumReleaseAge = null;
36863
36820
  let blockExoticSubdeps = null;
36864
36821
  let trustPolicy = null;
36865
- const lines = stripUtf8Bom(content).split(/\r?\n/);
36822
+ const lines = stripBom(content).split(/\r?\n/);
36866
36823
  for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
36867
36824
  const lineText = lines[lineIndex];
36868
36825
  if (lineText === void 0) continue;
@@ -36896,7 +36853,7 @@ const isPnpmManagedProject = (rootDirectory) => {
36896
36853
  const packageJsonPath = Path.join(rootDirectory, PACKAGE_JSON_FILE);
36897
36854
  if (!isFile(packageJsonPath)) return false;
36898
36855
  try {
36899
- const packageJsonRaw = stripUtf8Bom(NFS.readFileSync(packageJsonPath, "utf-8"));
36856
+ const packageJsonRaw = NFS.readFileSync(packageJsonPath, "utf-8");
36900
36857
  const packageJson = JSON.parse(packageJsonRaw);
36901
36858
  if (packageJson !== null && typeof packageJson === "object" && "packageManager" in packageJson && typeof packageJson.packageManager === "string" && packageJson.packageManager.startsWith("pnpm@")) return true;
36902
36859
  } catch {
@@ -38622,7 +38579,6 @@ const parseGithubViewerPermission = (stdout) => {
38622
38579
  return /^[A-Z_]+$/.test(value) ? value.toLowerCase() : null;
38623
38580
  };
38624
38581
  const splitNullSeparated = (value) => value.split("\0").filter((entry) => entry.length > 0);
38625
- const UNTRACKED_FILE_LAST_LINE = Number.MAX_SAFE_INTEGER;
38626
38582
  /**
38627
38583
  * `Git` wraps every `git`-via-subprocess call react-doctor makes
38628
38584
  * behind a `Context.Service`. The production layer (`layerNode`)
@@ -38693,14 +38649,6 @@ var Git = class Git extends Service()("react-doctor/Git") {
38693
38649
  args,
38694
38650
  directory
38695
38651
  });
38696
- const listUntrackedFilePaths = (directory, includePaths = []) => runGit(directory, [
38697
- "ls-files",
38698
- "-z",
38699
- "--others",
38700
- "--exclude-standard",
38701
- ...includePaths.length > 0 ? ["--", ...includePaths] : []
38702
- ]).pipe(map$3((result) => result.status === 0 ? splitNullSeparated(result.stdout) : null));
38703
- const mergeUntracked = (directory, trackedFilePaths, includeUntracked) => includeUntracked ? listUntrackedFilePaths(directory).pipe(map$3((untracked) => untracked === null ? trackedFilePaths : [...new Set([...trackedFilePaths, ...untracked])])) : succeed$2(trackedFilePaths);
38704
38652
  const currentBranch = (directory) => runGit(directory, [
38705
38653
  "rev-parse",
38706
38654
  "--abbrev-ref",
@@ -38823,7 +38771,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
38823
38771
  githubViewerPermission,
38824
38772
  branchExists,
38825
38773
  mergeBase,
38826
- diffSelection: ({ directory, explicitBaseBranch, includeUntracked = false }) => gen(function* () {
38774
+ diffSelection: ({ directory, explicitBaseBranch }) => gen(function* () {
38827
38775
  if (explicitBaseBranch !== void 0 && explicitBaseBranch.trim().length === 0) return yield* fail$4(new ReactDoctorError({ reason: new GitBaseBranchInvalid({ detail: "Diff base branch cannot be empty." }) }));
38828
38776
  if (explicitBaseBranch !== void 0) {
38829
38777
  const range = parseGitDiffRange(explicitBaseBranch);
@@ -38852,7 +38800,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
38852
38800
  "HEAD"
38853
38801
  ]);
38854
38802
  if (uncommitted.status !== 0) return null;
38855
- const files = yield* mergeUntracked(directory, splitNullSeparated(uncommitted.stdout), includeUntracked);
38803
+ const files = splitNullSeparated(uncommitted.stdout);
38856
38804
  if (files.length === 0) return null;
38857
38805
  return {
38858
38806
  currentBranch: resolvedCurrentBranch,
@@ -38882,7 +38830,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
38882
38830
  currentBranch: resolvedCurrentBranch,
38883
38831
  baseBranch,
38884
38832
  diffBaseRef: mergeBaseRef,
38885
- changedFiles: yield* mergeUntracked(directory, splitNullSeparated(diff.stdout), includeUntracked),
38833
+ changedFiles: splitNullSeparated(diff.stdout),
38886
38834
  isCurrentChanges: false
38887
38835
  };
38888
38836
  }).pipe(withSpan("Git.diffSelection")),
@@ -38928,7 +38876,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
38928
38876
  stdout: result.stdout
38929
38877
  };
38930
38878
  }).pipe(withSpan("Git.grep")),
38931
- changedLineRanges: ({ directory, baseRef, cached, files, includeUntracked = false }) => gen(function* () {
38879
+ changedLineRanges: ({ directory, baseRef, cached, files }) => gen(function* () {
38932
38880
  if (files.length === 0) return [];
38933
38881
  if (baseRef !== void 0 && !isSafeGitRevision(baseRef)) return null;
38934
38882
  const result = yield* runGit(directory, [
@@ -38942,14 +38890,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
38942
38890
  ...files
38943
38891
  ]);
38944
38892
  if (result.status !== 0) return null;
38945
- const changedLineRanges = parseChangedLineRanges(result.stdout);
38946
- if (cached || !includeUntracked) return changedLineRanges;
38947
- const untrackedFilePaths = yield* listUntrackedFilePaths(directory, files);
38948
- if (untrackedFilePaths === null) return changedLineRanges;
38949
- return [...changedLineRanges, ...untrackedFilePaths.map((file) => ({
38950
- file,
38951
- ranges: [[1, UNTRACKED_FILE_LAST_LINE]]
38952
- }))];
38893
+ return parseChangedLineRanges(result.stdout);
38953
38894
  }).pipe(catch_$1((error) => error.reason._tag === "GitInvocationFailed" ? succeed$2(null) : fail$4(error)), withSpan("Git.changedLineRanges"))
38954
38895
  });
38955
38896
  })).pipe(provide$2(layer$2.pipe(provide$2(mergeAll$1(layer$1, layer)))));
@@ -39534,13 +39475,13 @@ const encodeSidecarFileEntry = (entry) => ({
39534
39475
  diagnostics: entry.diagnostics
39535
39476
  });
39536
39477
  const emptyCache = () => ({
39537
- version: 2,
39478
+ version: 1,
39538
39479
  rulesets: {}
39539
39480
  });
39540
39481
  const loadRulesetEntries = (cacheFilePath, rulesetHash) => {
39541
39482
  const entries = /* @__PURE__ */ new Map();
39542
39483
  const persisted = failOpenReadJson(cacheFilePath, emptyCache());
39543
- if (persisted.version !== 2 || !isRecord(persisted.rulesets)) return entries;
39484
+ if (persisted.version !== 1 || !isRecord(persisted.rulesets)) return entries;
39544
39485
  const bucket = persisted.rulesets[rulesetHash];
39545
39486
  if (!isRecord(bucket) || !isRecord(bucket.files)) return entries;
39546
39487
  for (const [fileKey, rawEntry] of Object.entries(bucket.files)) {
@@ -39560,7 +39501,7 @@ const createSidecarLintCache = (cacheDirectory, rulesetHash) => {
39560
39501
  },
39561
39502
  persist: () => {
39562
39503
  const onDisk = failOpenReadJson(cacheFilePath, emptyCache());
39563
- const rulesets = onDisk.version === 2 && isRecord(onDisk.rulesets) ? { ...onDisk.rulesets } : {};
39504
+ const rulesets = onDisk.version === 1 && isRecord(onDisk.rulesets) ? { ...onDisk.rulesets } : {};
39564
39505
  const existingBucket = rulesets[rulesetHash];
39565
39506
  const existingFiles = isRecord(existingBucket) && isRecord(existingBucket.files) ? existingBucket.files : {};
39566
39507
  const ourFiles = {};
@@ -39574,7 +39515,7 @@ const createSidecarLintCache = (cacheDirectory, rulesetHash) => {
39574
39515
  files: Object.fromEntries(cappedEntries)
39575
39516
  };
39576
39517
  atomicWriteJson(cacheFilePath, {
39577
- version: 2,
39518
+ version: 1,
39578
39519
  rulesets: Object.fromEntries(Object.entries(rulesets).filter(([, bucket]) => isRecord(bucket) && typeof bucket.updatedAtMs === "number").sort(([, first], [, second]) => second.updatedAtMs - first.updatedAtMs).slice(0, 8))
39579
39520
  });
39580
39521
  }
@@ -39625,6 +39566,23 @@ const resolveTsConfigRelativePath = (rootDirectory) => {
39625
39566
  for (const filename of TSCONFIG_FILENAMES) if (NFS.existsSync(Path.join(rootDirectory, filename))) return `./${filename}`;
39626
39567
  return null;
39627
39568
  };
39569
+ const DERIVED_STATE_RULE_PRIORITY = new Map([
39570
+ ["no-initialize-state", 0],
39571
+ ["no-adjust-state-on-prop-change", 1],
39572
+ ["no-derived-state", 2],
39573
+ ["no-derived-state-effect", 3]
39574
+ ]);
39575
+ const doDiagnosticSpansOverlap = (first, second) => {
39576
+ if (first.filePath !== second.filePath || first.plugin !== second.plugin) return false;
39577
+ if (first.offset !== void 0 && second.offset !== void 0) {
39578
+ const firstEnd = first.offset + Math.max(first.length ?? 1, 1);
39579
+ const secondEnd = second.offset + Math.max(second.length ?? 1, 1);
39580
+ return first.offset < secondEnd && second.offset < firstEnd;
39581
+ }
39582
+ const firstEndLine = first.endLine ?? first.line;
39583
+ const secondEndLine = second.endLine ?? second.line;
39584
+ return first.line <= secondEndLine && second.line <= firstEndLine;
39585
+ };
39628
39586
  const dedupeDiagnostics = (diagnostics) => {
39629
39587
  const seenKeys = /* @__PURE__ */ new Set();
39630
39588
  const uniqueDiagnostics = [];
@@ -39632,6 +39590,16 @@ const dedupeDiagnostics = (diagnostics) => {
39632
39590
  const key = `${diagnostic.filePath}\u0000${diagnostic.line}\u0000${diagnostic.column}\u0000${diagnostic.plugin}\u0000${diagnostic.rule}\u0000${diagnostic.severity}\u0000${diagnostic.message}`;
39633
39591
  if (seenKeys.has(key)) continue;
39634
39592
  seenKeys.add(key);
39593
+ const priority = DERIVED_STATE_RULE_PRIORITY.get(diagnostic.rule);
39594
+ if (priority !== void 0) {
39595
+ const overlappingDiagnosticIndex = uniqueDiagnostics.findIndex((candidate) => candidate.rule !== diagnostic.rule && candidate.severity === diagnostic.severity && DERIVED_STATE_RULE_PRIORITY.has(candidate.rule) && doDiagnosticSpansOverlap(candidate, diagnostic));
39596
+ if (overlappingDiagnosticIndex >= 0) {
39597
+ const existingDiagnostic = uniqueDiagnostics[overlappingDiagnosticIndex];
39598
+ const existingPriority = existingDiagnostic ? DERIVED_STATE_RULE_PRIORITY.get(existingDiagnostic.rule) : void 0;
39599
+ if (existingPriority !== void 0 && priority < existingPriority) uniqueDiagnostics[overlappingDiagnosticIndex] = diagnostic;
39600
+ continue;
39601
+ }
39602
+ }
39635
39603
  uniqueDiagnostics.push(diagnostic);
39636
39604
  }
39637
39605
  return uniqueDiagnostics;
@@ -39674,12 +39642,6 @@ const mapWithConcurrency = async (items, concurrency, task) => {
39674
39642
  if (errors.length > 0) throw errors[0];
39675
39643
  return results;
39676
39644
  };
39677
- const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
39678
- let lineNumber = 1;
39679
- const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
39680
- for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === 10) lineNumber++;
39681
- return lineNumber;
39682
- };
39683
39645
  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";
39684
39646
  const ACCESSORS_MIN_VERSION = "3.15.0";
39685
39647
  const supportsAccessors = (reanimatedVersion) => {
@@ -40251,6 +40213,13 @@ const findOutermostEnclosingFunctionRange = (sourceFile, targetLine) => {
40251
40213
  visit(sourceFile);
40252
40214
  return foundRange;
40253
40215
  };
40216
+ const NEWLINE_BYTE = 10;
40217
+ const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
40218
+ let lineNumber = 1;
40219
+ const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
40220
+ for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === NEWLINE_BYTE) lineNumber++;
40221
+ return lineNumber;
40222
+ };
40254
40223
  /**
40255
40224
  * Drops `react-doctor/react-compiler-no-manual-memoization` diagnostics
40256
40225
  * whose enclosing function also carries a `react-hooks-js` (React
@@ -40431,11 +40400,11 @@ const buildRelatedLocations = (labels, filePath) => {
40431
40400
  }
40432
40401
  return related;
40433
40402
  };
40434
- const isOxlintSpan = (value) => isRecord(value) && typeof value.offset === "number" && typeof value.length === "number" && typeof value.line === "number" && typeof value.column === "number";
40435
- const isOxlintLabel = (value) => isRecord(value) && isOxlintSpan(value.span);
40436
- 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);
40437
- const isEngineFailureDiagnostic = (value) => !isRecord(value) || typeof value.filename !== "string" || value.filename.length === 0;
40438
- const isOxlintOutput = (value) => isRecord(value) && Array.isArray(value.diagnostics);
40403
+ const isOxlintOutput = (value) => {
40404
+ if (typeof value !== "object" || value === null) return false;
40405
+ const candidate = value;
40406
+ return Array.isArray(candidate.diagnostics);
40407
+ };
40439
40408
  /**
40440
40409
  * Parses one oxlint subprocess's stdout into a flat `Diagnostic[]`.
40441
40410
  * Tolerates the leading-notice-line shape oxlint sometimes prints
@@ -40454,59 +40423,23 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
40454
40423
  throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
40455
40424
  }
40456
40425
  if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
40457
- const engineFailureDiagnostic = parsed.diagnostics.find(isEngineFailureDiagnostic);
40458
- if (engineFailureDiagnostic !== void 0) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: JSON.stringify(engineFailureDiagnostic).slice(0, 600) }) });
40459
40426
  const minifiedFileCache = /* @__PURE__ */ new Map();
40460
- const sourceBufferCache = /* @__PURE__ */ new Map();
40461
- const sourceLinesCache = /* @__PURE__ */ new Map();
40462
- const resolveAbsolutePath = (filename) => Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
40463
- const readSourceBuffer = (filename) => {
40464
- const absolutePath = resolveAbsolutePath(filename);
40465
- const cached = sourceBufferCache.get(absolutePath);
40466
- if (cached !== void 0) return cached;
40467
- let sourceBuffer;
40468
- try {
40469
- sourceBuffer = NFS.readFileSync(absolutePath);
40470
- } catch {
40471
- sourceBuffer = null;
40472
- }
40473
- sourceBufferCache.set(absolutePath, sourceBuffer);
40474
- return sourceBuffer;
40475
- };
40476
- const readSourceLines = (filename) => {
40477
- const absolutePath = resolveAbsolutePath(filename);
40478
- const cached = sourceLinesCache.get(absolutePath);
40479
- if (cached !== void 0) return cached;
40480
- const sourceBuffer = readSourceBuffer(filename);
40481
- const sourceLines = sourceBuffer ? sourceBuffer.toString("utf8").split("\n") : null;
40482
- sourceLinesCache.set(absolutePath, sourceLines);
40483
- return sourceLines;
40484
- };
40485
40427
  const isMinifiedDiagnosticFile = (filename) => {
40486
- const absolutePath = resolveAbsolutePath(filename);
40428
+ const absolutePath = Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
40487
40429
  const cached = minifiedFileCache.get(absolutePath);
40488
40430
  if (cached !== void 0) return cached;
40489
40431
  const minified = isMinifiedSource(absolutePath);
40490
40432
  minifiedFileCache.set(absolutePath, minified);
40491
40433
  return minified;
40492
40434
  };
40493
- return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => isMappableOxlintDiagnostic(diagnostic) && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
40435
+ return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => diagnostic.code && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
40494
40436
  const { plugin, rule } = parseRuleCode(diagnostic.code);
40495
40437
  const primaryLabel = diagnostic.labels[0];
40496
40438
  const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
40497
40439
  const normalizedFilePath = diagnostic.filename.replaceAll("\\", "/");
40498
40440
  const primarySpan = primaryLabel?.span;
40499
- const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
40500
40441
  const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
40501
40442
  const category = resolveDiagnosticCategory(plugin, rule);
40502
- const matchByOccurrence = resolveMatchByOccurrence(rule, category);
40503
- const sourceLines = primarySpan ? readSourceLines(diagnostic.filename) : null;
40504
- const primaryLineIndex = primarySpan ? primarySpan.line - 1 : -1;
40505
- const primaryLine = sourceLines?.[primaryLineIndex];
40506
- const primaryColumnIndex = primarySpan ? primarySpan.column - 1 : -1;
40507
- const isJsxTagLabel = primaryLine !== void 0 && primaryColumnIndex >= 0 && (primaryLine[primaryColumnIndex] === "<" || primaryLine[primaryColumnIndex - 1] === "<");
40508
- const jsxOpenerEndLineIndex = sourceLines && isJsxTagLabel ? findJsxOpenerSpan(sourceLines, primaryLineIndex) : null;
40509
- const primarySpanEndLine = jsxOpenerEndLineIndex !== null ? jsxOpenerEndLineIndex + 1 : primarySpan && sourceBuffer ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset + Math.max(primarySpan.length - 1, 0)) : void 0;
40510
40443
  return {
40511
40444
  filePath: normalizedFilePath,
40512
40445
  plugin,
@@ -40520,11 +40453,10 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
40520
40453
  column: primarySpan?.column ?? 0,
40521
40454
  ...primarySpan ? {
40522
40455
  offset: primarySpan.offset,
40523
- length: primarySpan.length,
40524
- ...primarySpanEndLine !== void 0 ? { endLine: primarySpanEndLine } : {}
40456
+ length: primarySpan.length
40525
40457
  } : {},
40526
40458
  category,
40527
- ...matchByOccurrence ? { matchByOccurrence: true } : {},
40459
+ ...resolveMatchByOccurrence(rule, category) ? { matchByOccurrence: true } : {},
40528
40460
  ...relatedLocations.length > 0 ? { relatedLocations } : {}
40529
40461
  };
40530
40462
  }), rootDirectory);
@@ -42325,8 +42257,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
42325
42257
  respectInlineDisables: input.respectInlineDisables,
42326
42258
  showWarnings
42327
42259
  });
42328
- const filterPerElementPipeline = (rawStream) => rawStream.pipe(filterMap(filterMapNullable(transform.apply)));
42329
- const applyPerElementPipeline = (rawStream) => filterPerElementPipeline(rawStream).pipe(tap((diagnostic) => reporterService.emit(diagnostic)));
42260
+ const applyPerElementPipeline = (rawStream) => rawStream.pipe(filterMap(filterMapNullable(transform.apply)), tap((diagnostic) => reporterService.emit(diagnostic)));
42330
42261
  const envCollected = yield* runCollect(applyPerElementPipeline(fromIterable$1(isDiffMode ? [] : [
42331
42262
  ...checkReducedMotion(scanDirectory),
42332
42263
  ...checkPnpmHardening(scanDirectory),
@@ -42455,7 +42386,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
42455
42386
  });
42456
42387
  return empty$4;
42457
42388
  }))));
42458
- const lintCollected = dedupeRelatedDiagnostics(yield* runCollect(filterPerElementPipeline(shouldOverlapDeadCode ? baseLintStream.pipe(provideService(OxlintConcurrency, lintConcurrency)) : baseLintStream)).pipe(timeoutOption(lintPhaseTimeoutMs), flatMap$2(match$3({
42389
+ const lintCollected = yield* runCollect(applyPerElementPipeline(shouldOverlapDeadCode ? baseLintStream.pipe(provideService(OxlintConcurrency, lintConcurrency)) : baseLintStream)).pipe(timeoutOption(lintPhaseTimeoutMs), flatMap$2(match$3({
42459
42390
  onNone: () => set(lintFailure, {
42460
42391
  didFail: true,
42461
42392
  reason: `Lint analysis exceeded ${lintPhaseTimeoutMs / MILLISECONDS_PER_SECOND}s and was skipped.`,
@@ -42463,8 +42394,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
42463
42394
  reasonKind: null
42464
42395
  }).pipe(as([])),
42465
42396
  onSome: succeed$2
42466
- }))));
42467
- yield* forEach$1(lintCollected, reporterService.emit, { discard: true });
42397
+ })));
42468
42398
  const lintFailureState = yield* get$2(lintFailure);
42469
42399
  yield* afterLint(lintFailureState.didFail);
42470
42400
  if (lintFailureState.didFail) yield* scanProgress.fail(formatLintFailText(lintFailureState.reasonTag, process.version));
@@ -42984,11 +42914,10 @@ const buildSkippedChecks = (input) => {
42984
42914
  * render diff-base mistakes (`GitBaseBranchInvalid` /
42985
42915
  * `GitBaseBranchMissing`) as clean user errors instead of crashes.
42986
42916
  */
42987
- const getDiffInfo = (directory, explicitBaseBranch, includeUntracked) => runPromise(gen(function* () {
42917
+ const getDiffInfo = (directory, explicitBaseBranch) => runPromise(gen(function* () {
42988
42918
  const selection = yield* (yield* Git).diffSelection({
42989
42919
  directory,
42990
- explicitBaseBranch,
42991
- includeUntracked
42920
+ explicitBaseBranch
42992
42921
  });
42993
42922
  if (selection === null) return null;
42994
42923
  return {
@@ -43278,4 +43207,4 @@ const toJsonReport = (result, options) => buildJsonReport({
43278
43207
  export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
43279
43208
 
43280
43209
  //# sourceMappingURL=index.js.map
43281
- //# debugId=4da79386-f10f-5bae-95ac-7333b2d6c4e8
43210
+ //# debugId=3e7262c1-34a6-5fd7-a4a2-5e7a15ca735d