react-doctor 0.7.6-dev.64950ba → 0.7.6-dev.778f1a2
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 -25
- package/dist/index.d.ts +4 -3
- package/dist/index.js +50 -19
- package/dist/lsp.js +51 -20
- package/package.json +5 -5
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]="c3f08fa5-b97a-564f-9c58-cdb72d8eab8f")}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";
|
|
@@ -40762,9 +40762,7 @@ const setColorEnabled = (enabled) => {
|
|
|
40762
40762
|
highlighter.gray = colors.gray;
|
|
40763
40763
|
highlighter.bold = colors.bold;
|
|
40764
40764
|
};
|
|
40765
|
-
const
|
|
40766
|
-
const shouldIncludeExplicitLintPath = (filePath, project) => JSX_FILE_PATTERN.test(filePath) || project?.framework === "nextjs" && NEXT_ENTRY_FILE_PATTERN.test(filePath);
|
|
40767
|
-
const computeExplicitLintIncludePaths = (includePaths, project) => includePaths.length > 0 ? includePaths.filter((filePath) => shouldIncludeExplicitLintPath(filePath, project)) : void 0;
|
|
40765
|
+
const computeExplicitLintIncludePaths = (includePaths) => includePaths.length > 0 ? includePaths.filter(isLintableSourceFile) : void 0;
|
|
40768
40766
|
const LINGUIST_ATTRIBUTE_PATTERN = /^linguist-(?:vendored|generated)(?:=([a-zA-Z0-9]+))?$/i;
|
|
40769
40767
|
const FALSY_VALUES = new Set([
|
|
40770
40768
|
"false",
|
|
@@ -41603,11 +41601,11 @@ const resolveDeadCodeTimeout = (input) => {
|
|
|
41603
41601
|
phaseTimeoutMs: workerTimeoutMs + DEAD_CODE_PHASE_TIMEOUT_OVER_WORKER_MS
|
|
41604
41602
|
};
|
|
41605
41603
|
};
|
|
41606
|
-
const resolveLintIncludePaths = (rootDirectory, userConfig
|
|
41604
|
+
const resolveLintIncludePaths = (rootDirectory, userConfig) => {
|
|
41607
41605
|
if (!Array.isArray(userConfig?.ignore?.files) || userConfig.ignore.files.length === 0) return;
|
|
41608
41606
|
const ignoredPatterns = compileIgnoredFilePatterns(userConfig);
|
|
41609
41607
|
return listSourceFiles(rootDirectory).filter((filePath) => {
|
|
41610
|
-
if (!
|
|
41608
|
+
if (!isLintableSourceFile(filePath)) return false;
|
|
41611
41609
|
return !isFileIgnoredByPatterns(filePath, rootDirectory, ignoredPatterns);
|
|
41612
41610
|
});
|
|
41613
41611
|
};
|
|
@@ -42888,6 +42886,12 @@ const mapWithConcurrency = async (items, concurrency, task) => {
|
|
|
42888
42886
|
if (errors.length > 0) throw errors[0];
|
|
42889
42887
|
return results;
|
|
42890
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
|
+
};
|
|
42891
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";
|
|
42892
42896
|
const ACCESSORS_MIN_VERSION = "3.15.0";
|
|
42893
42897
|
const supportsAccessors = (reanimatedVersion) => {
|
|
@@ -43459,13 +43463,6 @@ const findOutermostEnclosingFunctionRange = (sourceFile, targetLine) => {
|
|
|
43459
43463
|
visit(sourceFile);
|
|
43460
43464
|
return foundRange;
|
|
43461
43465
|
};
|
|
43462
|
-
const NEWLINE_BYTE = 10;
|
|
43463
|
-
const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
43464
|
-
let lineNumber = 1;
|
|
43465
|
-
const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
|
|
43466
|
-
for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === NEWLINE_BYTE) lineNumber++;
|
|
43467
|
-
return lineNumber;
|
|
43468
|
-
};
|
|
43469
43466
|
/**
|
|
43470
43467
|
* Drops `react-doctor/react-compiler-no-manual-memoization` diagnostics
|
|
43471
43468
|
* whose enclosing function also carries a `react-hooks-js` (React
|
|
@@ -43670,8 +43667,33 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
43670
43667
|
}
|
|
43671
43668
|
if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
43672
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
|
+
};
|
|
43673
43695
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
43674
|
-
const absolutePath =
|
|
43696
|
+
const absolutePath = resolveAbsolutePath(filename);
|
|
43675
43697
|
const cached = minifiedFileCache.get(absolutePath);
|
|
43676
43698
|
if (cached !== void 0) return cached;
|
|
43677
43699
|
const minified = isMinifiedSource(absolutePath);
|
|
@@ -43684,8 +43706,17 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
43684
43706
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
43685
43707
|
const normalizedFilePath = diagnostic.filename.replaceAll("\\", "/");
|
|
43686
43708
|
const primarySpan = primaryLabel?.span;
|
|
43709
|
+
const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
|
|
43687
43710
|
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
|
|
43688
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;
|
|
43689
43720
|
return {
|
|
43690
43721
|
filePath: normalizedFilePath,
|
|
43691
43722
|
plugin,
|
|
@@ -43699,10 +43730,11 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
43699
43730
|
column: primarySpan?.column ?? 0,
|
|
43700
43731
|
...primarySpan ? {
|
|
43701
43732
|
offset: primarySpan.offset,
|
|
43702
|
-
length: primarySpan.length
|
|
43733
|
+
length: primarySpan.length,
|
|
43734
|
+
...primarySpanEndLine !== void 0 ? { endLine: primarySpanEndLine } : {}
|
|
43703
43735
|
} : {},
|
|
43704
43736
|
category,
|
|
43705
|
-
...
|
|
43737
|
+
...matchByOccurrence ? { matchByOccurrence: true } : {},
|
|
43706
43738
|
...relatedLocations.length > 0 ? { relatedLocations } : {}
|
|
43707
43739
|
};
|
|
43708
43740
|
}), rootDirectory);
|
|
@@ -45489,7 +45521,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
45489
45521
|
directory: scanDirectory,
|
|
45490
45522
|
repo
|
|
45491
45523
|
}).pipe(orElseSucceed(() => null)) : succeed$2(null));
|
|
45492
|
-
const lintIncludePaths = (input.
|
|
45524
|
+
const lintIncludePaths = (input.skipExplicitIncludePathFilter ? input.includePaths.length > 0 ? [...input.includePaths] : void 0 : computeExplicitLintIncludePaths([...input.includePaths])) ?? resolveLintIncludePaths(scanDirectory, resolvedConfig.config);
|
|
45493
45525
|
const fallbackScannedFilePaths = input.suppressScanSummary ? (lintIncludePaths ?? (yield* filesService.listSourceFiles(scanDirectory))).map((relativePath) => Path.resolve(scanDirectory, relativePath)) : [];
|
|
45494
45526
|
const beforeLint = hooks.beforeLint ?? NO_HOOKS.beforeLint;
|
|
45495
45527
|
const afterLint = hooks.afterLint ?? NO_HOOKS.afterLint;
|
|
@@ -46667,7 +46699,7 @@ const makeNoopConsole = () => ({
|
|
|
46667
46699
|
});
|
|
46668
46700
|
//#endregion
|
|
46669
46701
|
//#region src/cli/utils/version.ts
|
|
46670
|
-
const VERSION = "0.7.6-dev.
|
|
46702
|
+
const VERSION = "0.7.6-dev.778f1a2";
|
|
46671
46703
|
//#endregion
|
|
46672
46704
|
//#region src/cli/utils/json-mode.ts
|
|
46673
46705
|
let context = null;
|
|
@@ -47036,13 +47068,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
|
|
|
47036
47068
|
* uploads source-map artifacts under, so stack frames symbolicate. Honors the
|
|
47037
47069
|
* standard `SENTRY_RELEASE` override.
|
|
47038
47070
|
*/
|
|
47039
|
-
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.778f1a2`;
|
|
47040
47072
|
/**
|
|
47041
47073
|
* Deployment environment shown in Sentry's environment filter. Defaults to
|
|
47042
47074
|
* `production` for tagged releases and `development` for dev/unbuilt versions,
|
|
47043
47075
|
* overridable via the standard `SENTRY_ENVIRONMENT` env var.
|
|
47044
47076
|
*/
|
|
47045
|
-
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.6-dev.
|
|
47077
|
+
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.7.6-dev.778f1a2") ? "development" : "production");
|
|
47046
47078
|
/**
|
|
47047
47079
|
* Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
|
|
47048
47080
|
* (set to `0` to disable tracing) and falls back to
|
|
@@ -50807,7 +50839,7 @@ const BLOCKING_SUMMARY = {
|
|
|
50807
50839
|
const SCOPE_SUMMARY = {
|
|
50808
50840
|
full: "Scan the whole project on every run",
|
|
50809
50841
|
files: "Report every issue in changed files",
|
|
50810
|
-
lines: "Report issues
|
|
50842
|
+
lines: "Report issues whose source spans touch changed lines",
|
|
50811
50843
|
changed: "Report only the issues a change introduces"
|
|
50812
50844
|
};
|
|
50813
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;
|
|
@@ -59676,7 +59708,9 @@ const buildScanAttributes = (input) => {
|
|
|
59676
59708
|
hasCustomConfig: input.hasCustomConfig,
|
|
59677
59709
|
rulesConfigured: ruleKeys.length,
|
|
59678
59710
|
rulesDisabled: ruleKeys.filter((key) => ruleOverrides[key] === "off").length,
|
|
59679
|
-
fileCount: input.result?.scannedFileCount ?? null
|
|
59711
|
+
fileCount: input.result?.scannedFileCount ?? 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
|
|
59680
59714
|
});
|
|
59681
59715
|
};
|
|
59682
59716
|
/**
|
|
@@ -59745,6 +59779,12 @@ const countDeadlineSkippedFiles = (lintPartialFailures) => sumFileCountsMatching
|
|
|
59745
59779
|
const DROPPED_FILES_MESSAGE_PATTERN = /^(\d+) file\(s\) failed to lint and were skipped/;
|
|
59746
59780
|
const countDroppedLintFiles = (lintPartialFailures) => sumFileCountsMatching(lintPartialFailures, DROPPED_FILES_MESSAGE_PATTERN);
|
|
59747
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
|
|
59748
59788
|
//#region src/cli/utils/materialize-baseline-files.ts
|
|
59749
59789
|
/**
|
|
59750
59790
|
* Materializes the `ref` version of `files` into `tempDirectory` (via
|
|
@@ -60930,7 +60970,7 @@ const buildChangedLineMatcher = (directory, changedLineRanges) => {
|
|
|
60930
60970
|
const relativePath = toForwardSlashes(path.isAbsolute(diagnostic.filePath) ? path.relative(directory, diagnostic.filePath) : diagnostic.filePath);
|
|
60931
60971
|
const ranges = rangesByFile.get(relativePath);
|
|
60932
60972
|
if (ranges === void 0) return false;
|
|
60933
|
-
return
|
|
60973
|
+
return diagnosticIntersectsLineRanges(diagnostic, ranges);
|
|
60934
60974
|
};
|
|
60935
60975
|
};
|
|
60936
60976
|
const buildIgnoredTags = (userConfig) => {
|
|
@@ -65181,7 +65221,7 @@ ${highlighter.dim("Learn more:")}
|
|
|
65181
65221
|
${highlighter.info(CI_URL)}
|
|
65182
65222
|
`;
|
|
65183
65223
|
const collectCategoryOption = (value, previousValues) => [...previousValues ?? [], value];
|
|
65184
|
-
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 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);
|
|
65185
65225
|
program.action(inspectAction);
|
|
65186
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));
|
|
65187
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);
|
|
@@ -65231,4 +65271,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
|
|
|
65231
65271
|
export {};
|
|
65232
65272
|
|
|
65233
65273
|
//# sourceMappingURL=cli.js.map
|
|
65234
|
-
//# debugId=
|
|
65274
|
+
//# debugId=c3f08fa5-b97a-564f-9c58-cdb72d8eab8f
|
package/dist/index.d.ts
CHANGED
|
@@ -9654,6 +9654,7 @@ interface DiagnoseOptions {
|
|
|
9654
9654
|
/** See `ReactDoctorConfig.deadCode`. Ignored in diff mode. */
|
|
9655
9655
|
deadCode?: boolean;
|
|
9656
9656
|
verbose?: boolean;
|
|
9657
|
+
/** Restrict linting to these supported JS/TS source files. */
|
|
9657
9658
|
includePaths?: string[];
|
|
9658
9659
|
/**
|
|
9659
9660
|
* Per-call override for `ReactDoctorConfig.respectInlineDisables`.
|
|
@@ -9915,9 +9916,9 @@ interface JsonReportProjectEntry {
|
|
|
9915
9916
|
skippedCheckReasons?: Record<string, string>;
|
|
9916
9917
|
/**
|
|
9917
9918
|
* Number of source files this scan's linter examined. In diff / changed
|
|
9918
|
-
* mode it's the count of changed
|
|
9919
|
-
*
|
|
9920
|
-
*
|
|
9919
|
+
* mode it's the count of changed supported JS/TS source files; in a full
|
|
9920
|
+
* scan it's the whole source tree. `0` in a diff scan means the changed
|
|
9921
|
+
* files held nothing React Doctor lints —
|
|
9921
9922
|
* the GitHub Action reads that as "nothing to report" (skips the PR comment;
|
|
9922
9923
|
* the commit status says "skipped"). Optional: absent on reports from
|
|
9923
9924
|
* constructors that don't track it (e.g. `toJsonReport`).
|
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]="fc1129a0-9ad2-5802-a82e-4982d9572eed")}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";
|
|
@@ -32930,7 +32930,6 @@ const IGNORED_DIRECTORIES = new Set([
|
|
|
32930
32930
|
"out",
|
|
32931
32931
|
"storybook-static"
|
|
32932
32932
|
]);
|
|
32933
|
-
const JSX_FILE_PATTERN = /\.(tsx|jsx)$/;
|
|
32934
32933
|
const MILLISECONDS_PER_SECOND = 1e3;
|
|
32935
32934
|
const SCORE_API_URL = "https://www.react.doctor/api/score";
|
|
32936
32935
|
const FETCH_TIMEOUT_MS = 1e4;
|
|
@@ -37516,9 +37515,7 @@ const highlighter = {
|
|
|
37516
37515
|
gray: import_picocolors.default.gray,
|
|
37517
37516
|
bold: import_picocolors.default.bold
|
|
37518
37517
|
};
|
|
37519
|
-
const
|
|
37520
|
-
const shouldIncludeExplicitLintPath = (filePath, project) => JSX_FILE_PATTERN.test(filePath) || project?.framework === "nextjs" && NEXT_ENTRY_FILE_PATTERN.test(filePath);
|
|
37521
|
-
const computeExplicitLintIncludePaths = (includePaths, project) => includePaths.length > 0 ? includePaths.filter((filePath) => shouldIncludeExplicitLintPath(filePath, project)) : void 0;
|
|
37518
|
+
const computeExplicitLintIncludePaths = (includePaths) => includePaths.length > 0 ? includePaths.filter(isLintableSourceFile) : void 0;
|
|
37522
37519
|
const LINGUIST_ATTRIBUTE_PATTERN = /^linguist-(?:vendored|generated)(?:=([a-zA-Z0-9]+))?$/i;
|
|
37523
37520
|
const FALSY_VALUES = new Set([
|
|
37524
37521
|
"false",
|
|
@@ -38360,11 +38357,11 @@ const resolveDeadCodeTimeout = (input) => {
|
|
|
38360
38357
|
phaseTimeoutMs: workerTimeoutMs + DEAD_CODE_PHASE_TIMEOUT_OVER_WORKER_MS
|
|
38361
38358
|
};
|
|
38362
38359
|
};
|
|
38363
|
-
const resolveLintIncludePaths = (rootDirectory, userConfig
|
|
38360
|
+
const resolveLintIncludePaths = (rootDirectory, userConfig) => {
|
|
38364
38361
|
if (!Array.isArray(userConfig?.ignore?.files) || userConfig.ignore.files.length === 0) return;
|
|
38365
38362
|
const ignoredPatterns = compileIgnoredFilePatterns(userConfig);
|
|
38366
38363
|
return listSourceFiles(rootDirectory).filter((filePath) => {
|
|
38367
|
-
if (!
|
|
38364
|
+
if (!isLintableSourceFile(filePath)) return false;
|
|
38368
38365
|
return !isFileIgnoredByPatterns(filePath, rootDirectory, ignoredPatterns);
|
|
38369
38366
|
});
|
|
38370
38367
|
};
|
|
@@ -39645,6 +39642,12 @@ const mapWithConcurrency = async (items, concurrency, task) => {
|
|
|
39645
39642
|
if (errors.length > 0) throw errors[0];
|
|
39646
39643
|
return results;
|
|
39647
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
|
+
};
|
|
39648
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";
|
|
39649
39652
|
const ACCESSORS_MIN_VERSION = "3.15.0";
|
|
39650
39653
|
const supportsAccessors = (reanimatedVersion) => {
|
|
@@ -40216,13 +40219,6 @@ const findOutermostEnclosingFunctionRange = (sourceFile, targetLine) => {
|
|
|
40216
40219
|
visit(sourceFile);
|
|
40217
40220
|
return foundRange;
|
|
40218
40221
|
};
|
|
40219
|
-
const NEWLINE_BYTE = 10;
|
|
40220
|
-
const lineOfUtf8Offset = (sourceBuffer, utf8Offset) => {
|
|
40221
|
-
let lineNumber = 1;
|
|
40222
|
-
const scanEnd = Math.min(utf8Offset, sourceBuffer.length);
|
|
40223
|
-
for (let byteIndex = 0; byteIndex < scanEnd; byteIndex++) if (sourceBuffer[byteIndex] === NEWLINE_BYTE) lineNumber++;
|
|
40224
|
-
return lineNumber;
|
|
40225
|
-
};
|
|
40226
40222
|
/**
|
|
40227
40223
|
* Drops `react-doctor/react-compiler-no-manual-memoization` diagnostics
|
|
40228
40224
|
* whose enclosing function also carries a `react-hooks-js` (React
|
|
@@ -40427,8 +40423,33 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40427
40423
|
}
|
|
40428
40424
|
if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
40429
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
|
+
};
|
|
40430
40451
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
40431
|
-
const absolutePath =
|
|
40452
|
+
const absolutePath = resolveAbsolutePath(filename);
|
|
40432
40453
|
const cached = minifiedFileCache.get(absolutePath);
|
|
40433
40454
|
if (cached !== void 0) return cached;
|
|
40434
40455
|
const minified = isMinifiedSource(absolutePath);
|
|
@@ -40441,8 +40462,17 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40441
40462
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
40442
40463
|
const normalizedFilePath = diagnostic.filename.replaceAll("\\", "/");
|
|
40443
40464
|
const primarySpan = primaryLabel?.span;
|
|
40465
|
+
const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
|
|
40444
40466
|
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
|
|
40445
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;
|
|
40446
40476
|
return {
|
|
40447
40477
|
filePath: normalizedFilePath,
|
|
40448
40478
|
plugin,
|
|
@@ -40456,10 +40486,11 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40456
40486
|
column: primarySpan?.column ?? 0,
|
|
40457
40487
|
...primarySpan ? {
|
|
40458
40488
|
offset: primarySpan.offset,
|
|
40459
|
-
length: primarySpan.length
|
|
40489
|
+
length: primarySpan.length,
|
|
40490
|
+
...primarySpanEndLine !== void 0 ? { endLine: primarySpanEndLine } : {}
|
|
40460
40491
|
} : {},
|
|
40461
40492
|
category,
|
|
40462
|
-
...
|
|
40493
|
+
...matchByOccurrence ? { matchByOccurrence: true } : {},
|
|
40463
40494
|
...relatedLocations.length > 0 ? { relatedLocations } : {}
|
|
40464
40495
|
};
|
|
40465
40496
|
}), rootDirectory);
|
|
@@ -42246,7 +42277,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
42246
42277
|
directory: scanDirectory,
|
|
42247
42278
|
repo
|
|
42248
42279
|
}).pipe(orElseSucceed(() => null)) : succeed$2(null));
|
|
42249
|
-
const lintIncludePaths = (input.
|
|
42280
|
+
const lintIncludePaths = (input.skipExplicitIncludePathFilter ? input.includePaths.length > 0 ? [...input.includePaths] : void 0 : computeExplicitLintIncludePaths([...input.includePaths])) ?? resolveLintIncludePaths(scanDirectory, resolvedConfig.config);
|
|
42250
42281
|
const fallbackScannedFilePaths = input.suppressScanSummary ? (lintIncludePaths ?? (yield* filesService.listSourceFiles(scanDirectory))).map((relativePath) => Path.resolve(scanDirectory, relativePath)) : [];
|
|
42251
42282
|
const beforeLint = hooks.beforeLint ?? NO_HOOKS.beforeLint;
|
|
42252
42283
|
const afterLint = hooks.afterLint ?? NO_HOOKS.afterLint;
|
|
@@ -43210,4 +43241,4 @@ const toJsonReport = (result, options) => buildJsonReport({
|
|
|
43210
43241
|
export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, hasReactRuntime, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
|
|
43211
43242
|
|
|
43212
43243
|
//# sourceMappingURL=index.js.map
|
|
43213
|
-
//# debugId=
|
|
43244
|
+
//# debugId=fc1129a0-9ad2-5802-a82e-4982d9572eed
|
package/dist/lsp.js
CHANGED
|
@@ -32959,7 +32959,6 @@ const IGNORED_DIRECTORIES = new Set([
|
|
|
32959
32959
|
"out",
|
|
32960
32960
|
"storybook-static"
|
|
32961
32961
|
]);
|
|
32962
|
-
const JSX_FILE_PATTERN = /\.(tsx|jsx)$/;
|
|
32963
32962
|
const MILLISECONDS_PER_SECOND = 1e3;
|
|
32964
32963
|
const SCORE_API_URL = "https://www.react.doctor/api/score";
|
|
32965
32964
|
const FETCH_TIMEOUT_MS = 1e4;
|
|
@@ -37494,9 +37493,7 @@ const highlighter = {
|
|
|
37494
37493
|
gray: import_picocolors.default.gray,
|
|
37495
37494
|
bold: import_picocolors.default.bold
|
|
37496
37495
|
};
|
|
37497
|
-
const
|
|
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;
|
|
37496
|
+
const computeExplicitLintIncludePaths = (includePaths) => includePaths.length > 0 ? includePaths.filter(isLintableSourceFile) : void 0;
|
|
37500
37497
|
const LINGUIST_ATTRIBUTE_PATTERN = /^linguist-(?:vendored|generated)(?:=([a-zA-Z0-9]+))?$/i;
|
|
37501
37498
|
const FALSY_VALUES = new Set([
|
|
37502
37499
|
"false",
|
|
@@ -38338,11 +38335,11 @@ const resolveDeadCodeTimeout = (input) => {
|
|
|
38338
38335
|
phaseTimeoutMs: workerTimeoutMs + DEAD_CODE_PHASE_TIMEOUT_OVER_WORKER_MS
|
|
38339
38336
|
};
|
|
38340
38337
|
};
|
|
38341
|
-
const resolveLintIncludePaths = (rootDirectory, userConfig
|
|
38338
|
+
const resolveLintIncludePaths = (rootDirectory, userConfig) => {
|
|
38342
38339
|
if (!Array.isArray(userConfig?.ignore?.files) || userConfig.ignore.files.length === 0) return;
|
|
38343
38340
|
const ignoredPatterns = compileIgnoredFilePatterns(userConfig);
|
|
38344
38341
|
return listSourceFiles(rootDirectory).filter((filePath) => {
|
|
38345
|
-
if (!
|
|
38342
|
+
if (!isLintableSourceFile(filePath)) return false;
|
|
38346
38343
|
return !isFileIgnoredByPatterns(filePath, rootDirectory, ignoredPatterns);
|
|
38347
38344
|
});
|
|
38348
38345
|
};
|
|
@@ -39623,6 +39620,12 @@ const mapWithConcurrency = async (items, concurrency, task) => {
|
|
|
39623
39620
|
if (errors.length > 0) throw errors[0];
|
|
39624
39621
|
return results;
|
|
39625
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
|
+
};
|
|
39626
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";
|
|
39627
39630
|
const ACCESSORS_MIN_VERSION = "3.15.0";
|
|
39628
39631
|
const supportsAccessors = (reanimatedVersion) => {
|
|
@@ -40194,13 +40197,6 @@ const findOutermostEnclosingFunctionRange = (sourceFile, targetLine) => {
|
|
|
40194
40197
|
visit(sourceFile);
|
|
40195
40198
|
return foundRange;
|
|
40196
40199
|
};
|
|
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
|
-
};
|
|
40204
40200
|
/**
|
|
40205
40201
|
* Drops `react-doctor/react-compiler-no-manual-memoization` diagnostics
|
|
40206
40202
|
* whose enclosing function also carries a `react-hooks-js` (React
|
|
@@ -40405,8 +40401,33 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40405
40401
|
}
|
|
40406
40402
|
if (!isOxlintOutput(parsed)) throw new ReactDoctorError({ reason: new OxlintOutputUnparseable({ preview: stdout.slice(0, 600) }) });
|
|
40407
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
|
+
};
|
|
40408
40429
|
const isMinifiedDiagnosticFile = (filename) => {
|
|
40409
|
-
const absolutePath =
|
|
40430
|
+
const absolutePath = resolveAbsolutePath(filename);
|
|
40410
40431
|
const cached = minifiedFileCache.get(absolutePath);
|
|
40411
40432
|
if (cached !== void 0) return cached;
|
|
40412
40433
|
const minified = isMinifiedSource(absolutePath);
|
|
@@ -40419,8 +40440,17 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40419
40440
|
const cleaned = cleanDiagnosticMessage(diagnostic.message, diagnostic.help, plugin, rule, project);
|
|
40420
40441
|
const normalizedFilePath = diagnostic.filename.replaceAll("\\", "/");
|
|
40421
40442
|
const primarySpan = primaryLabel?.span;
|
|
40443
|
+
const sourceBuffer = primarySpan ? readSourceBuffer(diagnostic.filename) : null;
|
|
40422
40444
|
const relatedLocations = buildRelatedLocations(diagnostic.labels, normalizedFilePath);
|
|
40423
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;
|
|
40424
40454
|
return {
|
|
40425
40455
|
filePath: normalizedFilePath,
|
|
40426
40456
|
plugin,
|
|
@@ -40434,10 +40464,11 @@ const parseOxlintOutput = (stdout, project, rootDirectory) => {
|
|
|
40434
40464
|
column: primarySpan?.column ?? 0,
|
|
40435
40465
|
...primarySpan ? {
|
|
40436
40466
|
offset: primarySpan.offset,
|
|
40437
|
-
length: primarySpan.length
|
|
40467
|
+
length: primarySpan.length,
|
|
40468
|
+
...primarySpanEndLine !== void 0 ? { endLine: primarySpanEndLine } : {}
|
|
40438
40469
|
} : {},
|
|
40439
40470
|
category,
|
|
40440
|
-
...
|
|
40471
|
+
...matchByOccurrence ? { matchByOccurrence: true } : {},
|
|
40441
40472
|
...relatedLocations.length > 0 ? { relatedLocations } : {}
|
|
40442
40473
|
};
|
|
40443
40474
|
}), rootDirectory);
|
|
@@ -42224,7 +42255,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
42224
42255
|
directory: scanDirectory,
|
|
42225
42256
|
repo
|
|
42226
42257
|
}).pipe(orElseSucceed(() => null)) : succeed$2(null));
|
|
42227
|
-
const lintIncludePaths = (input.
|
|
42258
|
+
const lintIncludePaths = (input.skipExplicitIncludePathFilter ? input.includePaths.length > 0 ? [...input.includePaths] : void 0 : computeExplicitLintIncludePaths([...input.includePaths])) ?? resolveLintIncludePaths(scanDirectory, resolvedConfig.config);
|
|
42228
42259
|
const fallbackScannedFilePaths = input.suppressScanSummary ? (lintIncludePaths ?? (yield* filesService.listSourceFiles(scanDirectory))).map((relativePath) => Path.resolve(scanDirectory, relativePath)) : [];
|
|
42229
42260
|
const beforeLint = hooks.beforeLint ?? NO_HOOKS.beforeLint;
|
|
42230
42261
|
const afterLint = hooks.afterLint ?? NO_HOOKS.afterLint;
|
|
@@ -42719,7 +42750,7 @@ const runEditorScan = async (input) => {
|
|
|
42719
42750
|
warnings,
|
|
42720
42751
|
isCi: false,
|
|
42721
42752
|
resolveLocalGithubViewerPermission: false,
|
|
42722
|
-
|
|
42753
|
+
skipExplicitIncludePathFilter: true
|
|
42723
42754
|
}).pipe(withSpan("runEditorScan", { attributes: {
|
|
42724
42755
|
"editor.lint": lint,
|
|
42725
42756
|
"editor.runDeadCode": runDeadCode
|
|
@@ -44847,5 +44878,5 @@ const startLanguageServer = () => {
|
|
|
44847
44878
|
};
|
|
44848
44879
|
//#endregion
|
|
44849
44880
|
export { startLanguageServer };
|
|
44850
|
-
!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]="
|
|
44851
|
-
//# 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]="e43f1571-2fdb-5f22-88b7-df9f86c3af31")}catch(e){}}();
|
|
44882
|
+
//# debugId=e43f1571-2fdb-5f22-88b7-df9f86c3af31
|
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.778f1a2",
|
|
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.778f1a2"
|
|
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/api": "0.7.6",
|
|
78
|
-
"@react-doctor/
|
|
79
|
-
"@react-doctor/
|
|
78
|
+
"@react-doctor/language-server": "0.7.6",
|
|
79
|
+
"@react-doctor/core": "0.7.6"
|
|
80
80
|
},
|
|
81
81
|
"engines": {
|
|
82
82
|
"node": "^20.19.0 || >=22.13.0"
|