react-doctor 0.7.6-dev.e026a23 → 0.7.6-dev.e141d90
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 +65 -24
- package/dist/index.js +51 -17
- package/dist/lsp.js +51 -17
- package/package.json +3 -3
package/dist/cli.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]="
|
|
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]="9a5c1a3c-7706-5a23-bca4-ddddd2f085af")}catch(e){}}();
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import * as NodeChildProcess from "node:child_process";
|
|
5
5
|
import { execFile, execFileSync, spawn, spawnSync } from "node:child_process";
|
|
@@ -36341,10 +36341,12 @@ const listSourceFilesViaFilesystem = (rootDirectory) => {
|
|
|
36341
36341
|
const listSourceFilesWithSize = (rootDirectory) => collectSizedSourceFiles(rootDirectory, (listSourceFilesViaGit(rootDirectory) ?? listSourceFilesViaFilesystem(rootDirectory)).sort());
|
|
36342
36342
|
const listSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).map((entry) => entry.path);
|
|
36343
36343
|
const countSourceFiles = (rootDirectory) => listSourceFilesWithSize(rootDirectory).length;
|
|
36344
|
+
const UTF8_BOM_CHARACTER = "";
|
|
36345
|
+
const stripUtf8Bom = (content) => content.startsWith(UTF8_BOM_CHARACTER) ? content.slice(1) : content;
|
|
36344
36346
|
const cachedPackageJsons = /* @__PURE__ */ new Map();
|
|
36345
36347
|
const readPackageJsonUncached = (packageJsonPath) => {
|
|
36346
36348
|
try {
|
|
36347
|
-
return JSON.parse(NFS.readFileSync(packageJsonPath, "utf-8"));
|
|
36349
|
+
return JSON.parse(stripUtf8Bom(NFS.readFileSync(packageJsonPath, "utf-8")));
|
|
36348
36350
|
} catch (error) {
|
|
36349
36351
|
if (error instanceof SyntaxError) return {};
|
|
36350
36352
|
if (isErrnoException(error)) {
|
|
@@ -40017,7 +40019,6 @@ const PNPM_WORKSPACE_FILE = "pnpm-workspace.yaml";
|
|
|
40017
40019
|
const PNPM_LOCKFILE = "pnpm-lock.yaml";
|
|
40018
40020
|
const PACKAGE_JSON_FILE = "package.json";
|
|
40019
40021
|
const PNPM_HARDENING_RULE_KEY = "require-pnpm-hardening";
|
|
40020
|
-
const UTF8_BOM_CHAR = "";
|
|
40021
40022
|
const HARDENING_SETTING_KEYS = new Set([
|
|
40022
40023
|
"minimumReleaseAge",
|
|
40023
40024
|
"blockExoticSubdeps",
|
|
@@ -40042,12 +40043,11 @@ const stripInlineComment = (rawValue) => {
|
|
|
40042
40043
|
return rawValue;
|
|
40043
40044
|
};
|
|
40044
40045
|
const unquote = (rawValue) => rawValue.replace(/^["']|["']$/g, "");
|
|
40045
|
-
const stripBom = (rawContent) => rawContent.startsWith(UTF8_BOM_CHAR) ? rawContent.slice(1) : rawContent;
|
|
40046
40046
|
const parseHardeningSettings = (content) => {
|
|
40047
40047
|
let minimumReleaseAge = null;
|
|
40048
40048
|
let blockExoticSubdeps = null;
|
|
40049
40049
|
let trustPolicy = null;
|
|
40050
|
-
const lines =
|
|
40050
|
+
const lines = stripUtf8Bom(content).split(/\r?\n/);
|
|
40051
40051
|
for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
|
|
40052
40052
|
const lineText = lines[lineIndex];
|
|
40053
40053
|
if (lineText === void 0) continue;
|
|
@@ -40081,7 +40081,7 @@ const isPnpmManagedProject = (rootDirectory) => {
|
|
|
40081
40081
|
const packageJsonPath = Path.join(rootDirectory, PACKAGE_JSON_FILE);
|
|
40082
40082
|
if (!isFile(packageJsonPath)) return false;
|
|
40083
40083
|
try {
|
|
40084
|
-
const packageJsonRaw = NFS.readFileSync(packageJsonPath, "utf-8");
|
|
40084
|
+
const packageJsonRaw = stripUtf8Bom(NFS.readFileSync(packageJsonPath, "utf-8"));
|
|
40085
40085
|
const packageJson = JSON.parse(packageJsonRaw);
|
|
40086
40086
|
if (packageJson !== null && typeof packageJson === "object" && "packageManager" in packageJson && typeof packageJson.packageManager === "string" && packageJson.packageManager.startsWith("pnpm@")) return true;
|
|
40087
40087
|
} catch {
|
|
@@ -42886,6 +42886,12 @@ const mapWithConcurrency = async (items, concurrency, task) => {
|
|
|
42886
42886
|
if (errors.length > 0) throw errors[0];
|
|
42887
42887
|
return results;
|
|
42888
42888
|
};
|
|
42889
|
+
const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
42890
|
+
let lineNumber = 1;
|
|
42891
|
+
const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
|
|
42892
|
+
for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === 10) lineNumber++;
|
|
42893
|
+
return lineNumber;
|
|
42894
|
+
};
|
|
42889
42895
|
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";
|
|
42890
42896
|
const ACCESSORS_MIN_VERSION = "3.15.0";
|
|
42891
42897
|
const supportsAccessors = (reanimatedVersion) => {
|
|
@@ -43457,13 +43463,6 @@ const findOutermostEnclosingFunctionRange = (sourceFile, targetLine) => {
|
|
|
43457
43463
|
visit(sourceFile);
|
|
43458
43464
|
return foundRange;
|
|
43459
43465
|
};
|
|
43460
|
-
const NEWLINE_BYTE = 10;
|
|
43461
|
-
const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
43462
|
-
let lineNumber = 1;
|
|
43463
|
-
const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
|
|
43464
|
-
for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === NEWLINE_BYTE) lineNumber++;
|
|
43465
|
-
return lineNumber;
|
|
43466
|
-
};
|
|
43467
43466
|
/**
|
|
43468
43467
|
* Drops `react-doctor/react-compiler-no-manual-memoization` diagnostics
|
|
43469
43468
|
* whose enclosing function also carries a `react-hooks-js` (React
|
|
@@ -43668,8 +43667,33 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
43668
43667
|
}
|
|
43669
43668
|
if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
43670
43669
|
const minifiedFileCache = /* @__PURE__ */ new Map();
|
|
43670
|
+
const sourceBufferCache = /* @__PURE__ */ new Map();
|
|
43671
|
+
const sourceLinesCache = /* @__PURE__ */ new Map();
|
|
43672
|
+
const resolveAbsolutePath = (filename) => Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
43673
|
+
const readSourceBuffer = (filename) => {
|
|
43674
|
+
const absolutePath = resolveAbsolutePath(filename);
|
|
43675
|
+
const cached = sourceBufferCache.get(absolutePath);
|
|
43676
|
+
if (cached !== void 0) return cached;
|
|
43677
|
+
let sourceBuffer;
|
|
43678
|
+
try {
|
|
43679
|
+
sourceBuffer = NFS.readFileSync(absolutePath);
|
|
43680
|
+
} catch {
|
|
43681
|
+
sourceBuffer = null;
|
|
43682
|
+
}
|
|
43683
|
+
sourceBufferCache.set(absolutePath, sourceBuffer);
|
|
43684
|
+
return sourceBuffer;
|
|
43685
|
+
};
|
|
43686
|
+
const readSourceLines = (filename) => {
|
|
43687
|
+
const absolutePath = resolveAbsolutePath(filename);
|
|
43688
|
+
const cached = sourceLinesCache.get(absolutePath);
|
|
43689
|
+
if (cached !== void 0) return cached;
|
|
43690
|
+
const sourceBuffer = readSourceBuffer(filename);
|
|
43691
|
+
const sourceLines = sourceBuffer ? sourceBuffer.toString("utf8").split("\n") : null;
|
|
43692
|
+
sourceLinesCache.set(absolutePath, sourceLines);
|
|
43693
|
+
return sourceLines;
|
|
43694
|
+
};
|
|
43671
43695
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
43672
|
-
const absolutePath =
|
|
43696
|
+
const absolutePath = resolveAbsolutePath(filename);
|
|
43673
43697
|
const cached = minifiedFileCache.get(absolutePath);
|
|
43674
43698
|
if (cached !== void 0) return cached;
|
|
43675
43699
|
const minified = isMinifiedSource(absolutePath);
|
|
@@ -43682,8 +43706,17 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
43682
43706
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
43683
43707
|
const normalizedFilePath = diagnostic.filename.replaceAll("\\", "/");
|
|
43684
43708
|
const primarySpan = primaryLabel?.span;
|
|
43709
|
+
const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
|
|
43685
43710
|
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
|
|
43686
43711
|
const category = resolveDiagnosticCategory(plugin, rule);
|
|
43712
|
+
const matchByOccurrence = resolveMatchByOccurrence(rule, category);
|
|
43713
|
+
const sourceLines = primarySpan ? readSourceLines(diagnostic.filename) : null;
|
|
43714
|
+
const primaryLineIndex = primarySpan ? primarySpan.line - 1 : -1;
|
|
43715
|
+
const primaryLine = sourceLines?.[primaryLineIndex];
|
|
43716
|
+
const primaryColumnIndex = primarySpan ? primarySpan.column - 1 : -1;
|
|
43717
|
+
const isJsxTagLabel = primaryLine !== void 0 && primaryColumnIndex >= 0 && (primaryLine[primaryColumnIndex] === "<" || primaryLine[primaryColumnIndex - 1] === "<");
|
|
43718
|
+
const jsxOpenerEndLineIndex = sourceLines && isJsxTagLabel ? findJsxOpenerSpan(sourceLines, primaryLineIndex) : null;
|
|
43719
|
+
const primarySpanEndLine = jsxOpenerEndLineIndex !== null ? jsxOpenerEndLineIndex + 1 : primarySpan && sourceBuffer ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset + Math.max(primarySpan.length - 1, 0)) : void 0;
|
|
43687
43720
|
return {
|
|
43688
43721
|
filePath: normalizedFilePath,
|
|
43689
43722
|
plugin,
|
|
@@ -43697,10 +43730,11 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
43697
43730
|
column: primarySpan?.column ?? 0,
|
|
43698
43731
|
...primarySpan ? {
|
|
43699
43732
|
offset: primarySpan.offset,
|
|
43700
|
-
length: primarySpan.length
|
|
43733
|
+
length: primarySpan.length,
|
|
43734
|
+
...primarySpanEndLine !== void 0 ? { endLine: primarySpanEndLine } : {}
|
|
43701
43735
|
} : {},
|
|
43702
43736
|
category,
|
|
43703
|
-
...
|
|
43737
|
+
...matchByOccurrence ? { matchByOccurrence: true } : {},
|
|
43704
43738
|
...relatedLocations.length > 0 ? { relatedLocations } : {}
|
|
43705
43739
|
};
|
|
43706
43740
|
}), rootDirectory);
|
|
@@ -46665,7 +46699,7 @@ const makeNoopConsole = () => ({
|
|
|
46665
46699
|
});
|
|
46666
46700
|
//#endregion
|
|
46667
46701
|
//#region src/cli/utils/version.ts
|
|
46668
|
-
const VERSION = "0.7.6-dev.
|
|
46702
|
+
const VERSION = "0.7.6-dev.e141d90";
|
|
46669
46703
|
//#endregion
|
|
46670
46704
|
//#region src/cli/utils/json-mode.ts
|
|
46671
46705
|
let context = null;
|
|
@@ -47034,13 +47068,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
|
|
|
47034
47068
|
* uploads source-map artifacts under, so stack frames symbolicate. Honors the
|
|
47035
47069
|
* standard `SENTRY_RELEASE` override.
|
|
47036
47070
|
*/
|
|
47037
|
-
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.7.6-dev.
|
|
47071
|
+
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.7.6-dev.e141d90`;
|
|
47038
47072
|
/**
|
|
47039
47073
|
* Deployment environment shown in Sentry's environment filter. Defaults to
|
|
47040
47074
|
* `production` for tagged releases and `development` for dev/unbuilt versions,
|
|
47041
47075
|
* overridable via the standard `SENTRY_ENVIRONMENT` env var.
|
|
47042
47076
|
*/
|
|
47043
|
-
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.6-dev.
|
|
47077
|
+
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.6-dev.e141d90") ? "development" : "production");
|
|
47044
47078
|
/**
|
|
47045
47079
|
* Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
|
|
47046
47080
|
* (set to `0` to disable tracing) and falls back to
|
|
@@ -50805,7 +50839,7 @@ const BLOCKING_SUMMARY = {
|
|
|
50805
50839
|
const SCOPE_SUMMARY = {
|
|
50806
50840
|
full: "Scan the whole project on every run",
|
|
50807
50841
|
files: "Report every issue in changed files",
|
|
50808
|
-
lines: "Report issues
|
|
50842
|
+
lines: "Report issues whose source spans touch changed lines",
|
|
50809
50843
|
changed: "Report only the issues a change introduces"
|
|
50810
50844
|
};
|
|
50811
50845
|
const gatesEqual = (left, right) => left.blocking === right.blocking && left.scope === right.scope && left.comment === right.comment && left.reviewComments === right.reviewComments && left.commitStatus === right.commitStatus;
|
|
@@ -59675,7 +59709,8 @@ const buildScanAttributes = (input) => {
|
|
|
59675
59709
|
rulesConfigured: ruleKeys.length,
|
|
59676
59710
|
rulesDisabled: ruleKeys.filter((key) => ruleOverrides[key] === "off").length,
|
|
59677
59711
|
fileCount: input.result?.scannedFileCount ?? null,
|
|
59678
|
-
nonJsxFileCount: input.result?.analyzedFiles?.filter((filePath) => !JSX_FILE_PATTERN.test(filePath)).length ?? null
|
|
59712
|
+
nonJsxFileCount: input.result?.analyzedFiles?.filter((filePath) => !JSX_FILE_PATTERN.test(filePath)).length ?? null,
|
|
59713
|
+
multilineDiagnosticCount: input.result?.diagnostics.filter((diagnostic) => (diagnostic.endLine ?? diagnostic.line) > diagnostic.line).length ?? null
|
|
59679
59714
|
});
|
|
59680
59715
|
};
|
|
59681
59716
|
/**
|
|
@@ -59744,6 +59779,12 @@ const countDeadlineSkippedFiles = (lintPartialFailures) => sumFileCountsMatching
|
|
|
59744
59779
|
const DROPPED_FILES_MESSAGE_PATTERN = /^(\d+) file\(s\) failed to lint and were skipped/;
|
|
59745
59780
|
const countDroppedLintFiles = (lintPartialFailures) => sumFileCountsMatching(lintPartialFailures, DROPPED_FILES_MESSAGE_PATTERN);
|
|
59746
59781
|
//#endregion
|
|
59782
|
+
//#region src/cli/utils/diagnostic-intersects-line-ranges.ts
|
|
59783
|
+
const diagnosticIntersectsLineRanges = (diagnostic, lineRanges) => {
|
|
59784
|
+
const diagnosticEndLine = Math.max(diagnostic.line, diagnostic.endLine ?? diagnostic.line);
|
|
59785
|
+
return lineRanges.some(([rangeStartLine, rangeEndLine]) => diagnostic.line <= rangeEndLine && diagnosticEndLine >= rangeStartLine);
|
|
59786
|
+
};
|
|
59787
|
+
//#endregion
|
|
59747
59788
|
//#region src/cli/utils/materialize-baseline-files.ts
|
|
59748
59789
|
/**
|
|
59749
59790
|
* Materializes the `ref` version of `files` into `tempDirectory` (via
|
|
@@ -60929,7 +60970,7 @@ const buildChangedLineMatcher = (directory, changedLineRanges) => {
|
|
|
60929
60970
|
const relativePath = toForwardSlashes(path.isAbsolute(diagnostic.filePath) ? path.relative(directory, diagnostic.filePath) : diagnostic.filePath);
|
|
60930
60971
|
const ranges = rangesByFile.get(relativePath);
|
|
60931
60972
|
if (ranges === void 0) return false;
|
|
60932
|
-
return
|
|
60973
|
+
return diagnosticIntersectsLineRanges(diagnostic, ranges);
|
|
60933
60974
|
};
|
|
60934
60975
|
};
|
|
60935
60976
|
const buildIgnoredTags = (userConfig) => {
|
|
@@ -65180,7 +65221,7 @@ ${highlighter.dim("Learn more:")}
|
|
|
65180
65221
|
${highlighter.info(CI_URL)}
|
|
65181
65222
|
`;
|
|
65182
65223
|
const collectCategoryOption = (value, previousValues) => [...previousValues ?? [], value];
|
|
65183
|
-
const program = new Command().name("react-doctor").description("Diagnose React codebase health").version(VERSION, "-v, --version", "display the version number").argument("[directory]", "project directory to scan", ".").option("--lint", "enable linting").option("--no-lint", "skip linting").option("--dead-code", "enable dead-code analysis (default)").option("--no-dead-code", "skip dead-code analysis (unused files / exports / dependencies, circular imports)").option("--supply-chain", "enable the dependency supply-chain scan (default)").option("--no-supply-chain", "skip the dependency supply-chain scan (Socket.dev dependency health checks)").option("--verbose", "show every rule and per-file details (default shows top 3 rules)").option("--debug", "force a Sentry trace and print its id at the end (paste it into a bug report)").option("--output-dir <dir>", "directory for the full diagnostics dump (default: a temp folder)").option("--score", "output only the score").option("--json", "output a single structured JSON report (suppresses other output)").option("--json-compact", "with --json, emit compact JSON (no indentation)").option("--json-out <path>", "with --json, write the report to a file instead of stdout").option("-y, --yes", "skip prompts, scan all workspace projects").option("--no-parallel", "lint serially with one worker (default: parallel across CPU cores; set the worker count with REACT_DOCTOR_PARALLEL)").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple); overrides the `projects` config field").option("--scope <value>", "how much supported JS/TS source to scan/report: full (default), files, changed (only new issues vs base), or lines (
|
|
65224
|
+
const program = new Command().name("react-doctor").description("Diagnose React codebase health").version(VERSION, "-v, --version", "display the version number").argument("[directory]", "project directory to scan", ".").option("--lint", "enable linting").option("--no-lint", "skip linting").option("--dead-code", "enable dead-code analysis (default)").option("--no-dead-code", "skip dead-code analysis (unused files / exports / dependencies, circular imports)").option("--supply-chain", "enable the dependency supply-chain scan (default)").option("--no-supply-chain", "skip the dependency supply-chain scan (Socket.dev dependency health checks)").option("--verbose", "show every rule and per-file details (default shows top 3 rules)").option("--debug", "force a Sentry trace and print its id at the end (paste it into a bug report)").option("--output-dir <dir>", "directory for the full diagnostics dump (default: a temp folder)").option("--score", "output only the score").option("--json", "output a single structured JSON report (suppresses other output)").option("--json-compact", "with --json, emit compact JSON (no indentation)").option("--json-out <path>", "with --json, write the report to a file instead of stdout").option("-y, --yes", "skip prompts, scan all workspace projects").option("--no-parallel", "lint serially with one worker (default: parallel across CPU cores; set the worker count with REACT_DOCTOR_PARALLEL)").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple); overrides the `projects` config field").option("--scope <value>", "how much supported JS/TS source to scan/report: full (default), files, changed (only new issues vs base), or lines (issues whose source spans touch changed lines)").option("--base <ref>", "base git ref for files/changed/lines scope (auto-detected when omitted)").addOption(new Option("--diff [base]", "[deprecated] alias for --scope changed (pass `false` to force a full scan)").hideHelp()).addOption(new Option("--changed-files-from <file>", "scan source files listed in a newline-delimited changed-files file").hideHelp()).option("--no-score", "skip the score API, the share URL, and crash reporting").addOption(new Option("--category <category>", "only show diagnostics in a category (repeatable; e.g. Security)").argParser(collectCategoryOption)).option("--no-telemetry", "alias for --no-score (skip the score API, share URL, and crash reporting)").option("--staged", "scan only staged (git index) files for pre-commit hooks").option("--max-duration <seconds>", "scan time budget for the whole run, shared across workspace projects: past it, remaining lint batches and dead-code are skipped and partial results are reported (skipped files are listed in the JSON report)").option("--blocking <level>", "severity that fails CI: error (default), warning, or none (advisory)").addOption(new Option("--fail-on <level>", "[deprecated] alias for --blocking <level>").hideHelp()).option("--no-respect-inline-disables", "audit mode: neutralize inline lint suppressions before scanning").option("--warnings", "show warning-severity diagnostics (default)").option("--no-warnings", "hide warning-severity diagnostics (errors only)").option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").addHelpText("after", renderRootHelpEpilog);
|
|
65184
65225
|
program.action(inspectAction);
|
|
65185
65226
|
program.command("why <location>").description("Explain why a rule fired (or why a suppression didn't apply) at a file:line").option("--project <name>", "select projects: workspace names or directory paths (comma-separated for multiple)").option("-c, --cwd <cwd>", "working directory", process.cwd()).option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").action((location, options) => whyAction(location, options));
|
|
65186
65227
|
program.command("install").alias("setup").description("Install the react-doctor skill into your coding agents and optional git hook").option("-y, --yes", "skip prompts, install for all detected agents").option("--dry-run", "show what would be installed without writing files").option("--agent-hooks", "install native non-blocking agent hooks for Claude Code and Cursor").option("-c, --cwd <cwd>", "working directory", process.cwd()).option("--color", "force colored output").option("--no-color", "disable colored output (also honors NO_COLOR)").addHelpText("after", renderInstallHelpEpilog).action(installAction);
|
|
@@ -65230,4 +65271,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
|
|
|
65230
65271
|
export {};
|
|
65231
65272
|
|
|
65232
65273
|
//# sourceMappingURL=cli.js.map
|
|
65233
|
-
//# debugId=
|
|
65274
|
+
//# debugId=9a5c1a3c-7706-5a23-bca4-ddddd2f085af
|
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]="
|
|
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]="11364a34-6c8b-5bd3-b9e8-aaa7c0ea264c")}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,13 +33142,15 @@ 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;
|
|
33145
33147
|
const cachedPackageJsons = /* @__PURE__ */ new Map();
|
|
33146
33148
|
const clearPackageJsonCache = () => {
|
|
33147
33149
|
cachedPackageJsons.clear();
|
|
33148
33150
|
};
|
|
33149
33151
|
const readPackageJsonUncached = (packageJsonPath) => {
|
|
33150
33152
|
try {
|
|
33151
|
-
return JSON.parse(NFS.readFileSync(packageJsonPath, "utf-8"));
|
|
33153
|
+
return JSON.parse(stripUtf8Bom(NFS.readFileSync(packageJsonPath, "utf-8")));
|
|
33152
33154
|
} catch (error) {
|
|
33153
33155
|
if (error instanceof SyntaxError) return {};
|
|
33154
33156
|
if (isErrnoException(error)) {
|
|
@@ -36789,7 +36791,6 @@ const PNPM_WORKSPACE_FILE = "pnpm-workspace.yaml";
|
|
|
36789
36791
|
const PNPM_LOCKFILE = "pnpm-lock.yaml";
|
|
36790
36792
|
const PACKAGE_JSON_FILE = "package.json";
|
|
36791
36793
|
const PNPM_HARDENING_RULE_KEY = "require-pnpm-hardening";
|
|
36792
|
-
const UTF8_BOM_CHAR = "";
|
|
36793
36794
|
const HARDENING_SETTING_KEYS = new Set([
|
|
36794
36795
|
"minimumReleaseAge",
|
|
36795
36796
|
"blockExoticSubdeps",
|
|
@@ -36814,12 +36815,11 @@ const stripInlineComment = (rawValue) => {
|
|
|
36814
36815
|
return rawValue;
|
|
36815
36816
|
};
|
|
36816
36817
|
const unquote = (rawValue) => rawValue.replace(/^["']|["']$/g, "");
|
|
36817
|
-
const stripBom = (rawContent) => rawContent.startsWith(UTF8_BOM_CHAR) ? rawContent.slice(1) : rawContent;
|
|
36818
36818
|
const parseHardeningSettings = (content) => {
|
|
36819
36819
|
let minimumReleaseAge = null;
|
|
36820
36820
|
let blockExoticSubdeps = null;
|
|
36821
36821
|
let trustPolicy = null;
|
|
36822
|
-
const lines =
|
|
36822
|
+
const lines = stripUtf8Bom(content).split(/\r?\n/);
|
|
36823
36823
|
for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
|
|
36824
36824
|
const lineText = lines[lineIndex];
|
|
36825
36825
|
if (lineText === void 0) continue;
|
|
@@ -36853,7 +36853,7 @@ const isPnpmManagedProject = (rootDirectory) => {
|
|
|
36853
36853
|
const packageJsonPath = Path.join(rootDirectory, PACKAGE_JSON_FILE);
|
|
36854
36854
|
if (!isFile(packageJsonPath)) return false;
|
|
36855
36855
|
try {
|
|
36856
|
-
const packageJsonRaw = NFS.readFileSync(packageJsonPath, "utf-8");
|
|
36856
|
+
const packageJsonRaw = stripUtf8Bom(NFS.readFileSync(packageJsonPath, "utf-8"));
|
|
36857
36857
|
const packageJson = JSON.parse(packageJsonRaw);
|
|
36858
36858
|
if (packageJson !== null && typeof packageJson === "object" && "packageManager" in packageJson && typeof packageJson.packageManager === "string" && packageJson.packageManager.startsWith("pnpm@")) return true;
|
|
36859
36859
|
} catch {
|
|
@@ -39642,6 +39642,12 @@ const mapWithConcurrency = async (items, concurrency, task) => {
|
|
|
39642
39642
|
if (errors.length > 0) throw errors[0];
|
|
39643
39643
|
return results;
|
|
39644
39644
|
};
|
|
39645
|
+
const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
39646
|
+
let lineNumber = 1;
|
|
39647
|
+
const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
|
|
39648
|
+
for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === 10) lineNumber++;
|
|
39649
|
+
return lineNumber;
|
|
39650
|
+
};
|
|
39645
39651
|
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
39652
|
const ACCESSORS_MIN_VERSION = "3.15.0";
|
|
39647
39653
|
const supportsAccessors = (reanimatedVersion) => {
|
|
@@ -40213,13 +40219,6 @@ const findOutermostEnclosingFunctionRange = (sourceFile, targetLine) => {
|
|
|
40213
40219
|
visit(sourceFile);
|
|
40214
40220
|
return foundRange;
|
|
40215
40221
|
};
|
|
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
|
-
};
|
|
40223
40222
|
/**
|
|
40224
40223
|
* Drops `react-doctor/react-compiler-no-manual-memoization` diagnostics
|
|
40225
40224
|
* whose enclosing function also carries a `react-hooks-js` (React
|
|
@@ -40424,8 +40423,33 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40424
40423
|
}
|
|
40425
40424
|
if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
40426
40425
|
const minifiedFileCache = /* @__PURE__ */ new Map();
|
|
40426
|
+
const sourceBufferCache = /* @__PURE__ */ new Map();
|
|
40427
|
+
const sourceLinesCache = /* @__PURE__ */ new Map();
|
|
40428
|
+
const resolveAbsolutePath = (filename) => Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
40429
|
+
const readSourceBuffer = (filename) => {
|
|
40430
|
+
const absolutePath = resolveAbsolutePath(filename);
|
|
40431
|
+
const cached = sourceBufferCache.get(absolutePath);
|
|
40432
|
+
if (cached !== void 0) return cached;
|
|
40433
|
+
let sourceBuffer;
|
|
40434
|
+
try {
|
|
40435
|
+
sourceBuffer = NFS.readFileSync(absolutePath);
|
|
40436
|
+
} catch {
|
|
40437
|
+
sourceBuffer = null;
|
|
40438
|
+
}
|
|
40439
|
+
sourceBufferCache.set(absolutePath, sourceBuffer);
|
|
40440
|
+
return sourceBuffer;
|
|
40441
|
+
};
|
|
40442
|
+
const readSourceLines = (filename) => {
|
|
40443
|
+
const absolutePath = resolveAbsolutePath(filename);
|
|
40444
|
+
const cached = sourceLinesCache.get(absolutePath);
|
|
40445
|
+
if (cached !== void 0) return cached;
|
|
40446
|
+
const sourceBuffer = readSourceBuffer(filename);
|
|
40447
|
+
const sourceLines = sourceBuffer ? sourceBuffer.toString("utf8").split("\n") : null;
|
|
40448
|
+
sourceLinesCache.set(absolutePath, sourceLines);
|
|
40449
|
+
return sourceLines;
|
|
40450
|
+
};
|
|
40427
40451
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
40428
|
-
const absolutePath =
|
|
40452
|
+
const absolutePath = resolveAbsolutePath(filename);
|
|
40429
40453
|
const cached = minifiedFileCache.get(absolutePath);
|
|
40430
40454
|
if (cached !== void 0) return cached;
|
|
40431
40455
|
const minified = isMinifiedSource(absolutePath);
|
|
@@ -40438,8 +40462,17 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40438
40462
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
40439
40463
|
const normalizedFilePath = diagnostic.filename.replaceAll("\\", "/");
|
|
40440
40464
|
const primarySpan = primaryLabel?.span;
|
|
40465
|
+
const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
|
|
40441
40466
|
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
|
|
40442
40467
|
const category = resolveDiagnosticCategory(plugin, rule);
|
|
40468
|
+
const matchByOccurrence = resolveMatchByOccurrence(rule, category);
|
|
40469
|
+
const sourceLines = primarySpan ? readSourceLines(diagnostic.filename) : null;
|
|
40470
|
+
const primaryLineIndex = primarySpan ? primarySpan.line - 1 : -1;
|
|
40471
|
+
const primaryLine = sourceLines?.[primaryLineIndex];
|
|
40472
|
+
const primaryColumnIndex = primarySpan ? primarySpan.column - 1 : -1;
|
|
40473
|
+
const isJsxTagLabel = primaryLine !== void 0 && primaryColumnIndex >= 0 && (primaryLine[primaryColumnIndex] === "<" || primaryLine[primaryColumnIndex - 1] === "<");
|
|
40474
|
+
const jsxOpenerEndLineIndex = sourceLines && isJsxTagLabel ? findJsxOpenerSpan(sourceLines, primaryLineIndex) : null;
|
|
40475
|
+
const primarySpanEndLine = jsxOpenerEndLineIndex !== null ? jsxOpenerEndLineIndex + 1 : primarySpan && sourceBuffer ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset + Math.max(primarySpan.length - 1, 0)) : void 0;
|
|
40443
40476
|
return {
|
|
40444
40477
|
filePath: normalizedFilePath,
|
|
40445
40478
|
plugin,
|
|
@@ -40453,10 +40486,11 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40453
40486
|
column: primarySpan?.column ?? 0,
|
|
40454
40487
|
...primarySpan ? {
|
|
40455
40488
|
offset: primarySpan.offset,
|
|
40456
|
-
length: primarySpan.length
|
|
40489
|
+
length: primarySpan.length,
|
|
40490
|
+
...primarySpanEndLine !== void 0 ? { endLine: primarySpanEndLine } : {}
|
|
40457
40491
|
} : {},
|
|
40458
40492
|
category,
|
|
40459
|
-
...
|
|
40493
|
+
...matchByOccurrence ? { matchByOccurrence: true } : {},
|
|
40460
40494
|
...relatedLocations.length > 0 ? { relatedLocations } : {}
|
|
40461
40495
|
};
|
|
40462
40496
|
}), rootDirectory);
|
|
@@ -43207,4 +43241,4 @@ const toJsonReport = (result, options) => buildJsonReport({
|
|
|
43207
43241
|
export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
|
|
43208
43242
|
|
|
43209
43243
|
//# sourceMappingURL=index.js.map
|
|
43210
|
-
//# debugId=
|
|
43244
|
+
//# debugId=11364a34-6c8b-5bd3-b9e8-aaa7c0ea264c
|
package/dist/lsp.js
CHANGED
|
@@ -33194,13 +33194,15 @@ 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;
|
|
33197
33199
|
const cachedPackageJsons = /* @__PURE__ */ new Map();
|
|
33198
33200
|
const clearPackageJsonCache = () => {
|
|
33199
33201
|
cachedPackageJsons.clear();
|
|
33200
33202
|
};
|
|
33201
33203
|
const readPackageJsonUncached = (packageJsonPath) => {
|
|
33202
33204
|
try {
|
|
33203
|
-
return JSON.parse(NFS.readFileSync(packageJsonPath, "utf-8"));
|
|
33205
|
+
return JSON.parse(stripUtf8Bom(NFS.readFileSync(packageJsonPath, "utf-8")));
|
|
33204
33206
|
} catch (error) {
|
|
33205
33207
|
if (error instanceof SyntaxError) return {};
|
|
33206
33208
|
if (isErrnoException(error)) {
|
|
@@ -36767,7 +36769,6 @@ const PNPM_WORKSPACE_FILE = "pnpm-workspace.yaml";
|
|
|
36767
36769
|
const PNPM_LOCKFILE = "pnpm-lock.yaml";
|
|
36768
36770
|
const PACKAGE_JSON_FILE = "package.json";
|
|
36769
36771
|
const PNPM_HARDENING_RULE_KEY = "require-pnpm-hardening";
|
|
36770
|
-
const UTF8_BOM_CHAR = "";
|
|
36771
36772
|
const HARDENING_SETTING_KEYS = new Set([
|
|
36772
36773
|
"minimumReleaseAge",
|
|
36773
36774
|
"blockExoticSubdeps",
|
|
@@ -36792,12 +36793,11 @@ const stripInlineComment = (rawValue) => {
|
|
|
36792
36793
|
return rawValue;
|
|
36793
36794
|
};
|
|
36794
36795
|
const unquote = (rawValue) => rawValue.replace(/^["']|["']$/g, "");
|
|
36795
|
-
const stripBom = (rawContent) => rawContent.startsWith(UTF8_BOM_CHAR) ? rawContent.slice(1) : rawContent;
|
|
36796
36796
|
const parseHardeningSettings = (content) => {
|
|
36797
36797
|
let minimumReleaseAge = null;
|
|
36798
36798
|
let blockExoticSubdeps = null;
|
|
36799
36799
|
let trustPolicy = null;
|
|
36800
|
-
const lines =
|
|
36800
|
+
const lines = stripUtf8Bom(content).split(/\r?\n/);
|
|
36801
36801
|
for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
|
|
36802
36802
|
const lineText = lines[lineIndex];
|
|
36803
36803
|
if (lineText === void 0) continue;
|
|
@@ -36831,7 +36831,7 @@ const isPnpmManagedProject = (rootDirectory) => {
|
|
|
36831
36831
|
const packageJsonPath = Path.join(rootDirectory, PACKAGE_JSON_FILE);
|
|
36832
36832
|
if (!isFile(packageJsonPath)) return false;
|
|
36833
36833
|
try {
|
|
36834
|
-
const packageJsonRaw = NFS.readFileSync(packageJsonPath, "utf-8");
|
|
36834
|
+
const packageJsonRaw = stripUtf8Bom(NFS.readFileSync(packageJsonPath, "utf-8"));
|
|
36835
36835
|
const packageJson = JSON.parse(packageJsonRaw);
|
|
36836
36836
|
if (packageJson !== null && typeof packageJson === "object" && "packageManager" in packageJson && typeof packageJson.packageManager === "string" && packageJson.packageManager.startsWith("pnpm@")) return true;
|
|
36837
36837
|
} catch {
|
|
@@ -39620,6 +39620,12 @@ const mapWithConcurrency = async (items, concurrency, task) => {
|
|
|
39620
39620
|
if (errors.length > 0) throw errors[0];
|
|
39621
39621
|
return results;
|
|
39622
39622
|
};
|
|
39623
|
+
const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
39624
|
+
let lineNumber = 1;
|
|
39625
|
+
const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
|
|
39626
|
+
for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === 10) lineNumber++;
|
|
39627
|
+
return lineNumber;
|
|
39628
|
+
};
|
|
39623
39629
|
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";
|
|
39624
39630
|
const ACCESSORS_MIN_VERSION = "3.15.0";
|
|
39625
39631
|
const supportsAccessors = (reanimatedVersion) => {
|
|
@@ -40191,13 +40197,6 @@ const findOutermostEnclosingFunctionRange = (sourceFile, targetLine) => {
|
|
|
40191
40197
|
visit(sourceFile);
|
|
40192
40198
|
return foundRange;
|
|
40193
40199
|
};
|
|
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
|
-
};
|
|
40201
40200
|
/**
|
|
40202
40201
|
* Drops `react-doctor/react-compiler-no-manual-memoization` diagnostics
|
|
40203
40202
|
* whose enclosing function also carries a `react-hooks-js` (React
|
|
@@ -40402,8 +40401,33 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40402
40401
|
}
|
|
40403
40402
|
if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
40404
40403
|
const minifiedFileCache = /* @__PURE__ */ new Map();
|
|
40404
|
+
const sourceBufferCache = /* @__PURE__ */ new Map();
|
|
40405
|
+
const sourceLinesCache = /* @__PURE__ */ new Map();
|
|
40406
|
+
const resolveAbsolutePath = (filename) => Path.isAbsolute(filename) ? filename : Path.resolve(rootDirectory || ".", filename);
|
|
40407
|
+
const readSourceBuffer = (filename) => {
|
|
40408
|
+
const absolutePath = resolveAbsolutePath(filename);
|
|
40409
|
+
const cached = sourceBufferCache.get(absolutePath);
|
|
40410
|
+
if (cached !== void 0) return cached;
|
|
40411
|
+
let sourceBuffer;
|
|
40412
|
+
try {
|
|
40413
|
+
sourceBuffer = NFS.readFileSync(absolutePath);
|
|
40414
|
+
} catch {
|
|
40415
|
+
sourceBuffer = null;
|
|
40416
|
+
}
|
|
40417
|
+
sourceBufferCache.set(absolutePath, sourceBuffer);
|
|
40418
|
+
return sourceBuffer;
|
|
40419
|
+
};
|
|
40420
|
+
const readSourceLines = (filename) => {
|
|
40421
|
+
const absolutePath = resolveAbsolutePath(filename);
|
|
40422
|
+
const cached = sourceLinesCache.get(absolutePath);
|
|
40423
|
+
if (cached !== void 0) return cached;
|
|
40424
|
+
const sourceBuffer = readSourceBuffer(filename);
|
|
40425
|
+
const sourceLines = sourceBuffer ? sourceBuffer.toString("utf8").split("\n") : null;
|
|
40426
|
+
sourceLinesCache.set(absolutePath, sourceLines);
|
|
40427
|
+
return sourceLines;
|
|
40428
|
+
};
|
|
40405
40429
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
40406
|
-
const absolutePath =
|
|
40430
|
+
const absolutePath = resolveAbsolutePath(filename);
|
|
40407
40431
|
const cached = minifiedFileCache.get(absolutePath);
|
|
40408
40432
|
if (cached !== void 0) return cached;
|
|
40409
40433
|
const minified = isMinifiedSource(absolutePath);
|
|
@@ -40416,8 +40440,17 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40416
40440
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
40417
40441
|
const normalizedFilePath = diagnostic.filename.replaceAll("\\", "/");
|
|
40418
40442
|
const primarySpan = primaryLabel?.span;
|
|
40443
|
+
const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
|
|
40419
40444
|
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
|
|
40420
40445
|
const category = resolveDiagnosticCategory(plugin, rule);
|
|
40446
|
+
const matchByOccurrence = resolveMatchByOccurrence(rule, category);
|
|
40447
|
+
const sourceLines = primarySpan ? readSourceLines(diagnostic.filename) : null;
|
|
40448
|
+
const primaryLineIndex = primarySpan ? primarySpan.line - 1 : -1;
|
|
40449
|
+
const primaryLine = sourceLines?.[primaryLineIndex];
|
|
40450
|
+
const primaryColumnIndex = primarySpan ? primarySpan.column - 1 : -1;
|
|
40451
|
+
const isJsxTagLabel = primaryLine !== void 0 && primaryColumnIndex >= 0 && (primaryLine[primaryColumnIndex] === "<" || primaryLine[primaryColumnIndex - 1] === "<");
|
|
40452
|
+
const jsxOpenerEndLineIndex = sourceLines && isJsxTagLabel ? findJsxOpenerSpan(sourceLines, primaryLineIndex) : null;
|
|
40453
|
+
const primarySpanEndLine = jsxOpenerEndLineIndex !== null ? jsxOpenerEndLineIndex + 1 : primarySpan && sourceBuffer ? lineOfUtf8Offset(sourceBuffer, primarySpan.offset + Math.max(primarySpan.length - 1, 0)) : void 0;
|
|
40421
40454
|
return {
|
|
40422
40455
|
filePath: normalizedFilePath,
|
|
40423
40456
|
plugin,
|
|
@@ -40431,10 +40464,11 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40431
40464
|
column: primarySpan?.column ?? 0,
|
|
40432
40465
|
...primarySpan ? {
|
|
40433
40466
|
offset: primarySpan.offset,
|
|
40434
|
-
length: primarySpan.length
|
|
40467
|
+
length: primarySpan.length,
|
|
40468
|
+
...primarySpanEndLine !== void 0 ? { endLine: primarySpanEndLine } : {}
|
|
40435
40469
|
} : {},
|
|
40436
40470
|
category,
|
|
40437
|
-
...
|
|
40471
|
+
...matchByOccurrence ? { matchByOccurrence: true } : {},
|
|
40438
40472
|
...relatedLocations.length > 0 ? { relatedLocations } : {}
|
|
40439
40473
|
};
|
|
40440
40474
|
}), rootDirectory);
|
|
@@ -44844,5 +44878,5 @@ const startLanguageServer = () => {
|
|
|
44844
44878
|
};
|
|
44845
44879
|
//#endregion
|
|
44846
44880
|
export { startLanguageServer };
|
|
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]="
|
|
44848
|
-
//# debugId=
|
|
44881
|
+
!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]="f9337714-b38f-5f28-ac00-c9d7d79ebaea")}catch(e){}}();
|
|
44882
|
+
//# debugId=f9337714-b38f-5f28-ac00-c9d7d79ebaea
|
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.e141d90",
|
|
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
|
+
"deslop-js": "0.7.6",
|
|
69
|
+
"oxlint-plugin-react-doctor": "0.7.6-dev.e141d90"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/babel__code-frame": "^7.27.0",
|