react-doctor 0.7.6-dev.0d11bd5 → 0.7.6-dev.17418
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/cli.js +61 -227
- package/dist/index.d.ts +4 -5
- package/dist/index.js +37 -87
- package/dist/lsp.js +61 -104
- package/package.json +2 -2
package/dist/lsp.js
CHANGED
|
@@ -32959,6 +32959,7 @@ const IGNORED_DIRECTORIES = new Set([
|
|
|
32959
32959
|
"out",
|
|
32960
32960
|
"storybook-static"
|
|
32961
32961
|
]);
|
|
32962
|
+
const JSX_FILE_PATTERN = /\.(tsx|jsx)$/;
|
|
32962
32963
|
const MILLISECONDS_PER_SECOND = 1e3;
|
|
32963
32964
|
const SCORE_API_URL = "https://www.react.doctor/api/score";
|
|
32964
32965
|
const FETCH_TIMEOUT_MS = 1e4;
|
|
@@ -33194,15 +33195,13 @@ const listSourceFilesViaFilesystem = (rootDirectory) => {
|
|
|
33194
33195
|
const listSourceFilesWithSize = (rootDirectory) => collectSizedSourceFiles(rootDirectory, (listSourceFilesViaGit(rootDirectory) ?? listSourceFilesViaFilesystem(rootDirectory)).sort());
|
|
33195
33196
|
const listSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).map((entry) => entry.path);
|
|
33196
33197
|
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
33198
|
const cachedPackageJsons = /* @__PURE__ */ new Map();
|
|
33200
33199
|
const clearPackageJsonCache = () => {
|
|
33201
33200
|
cachedPackageJsons.clear();
|
|
33202
33201
|
};
|
|
33203
33202
|
const readPackageJsonUncached = (packageJsonPath) => {
|
|
33204
33203
|
try {
|
|
33205
|
-
return JSON.parse(
|
|
33204
|
+
return JSON.parse(NFS.readFileSync(packageJsonPath, "utf-8"));
|
|
33206
33205
|
} catch (error) {
|
|
33207
33206
|
if (error instanceof SyntaxError) return {};
|
|
33208
33207
|
if (isErrnoException(error)) {
|
|
@@ -36769,6 +36768,7 @@ const PNPM_WORKSPACE_FILE = "pnpm-workspace.yaml";
|
|
|
36769
36768
|
const PNPM_LOCKFILE = "pnpm-lock.yaml";
|
|
36770
36769
|
const PACKAGE_JSON_FILE = "package.json";
|
|
36771
36770
|
const PNPM_HARDENING_RULE_KEY = "require-pnpm-hardening";
|
|
36771
|
+
const UTF8_BOM_CHAR = "";
|
|
36772
36772
|
const HARDENING_SETTING_KEYS = new Set([
|
|
36773
36773
|
"minimumReleaseAge",
|
|
36774
36774
|
"blockExoticSubdeps",
|
|
@@ -36793,11 +36793,12 @@ const stripInlineComment = (rawValue) => {
|
|
|
36793
36793
|
return rawValue;
|
|
36794
36794
|
};
|
|
36795
36795
|
const unquote = (rawValue) => rawValue.replace(/^["']|["']$/g, "");
|
|
36796
|
+
const stripBom = (rawContent) => rawContent.startsWith(UTF8_BOM_CHAR) ? rawContent.slice(1) : rawContent;
|
|
36796
36797
|
const parseHardeningSettings = (content) => {
|
|
36797
36798
|
let minimumReleaseAge = null;
|
|
36798
36799
|
let blockExoticSubdeps = null;
|
|
36799
36800
|
let trustPolicy = null;
|
|
36800
|
-
const lines =
|
|
36801
|
+
const lines = stripBom(content).split(/\r?\n/);
|
|
36801
36802
|
for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
|
|
36802
36803
|
const lineText = lines[lineIndex];
|
|
36803
36804
|
if (lineText === void 0) continue;
|
|
@@ -36831,7 +36832,7 @@ const isPnpmManagedProject = (rootDirectory) => {
|
|
|
36831
36832
|
const packageJsonPath = Path.join(rootDirectory, PACKAGE_JSON_FILE);
|
|
36832
36833
|
if (!isFile(packageJsonPath)) return false;
|
|
36833
36834
|
try {
|
|
36834
|
-
const packageJsonRaw =
|
|
36835
|
+
const packageJsonRaw = NFS.readFileSync(packageJsonPath, "utf-8");
|
|
36835
36836
|
const packageJson = JSON.parse(packageJsonRaw);
|
|
36836
36837
|
if (packageJson !== null && typeof packageJson === "object" && "packageManager" in packageJson && typeof packageJson.packageManager === "string" && packageJson.packageManager.startsWith("pnpm@")) return true;
|
|
36837
36838
|
} catch {
|
|
@@ -37493,7 +37494,9 @@ const highlighter = {
|
|
|
37493
37494
|
gray: import_picocolors.default.gray,
|
|
37494
37495
|
bold: import_picocolors.default.bold
|
|
37495
37496
|
};
|
|
37496
|
-
const
|
|
37497
|
+
const NEXT_ENTRY_FILE_PATTERN = /^(?:\.\/)?(?:src\/)?(?:middleware|proxy)\.(?:tsx?|jsx?|mts|mjs)$/;
|
|
37498
|
+
const shouldIncludeExplicitLintPath = (filePath, project) => JSX_FILE_PATTERN.test(filePath) || project?.framework === "nextjs" && NEXT_ENTRY_FILE_PATTERN.test(filePath);
|
|
37499
|
+
const computeExplicitLintIncludePaths = (includePaths, project) => includePaths.length > 0 ? includePaths.filter((filePath) => shouldIncludeExplicitLintPath(filePath, project)) : void 0;
|
|
37497
37500
|
const LINGUIST_ATTRIBUTE_PATTERN = /^linguist-(?:vendored|generated)(?:=([a-zA-Z0-9]+))?$/i;
|
|
37498
37501
|
const FALSY_VALUES = new Set([
|
|
37499
37502
|
"false",
|
|
@@ -38335,11 +38338,11 @@ const resolveDeadCodeTimeout = (input) => {
|
|
|
38335
38338
|
phaseTimeoutMs: workerTimeoutMs + DEAD_CODE_PHASE_TIMEOUT_OVER_WORKER_MS
|
|
38336
38339
|
};
|
|
38337
38340
|
};
|
|
38338
|
-
const resolveLintIncludePaths = (rootDirectory, userConfig) => {
|
|
38341
|
+
const resolveLintIncludePaths = (rootDirectory, userConfig, project) => {
|
|
38339
38342
|
if (!Array.isArray(userConfig?.ignore?.files) || userConfig.ignore.files.length === 0) return;
|
|
38340
38343
|
const ignoredPatterns = compileIgnoredFilePatterns(userConfig);
|
|
38341
38344
|
return listSourceFiles(rootDirectory).filter((filePath) => {
|
|
38342
|
-
if (!
|
|
38345
|
+
if (!shouldIncludeExplicitLintPath(filePath, project)) return false;
|
|
38343
38346
|
return !isFileIgnoredByPatterns(filePath, rootDirectory, ignoredPatterns);
|
|
38344
38347
|
});
|
|
38345
38348
|
};
|
|
@@ -38557,7 +38560,6 @@ const parseGithubViewerPermission = (stdout) => {
|
|
|
38557
38560
|
return /^[A-Z_]+$/.test(value) ? value.toLowerCase() : null;
|
|
38558
38561
|
};
|
|
38559
38562
|
const splitNullSeparated = (value) => value.split("\0").filter((entry) => entry.length > 0);
|
|
38560
|
-
const UNTRACKED_FILE_LAST_LINE = Number.MAX_SAFE_INTEGER;
|
|
38561
38563
|
/**
|
|
38562
38564
|
* `Git` wraps every `git`-via-subprocess call react-doctor makes
|
|
38563
38565
|
* behind a `Context.Service`. The production layer (`layerNode`)
|
|
@@ -38628,14 +38630,6 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38628
38630
|
args,
|
|
38629
38631
|
directory
|
|
38630
38632
|
});
|
|
38631
|
-
const listUntrackedFilePaths = (directory, includePaths = []) => runGit(directory, [
|
|
38632
|
-
"ls-files",
|
|
38633
|
-
"-z",
|
|
38634
|
-
"--others",
|
|
38635
|
-
"--exclude-standard",
|
|
38636
|
-
...includePaths.length > 0 ? ["--", ...includePaths] : []
|
|
38637
|
-
]).pipe(map$3((result) => result.status === 0 ? splitNullSeparated(result.stdout) : null));
|
|
38638
|
-
const mergeUntracked = (directory, trackedFilePaths, includeUntracked) => includeUntracked ? listUntrackedFilePaths(directory).pipe(map$3((untracked) => untracked === null ? trackedFilePaths : [...new Set([...trackedFilePaths, ...untracked])])) : succeed$2(trackedFilePaths);
|
|
38639
38633
|
const currentBranch = (directory) => runGit(directory, [
|
|
38640
38634
|
"rev-parse",
|
|
38641
38635
|
"--abbrev-ref",
|
|
@@ -38758,7 +38752,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38758
38752
|
githubViewerPermission,
|
|
38759
38753
|
branchExists,
|
|
38760
38754
|
mergeBase,
|
|
38761
|
-
diffSelection: ({ directory, explicitBaseBranch
|
|
38755
|
+
diffSelection: ({ directory, explicitBaseBranch }) => gen(function* () {
|
|
38762
38756
|
if (explicitBaseBranch !== void 0 && explicitBaseBranch.trim().length === 0) return yield* fail$4(new ReactDoctorError({ reason: new GitBaseBranchInvalid({ detail: "Diff base branch cannot be empty." }) }));
|
|
38763
38757
|
if (explicitBaseBranch !== void 0) {
|
|
38764
38758
|
const range = parseGitDiffRange(explicitBaseBranch);
|
|
@@ -38787,7 +38781,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38787
38781
|
"HEAD"
|
|
38788
38782
|
]);
|
|
38789
38783
|
if (uncommitted.status !== 0) return null;
|
|
38790
|
-
const files =
|
|
38784
|
+
const files = splitNullSeparated(uncommitted.stdout);
|
|
38791
38785
|
if (files.length === 0) return null;
|
|
38792
38786
|
return {
|
|
38793
38787
|
currentBranch: resolvedCurrentBranch,
|
|
@@ -38817,7 +38811,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38817
38811
|
currentBranch: resolvedCurrentBranch,
|
|
38818
38812
|
baseBranch,
|
|
38819
38813
|
diffBaseRef: mergeBaseRef,
|
|
38820
|
-
changedFiles:
|
|
38814
|
+
changedFiles: splitNullSeparated(diff.stdout),
|
|
38821
38815
|
isCurrentChanges: false
|
|
38822
38816
|
};
|
|
38823
38817
|
}).pipe(withSpan("Git.diffSelection")),
|
|
@@ -38863,7 +38857,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38863
38857
|
stdout: result.stdout
|
|
38864
38858
|
};
|
|
38865
38859
|
}).pipe(withSpan("Git.grep")),
|
|
38866
|
-
changedLineRanges: ({ directory, baseRef, cached, files
|
|
38860
|
+
changedLineRanges: ({ directory, baseRef, cached, files }) => gen(function* () {
|
|
38867
38861
|
if (files.length === 0) return [];
|
|
38868
38862
|
if (baseRef !== void 0 && !isSafeGitRevision(baseRef)) return null;
|
|
38869
38863
|
const result = yield* runGit(directory, [
|
|
@@ -38877,14 +38871,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
38877
38871
|
...files
|
|
38878
38872
|
]);
|
|
38879
38873
|
if (result.status !== 0) return null;
|
|
38880
|
-
|
|
38881
|
-
if (cached || !includeUntracked) return changedLineRanges;
|
|
38882
|
-
const untrackedFilePaths = yield* listUntrackedFilePaths(directory, files);
|
|
38883
|
-
if (untrackedFilePaths === null) return changedLineRanges;
|
|
38884
|
-
return [...changedLineRanges, ...untrackedFilePaths.map((file) => ({
|
|
38885
|
-
file,
|
|
38886
|
-
ranges: [[1, UNTRACKED_FILE_LAST_LINE]]
|
|
38887
|
-
}))];
|
|
38874
|
+
return parseChangedLineRanges(result.stdout);
|
|
38888
38875
|
}).pipe(catch_$1((error) => error.reason._tag === "GitInvocationFailed" ? succeed$2(null) : fail$4(error)), withSpan("Git.changedLineRanges"))
|
|
38889
38876
|
});
|
|
38890
38877
|
})).pipe(provide$2(layer$2.pipe(provide$2(mergeAll$1(layer$1, layer)))));
|
|
@@ -39636,12 +39623,6 @@ const mapWithConcurrency = async (items, concurrency, task) => {
|
|
|
39636
39623
|
if (errors.length > 0) throw errors[0];
|
|
39637
39624
|
return results;
|
|
39638
39625
|
};
|
|
39639
|
-
const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
39640
|
-
let lineNumber = 1;
|
|
39641
|
-
const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
|
|
39642
|
-
for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === 10) lineNumber++;
|
|
39643
|
-
return lineNumber;
|
|
39644
|
-
};
|
|
39645
39626
|
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";
|
|
39646
39627
|
const ACCESSORS_MIN_VERSION = "3.15.0";
|
|
39647
39628
|
const supportsAccessors = (reanimatedVersion) => {
|
|
@@ -40213,6 +40194,13 @@ const findOutermostEnclosingFunctionRange = (sourceFile, targetLine) => {
|
|
|
40213
40194
|
visit(sourceFile);
|
|
40214
40195
|
return foundRange;
|
|
40215
40196
|
};
|
|
40197
|
+
const NEWLINE_BYTE = 10;
|
|
40198
|
+
const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
40199
|
+
let lineNumber = 1;
|
|
40200
|
+
const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
|
|
40201
|
+
for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === NEWLINE_BYTE) lineNumber++;
|
|
40202
|
+
return lineNumber;
|
|
40203
|
+
};
|
|
40216
40204
|
/**
|
|
40217
40205
|
* Drops `react-doctor/react-compiler-no-manual-memoization` diagnostics
|
|
40218
40206
|
* whose enclosing function also carries a `react-hooks-js` (React
|
|
@@ -40393,11 +40381,11 @@ const buildRelatedLocations = (labels, filePath) => {
|
|
|
40393
40381
|
}
|
|
40394
40382
|
return related;
|
|
40395
40383
|
};
|
|
40396
|
-
const
|
|
40397
|
-
|
|
40398
|
-
const
|
|
40399
|
-
|
|
40400
|
-
|
|
40384
|
+
const isOxlintOutput = (value) => {
|
|
40385
|
+
if (typeof value !== "object" || value === null) return false;
|
|
40386
|
+
const candidate = value;
|
|
40387
|
+
return Array.isArray(candidate.diagnostics);
|
|
40388
|
+
};
|
|
40401
40389
|
/**
|
|
40402
40390
|
* Parses one oxlint subprocess's stdout into a flat `Diagnostic[]`.
|
|
40403
40391
|
* Tolerates the leading-notice-line shape oxlint sometimes prints
|
|
@@ -40416,59 +40404,23 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40416
40404
|
throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
40417
40405
|
}
|
|
40418
40406
|
if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
40419
|
-
const engineFailureDiagnostic = parsed.diagnostics.find(isEngineFailureDiagnostic);
|
|
40420
|
-
if (engineFailureDiagnostic !== void 0) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: JSON.stringify(engineFailureDiagnostic).slice(0, 600) }) });
|
|
40421
40407
|
const minifiedFileCache = /* @__PURE__ */ new Map();
|
|
40422
|
-
const sourceBufferCache = /* @__PURE__ */ new Map();
|
|
40423
|
-
const sourceLinesCache = /* @__PURE__ */ new Map();
|
|
40424
|
-
const resolveAbsolutePath = (filename) => Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
40425
|
-
const readSourceBuffer = (filename) => {
|
|
40426
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
40427
|
-
const cached = sourceBufferCache.get(absolutePath);
|
|
40428
|
-
if (cached !== void 0) return cached;
|
|
40429
|
-
let sourceBuffer;
|
|
40430
|
-
try {
|
|
40431
|
-
sourceBuffer = NFS.readFileSync(absolutePath);
|
|
40432
|
-
} catch {
|
|
40433
|
-
sourceBuffer = null;
|
|
40434
|
-
}
|
|
40435
|
-
sourceBufferCache.set(absolutePath, sourceBuffer);
|
|
40436
|
-
return sourceBuffer;
|
|
40437
|
-
};
|
|
40438
|
-
const readSourceLines = (filename) => {
|
|
40439
|
-
const absolutePath = resolveAbsolutePath(filename);
|
|
40440
|
-
const cached = sourceLinesCache.get(absolutePath);
|
|
40441
|
-
if (cached !== void 0) return cached;
|
|
40442
|
-
const sourceBuffer = readSourceBuffer(filename);
|
|
40443
|
-
const sourceLines = sourceBuffer ? sourceBuffer.toString("utf8").split("\n") : null;
|
|
40444
|
-
sourceLinesCache.set(absolutePath, sourceLines);
|
|
40445
|
-
return sourceLines;
|
|
40446
|
-
};
|
|
40447
40408
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
40448
|
-
const absolutePath =
|
|
40409
|
+
const absolutePath = Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
40449
40410
|
const cached = minifiedFileCache.get(absolutePath);
|
|
40450
40411
|
if (cached !== void 0) return cached;
|
|
40451
40412
|
const minified = isMinifiedSource(absolutePath);
|
|
40452
40413
|
minifiedFileCache.set(absolutePath, minified);
|
|
40453
40414
|
return minified;
|
|
40454
40415
|
};
|
|
40455
|
-
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) =>
|
|
40416
|
+
return suppressMemoizationInBailedOutFunctions(parsed.diagnostics.filter((diagnostic) => diagnostic.code && isLintableSourceFile(diagnostic.filename) && !isMinifiedDiagnosticFile(diagnostic.filename) && !shouldSuppressLocalUseHookDiagnostic(diagnostic, rootDirectory) && !shouldSuppressCompilerFindingInWorklet(diagnostic, project, rootDirectory)).map((diagnostic) => {
|
|
40456
40417
|
const { plugin, rule } = parseRuleCode(diagnostic.code);
|
|
40457
40418
|
const primaryLabel = diagnostic.labels[0];
|
|
40458
40419
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
40459
40420
|
const normalizedFilePath = diagnostic.filename.replaceAll("\\", "/");
|
|
40460
40421
|
const primarySpan = primaryLabel?.span;
|
|
40461
|
-
const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
|
|
40462
40422
|
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
|
|
40463
40423
|
const category = resolveDiagnosticCategory(plugin, rule);
|
|
40464
|
-
const matchByOccurrence = resolveMatchByOccurrence(rule, category);
|
|
40465
|
-
const sourceLines = primarySpan ? readSourceLines(diagnostic.filename) : null;
|
|
40466
|
-
const primaryLineIndex = primarySpan ? primarySpan.line - 1 : -1;
|
|
40467
|
-
const primaryLine = sourceLines?.[primaryLineIndex];
|
|
40468
|
-
const primaryColumnIndex = primarySpan ? primarySpan.column - 1 : -1;
|
|
40469
|
-
const isJsxTagLabel = primaryLine !== void 0 && primaryColumnIndex >= 0 && (primaryLine[primaryColumnIndex] === "<" || primaryLine[primaryColumnIndex - 1] === "<");
|
|
40470
|
-
const jsxOpenerEndLineIndex = sourceLines && isJsxTagLabel ? findJsxOpenerSpan(sourceLines, primaryLineIndex) : null;
|
|
40471
|
-
const primarySpanEndLine = jsxOpenerEndLineIndex !== null ? jsxOpenerEndLineIndex + 1 : primarySpan && sourceBuffer ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset + Math.max(primarySpan.length - 1, 0)) : void 0;
|
|
40472
40424
|
return {
|
|
40473
40425
|
filePath: normalizedFilePath,
|
|
40474
40426
|
plugin,
|
|
@@ -40482,11 +40434,10 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40482
40434
|
column: primarySpan?.column ?? 0,
|
|
40483
40435
|
...primarySpan ? {
|
|
40484
40436
|
offset: primarySpan.offset,
|
|
40485
|
-
length: primarySpan.length
|
|
40486
|
-
...primarySpanEndLine !== void 0 ? { endLine: primarySpanEndLine } : {}
|
|
40437
|
+
length: primarySpan.length
|
|
40487
40438
|
} : {},
|
|
40488
40439
|
category,
|
|
40489
|
-
...
|
|
40440
|
+
...resolveMatchByOccurrence(rule, category) ? { matchByOccurrence: true } : {},
|
|
40490
40441
|
...relatedLocations.length > 0 ? { relatedLocations } : {}
|
|
40491
40442
|
};
|
|
40492
40443
|
}), rootDirectory);
|
|
@@ -42273,7 +42224,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
42273
42224
|
directory: scanDirectory,
|
|
42274
42225
|
repo
|
|
42275
42226
|
}).pipe(orElseSucceed(() => null)) : succeed$2(null));
|
|
42276
|
-
const lintIncludePaths = (input.
|
|
42227
|
+
const lintIncludePaths = (input.skipJsxIncludeFilter ? input.includePaths.length > 0 ? [...input.includePaths] : void 0 : computeExplicitLintIncludePaths([...input.includePaths], project)) ?? resolveLintIncludePaths(scanDirectory, resolvedConfig.config, project);
|
|
42277
42228
|
const fallbackScannedFilePaths = input.suppressScanSummary ? (lintIncludePaths ?? (yield* filesService.listSourceFiles(scanDirectory))).map((relativePath) => Path.resolve(scanDirectory, relativePath)) : [];
|
|
42278
42229
|
const beforeLint = hooks.beforeLint ?? NO_HOOKS.beforeLint;
|
|
42279
42230
|
const afterLint = hooks.afterLint ?? NO_HOOKS.afterLint;
|
|
@@ -42768,7 +42719,7 @@ const runEditorScan = async (input) => {
|
|
|
42768
42719
|
warnings,
|
|
42769
42720
|
isCi: false,
|
|
42770
42721
|
resolveLocalGithubViewerPermission: false,
|
|
42771
|
-
|
|
42722
|
+
skipJsxIncludeFilter: true
|
|
42772
42723
|
}).pipe(withSpan("runEditorScan", { attributes: {
|
|
42773
42724
|
"editor.lint": lint,
|
|
42774
42725
|
"editor.runDeadCode": runDeadCode
|
|
@@ -43531,7 +43482,7 @@ const createLintCache = (input) => {
|
|
|
43531
43482
|
let persistTimer = null;
|
|
43532
43483
|
try {
|
|
43533
43484
|
const parsed = JSON.parse(fs.readFileSync(cacheFilePath, "utf8"));
|
|
43534
|
-
if (parsed.version ===
|
|
43485
|
+
if (parsed.version === 1 && parsed.fingerprint === input.fingerprint) for (const [fsPath, entry] of Object.entries(parsed.entries)) entries.set(fsPath, entry);
|
|
43535
43486
|
} catch {}
|
|
43536
43487
|
const persist = () => {
|
|
43537
43488
|
if (persistTimer) {
|
|
@@ -43542,7 +43493,7 @@ const createLintCache = (input) => {
|
|
|
43542
43493
|
dirty = false;
|
|
43543
43494
|
try {
|
|
43544
43495
|
const payload = {
|
|
43545
|
-
version:
|
|
43496
|
+
version: 1,
|
|
43546
43497
|
fingerprint: input.fingerprint,
|
|
43547
43498
|
entries: Object.fromEntries(entries)
|
|
43548
43499
|
};
|
|
@@ -43555,14 +43506,14 @@ const createLintCache = (input) => {
|
|
|
43555
43506
|
}
|
|
43556
43507
|
};
|
|
43557
43508
|
return {
|
|
43558
|
-
lookup: (fsPath,
|
|
43509
|
+
lookup: (fsPath, stat) => {
|
|
43559
43510
|
const entry = entries.get(fsPath);
|
|
43560
|
-
if (entry !== void 0 && entry.
|
|
43511
|
+
if (entry !== void 0 && entry.mtimeMs === stat.mtimeMs && entry.size === stat.size) return entry.diagnostics;
|
|
43561
43512
|
return null;
|
|
43562
43513
|
},
|
|
43563
|
-
store: (fsPath,
|
|
43514
|
+
store: (fsPath, stat, diagnostics) => {
|
|
43564
43515
|
entries.set(fsPath, {
|
|
43565
|
-
...
|
|
43516
|
+
...stat,
|
|
43566
43517
|
diagnostics
|
|
43567
43518
|
});
|
|
43568
43519
|
dirty = true;
|
|
@@ -43651,9 +43602,16 @@ const resolveDiagnosticFsPath = (rawFilePath, scanDirectory, projectDirectory, o
|
|
|
43651
43602
|
}
|
|
43652
43603
|
return normalizeFsPath(absolute);
|
|
43653
43604
|
};
|
|
43654
|
-
const
|
|
43655
|
-
|
|
43656
|
-
|
|
43605
|
+
const statSafe = (fsPath) => {
|
|
43606
|
+
try {
|
|
43607
|
+
const stat = fs.statSync(fsPath);
|
|
43608
|
+
return {
|
|
43609
|
+
mtimeMs: stat.mtimeMs,
|
|
43610
|
+
size: stat.size
|
|
43611
|
+
};
|
|
43612
|
+
} catch {
|
|
43613
|
+
return null;
|
|
43614
|
+
}
|
|
43657
43615
|
};
|
|
43658
43616
|
/**
|
|
43659
43617
|
* Outcome for a per-file request served without running oxlint (every
|
|
@@ -43679,7 +43637,7 @@ const outcomeWithoutScan = (request, byFile, requestedPaths) => ({
|
|
|
43679
43637
|
* overlay tree (unsaved buffers) or disk, groups diagnostics by canonical
|
|
43680
43638
|
* absolute path, and reports stale-detection metadata.
|
|
43681
43639
|
*
|
|
43682
|
-
* A persistent per-file lint cache (keyed by
|
|
43640
|
+
* A persistent per-file lint cache (keyed by mtime + size, namespaced by a
|
|
43683
43641
|
* config fingerprint) short-circuits unchanged files so a re-opened editor
|
|
43684
43642
|
* or repeated workspace scan skips the oxlint subprocess for everything it
|
|
43685
43643
|
* hasn't edited. The cache applies only to disk-based, lint-only, per-file
|
|
@@ -43709,15 +43667,15 @@ const createScanRunner = (options) => {
|
|
|
43709
43667
|
const requestedPaths = request.priority === "background" && !request.useOverlay && options.isOpen ? allRequested.filter((fsPath) => !options.isOpen?.(fsPath)) : allRequested;
|
|
43710
43668
|
const cache = cacheEnabled && !isWholeProject && !request.useOverlay && !request.runDeadCode ? getCache(projectDirectory) : null;
|
|
43711
43669
|
const byFile = /* @__PURE__ */ new Map();
|
|
43712
|
-
const
|
|
43670
|
+
const statByPath = /* @__PURE__ */ new Map();
|
|
43713
43671
|
let filesToScan = requestedPaths;
|
|
43714
43672
|
if (cache) {
|
|
43715
43673
|
const uncached = [];
|
|
43716
43674
|
for (const fsPath of requestedPaths) {
|
|
43717
|
-
const
|
|
43718
|
-
if (
|
|
43719
|
-
|
|
43720
|
-
const hit = cache.lookup(fsPath,
|
|
43675
|
+
const stat = statSafe(fsPath);
|
|
43676
|
+
if (stat) {
|
|
43677
|
+
statByPath.set(fsPath, stat);
|
|
43678
|
+
const hit = cache.lookup(fsPath, stat);
|
|
43721
43679
|
if (hit !== null) {
|
|
43722
43680
|
if (hit.length > 0) byFile.set(fsPath, hit);
|
|
43723
43681
|
continue;
|
|
@@ -43760,9 +43718,9 @@ const createScanRunner = (options) => {
|
|
|
43760
43718
|
}
|
|
43761
43719
|
if (cache && result.ok && !result.skipped && !result.didLintFail && result.lintPartialFailures.length === 0) {
|
|
43762
43720
|
for (const fsPath of filesToScan) {
|
|
43763
|
-
const
|
|
43764
|
-
if (!
|
|
43765
|
-
cache.store(fsPath,
|
|
43721
|
+
const stat = statByPath.get(fsPath);
|
|
43722
|
+
if (!stat) continue;
|
|
43723
|
+
cache.store(fsPath, stat, byFile.get(fsPath) ?? []);
|
|
43766
43724
|
}
|
|
43767
43725
|
cache.schedulePersist();
|
|
43768
43726
|
}
|
|
@@ -44542,7 +44500,6 @@ const METRIC = {
|
|
|
44542
44500
|
cliInvoked: "cli.invoked",
|
|
44543
44501
|
cliError: "cli.error",
|
|
44544
44502
|
cliEnvironmentError: "cli.env_error",
|
|
44545
|
-
stagedSnapshotDivergence: "staged.snapshot_divergence",
|
|
44546
44503
|
projectDetected: "project.detected",
|
|
44547
44504
|
projectPathSelected: "project.path_selected",
|
|
44548
44505
|
projectConfigSelected: "project.config_selected",
|
|
@@ -44897,5 +44854,5 @@ const startLanguageServer = () => {
|
|
|
44897
44854
|
};
|
|
44898
44855
|
//#endregion
|
|
44899
44856
|
export { startLanguageServer };
|
|
44900
|
-
!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]="
|
|
44901
|
-
//# debugId=
|
|
44857
|
+
!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]="b77898db-d8e8-531a-a32b-9de2d1a63635")}catch(e){}}();
|
|
44858
|
+
//# debugId=b77898db-d8e8-531a-a32b-9de2d1a63635
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-doctor",
|
|
3
|
-
"version": "0.7.6-dev.
|
|
3
|
+
"version": "0.7.6-dev.0017418",
|
|
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.6",
|
|
69
|
-
"oxlint-plugin-react-doctor": "0.7.6-dev.
|
|
69
|
+
"oxlint-plugin-react-doctor": "0.7.6-dev.0017418"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/babel__code-frame": "^7.27.0",
|