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/cli.js +88 -273
- package/dist/index.d.ts +1 -1
- package/dist/index.js +64 -135
- package/dist/lsp.js +62 -133
- package/package.json +5 -5
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(
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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:
|
|
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
|
|
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
|
-
|
|
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:
|
|
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 !==
|
|
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 ===
|
|
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:
|
|
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
|
|
40413
|
-
|
|
40414
|
-
const
|
|
40415
|
-
|
|
40416
|
-
|
|
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 =
|
|
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) =>
|
|
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
|
-
...
|
|
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
|
|
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 =
|
|
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]="
|
|
44919
|
-
//# debugId=
|
|
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.
|
|
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
|
-
"
|
|
69
|
-
"
|
|
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/
|
|
79
|
-
"@react-doctor/
|
|
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"
|