react-doctor 0.5.8-dev.c72b560 → 0.5.8-dev.e2393c4
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/README.md +9 -3
- package/dist/cli.js +8925 -1334
- package/dist/index.d.ts +9 -0
- package/dist/index.js +24 -6
- package/dist/lsp.js +29 -7
- package/package.json +4 -3
package/dist/index.d.ts
CHANGED
|
@@ -9271,6 +9271,15 @@ interface ReactDoctorConfig {
|
|
|
9271
9271
|
* suppresses regardless of sibling content.
|
|
9272
9272
|
*/
|
|
9273
9273
|
rawTextWrapperComponents?: string[];
|
|
9274
|
+
/**
|
|
9275
|
+
* Capitalized identifiers that exist at runtime but aren't imported in
|
|
9276
|
+
* the file that uses them — react-live's `<LiveProvider scope={...}>`,
|
|
9277
|
+
* Storybook globals, MDX live blocks, or an ambient `declare global` in a
|
|
9278
|
+
* separate `.d.ts`. The single-file `jsx-no-undef` rule can't see those
|
|
9279
|
+
* bindings and would report `<DatePicker />` as an undefined JSX component.
|
|
9280
|
+
* List the injected names here and `jsx-no-undef` treats them as known.
|
|
9281
|
+
*/
|
|
9282
|
+
runtimeGlobals?: string[];
|
|
9274
9283
|
/**
|
|
9275
9284
|
* Project-level allowlist of function names that the
|
|
9276
9285
|
* `server-auth-actions` rule treats as an auth check at the top of
|
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]="1e049c6a-27f7-5c62-8be8-57ce0b987f6f")}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 * as NFS from "node:fs";
|
|
@@ -34999,6 +34999,7 @@ const collectStringSet = (values) => {
|
|
|
34999
34999
|
if (!Array.isArray(values)) return /* @__PURE__ */ new Set();
|
|
35000
35000
|
return new Set(values.filter((value) => typeof value === "string"));
|
|
35001
35001
|
};
|
|
35002
|
+
const JSX_NO_UNDEF_IDENTIFIER_PATTERN = /^`([^`]+)`/;
|
|
35002
35003
|
/**
|
|
35003
35004
|
* Pre-compiles every stateful filter and returns a single
|
|
35004
35005
|
* `apply(diagnostic)` closure that runs (in order):
|
|
@@ -35032,8 +35033,10 @@ const buildDiagnosticPipeline = (input) => {
|
|
|
35032
35033
|
const compiledOverrides = compileIgnoreOverrides(userConfig);
|
|
35033
35034
|
const textComponentNames = collectStringSet(userConfig?.textComponents);
|
|
35034
35035
|
const rawTextWrapperComponentNames = collectStringSet(userConfig?.rawTextWrapperComponents);
|
|
35036
|
+
const runtimeGlobalNames = collectStringSet(userConfig?.runtimeGlobals);
|
|
35035
35037
|
const hasTextComponents = textComponentNames.size > 0;
|
|
35036
35038
|
const hasRawTextWrappers = rawTextWrapperComponentNames.size > 0;
|
|
35039
|
+
const hasRuntimeGlobals = runtimeGlobalNames.size > 0;
|
|
35037
35040
|
const fileLinesCache = /* @__PURE__ */ new Map();
|
|
35038
35041
|
const fileContextCache = /* @__PURE__ */ new Map();
|
|
35039
35042
|
const libraryFileCache = /* @__PURE__ */ new Map();
|
|
@@ -35085,6 +35088,12 @@ const buildDiagnosticPipeline = (input) => {
|
|
|
35085
35088
|
if (hasRawTextWrappers && isInsideStringOnlyWrapper(lines, diagnostic.line, diagnostic.column, rawTextWrapperComponentNames)) return true;
|
|
35086
35089
|
return false;
|
|
35087
35090
|
};
|
|
35091
|
+
const isJsxNoUndefSuppressedByConfig = (diagnostic) => {
|
|
35092
|
+
if (!hasRuntimeGlobals) return false;
|
|
35093
|
+
if (diagnostic.rule !== "jsx-no-undef") return false;
|
|
35094
|
+
const identifierMatch = JSX_NO_UNDEF_IDENTIFIER_PATTERN.exec(diagnostic.message);
|
|
35095
|
+
return identifierMatch !== null && runtimeGlobalNames.has(identifierMatch[1]);
|
|
35096
|
+
};
|
|
35088
35097
|
return { apply: (diagnostic) => {
|
|
35089
35098
|
if (shouldAutoSuppress(diagnostic)) return null;
|
|
35090
35099
|
let current = diagnostic;
|
|
@@ -35109,6 +35118,7 @@ const buildDiagnosticPipeline = (input) => {
|
|
|
35109
35118
|
if (isFileIgnoredByPatterns(current.filePath, rootDirectory, ignoredFilePatterns)) return null;
|
|
35110
35119
|
if (isDiagnosticIgnoredByOverrides(current, rootDirectory, compiledOverrides)) return null;
|
|
35111
35120
|
if (isRnRawTextSuppressedByConfig(current)) return null;
|
|
35121
|
+
if (isJsxNoUndefSuppressedByConfig(current)) return null;
|
|
35112
35122
|
}
|
|
35113
35123
|
if (respectInlineDisables && current.line > 0) {
|
|
35114
35124
|
const lines = getFileLines(current.filePath);
|
|
@@ -35586,6 +35596,7 @@ const STRING_ARRAY_FIELD_NAMES = [
|
|
|
35586
35596
|
"projects",
|
|
35587
35597
|
"textComponents",
|
|
35588
35598
|
"rawTextWrapperComponents",
|
|
35599
|
+
"runtimeGlobals",
|
|
35589
35600
|
"serverAuthFunctionNames"
|
|
35590
35601
|
];
|
|
35591
35602
|
const SURFACE_CONTROL_FIELD_NAMES = [
|
|
@@ -37290,6 +37301,11 @@ const toCanonicalPath = (filePath) => {
|
|
|
37290
37301
|
};
|
|
37291
37302
|
const DEAD_CODE_PLUGIN = "deslop";
|
|
37292
37303
|
const DEAD_CODE_CATEGORY = "Maintainability";
|
|
37304
|
+
const REACT_DOCTOR_TOOLCHAIN_PACKAGES = new Set([
|
|
37305
|
+
"react-doctor",
|
|
37306
|
+
"eslint-plugin-react-doctor",
|
|
37307
|
+
"oxlint-plugin-react-doctor"
|
|
37308
|
+
]);
|
|
37293
37309
|
const DEAD_CODE_WORKER_SCRIPT = `
|
|
37294
37310
|
const inputChunks = [];
|
|
37295
37311
|
process.stdin.on("data", (chunk) => inputChunks.push(chunk));
|
|
@@ -37595,6 +37611,7 @@ const checkDeadCode = async (options) => {
|
|
|
37595
37611
|
});
|
|
37596
37612
|
}
|
|
37597
37613
|
for (const unusedDependency of result.unusedDependencies) {
|
|
37614
|
+
if (REACT_DOCTOR_TOOLCHAIN_PACKAGES.has(unusedDependency.name)) continue;
|
|
37598
37615
|
const label = unusedDependency.isDevDependency ? "devDependency" : "dependency";
|
|
37599
37616
|
diagnostics.push({
|
|
37600
37617
|
filePath: "package.json",
|
|
@@ -39328,11 +39345,12 @@ const REACT_COMPILER_TITLE = "React Compiler can't optimize this";
|
|
|
39328
39345
|
const REACT_COMPILER_TODO_TITLE = "React Compiler doesn't support this syntax";
|
|
39329
39346
|
const REACT_COMPILER_IMPACT = "This component misses React Compiler's automatic memoization & re-renders more than it should";
|
|
39330
39347
|
const REACT_COMPILER_ACTION = "Rewrite the flagged code so the compiler can optimize it.";
|
|
39348
|
+
const REACT_COMPILER_INCOMPATIBLE_LIBRARY_ACTION = "It's how the library works, not a bug in your code. Memoize values you pass from it into other memoized components, or suppress it with `// react-doctor-disable-next-line react-hooks-js/incompatible-library`.";
|
|
39331
39349
|
const REACT_COMPILER_GENERIC_MESSAGE = `${REACT_COMPILER_IMPACT}. ${REACT_COMPILER_ACTION}`;
|
|
39332
|
-
const buildReactCompilerMessage = (reasonSummary) => {
|
|
39350
|
+
const buildReactCompilerMessage = (reasonSummary, action = REACT_COMPILER_ACTION) => {
|
|
39333
39351
|
const normalizedSummary = reasonSummary.replace(TRAILING_PERIOD_PATTERN, "");
|
|
39334
|
-
if (!normalizedSummary) return
|
|
39335
|
-
return `${REACT_COMPILER_IMPACT}: ${normalizedSummary}. ${
|
|
39352
|
+
if (!normalizedSummary) return `${REACT_COMPILER_IMPACT}. ${action}`;
|
|
39353
|
+
return `${REACT_COMPILER_IMPACT}: ${normalizedSummary}. ${action}`;
|
|
39336
39354
|
};
|
|
39337
39355
|
const PLUGIN_CATEGORY_MAP = {
|
|
39338
39356
|
react: "Bugs",
|
|
@@ -39381,7 +39399,7 @@ const resolveCleanedDiagnostic = (message, help, plugin, rule, project) => {
|
|
|
39381
39399
|
const [reasonSummary = "", ...reasonDetailLines] = bailoutReason.split("\n");
|
|
39382
39400
|
const reasonDetail = reasonDetailLines.join("\n").trim();
|
|
39383
39401
|
return {
|
|
39384
|
-
message: buildReactCompilerMessage(reasonSummary.trim()),
|
|
39402
|
+
message: buildReactCompilerMessage(reasonSummary.trim(), rule === "incompatible-library" ? REACT_COMPILER_INCOMPATIBLE_LIBRARY_ACTION : REACT_COMPILER_ACTION),
|
|
39385
39403
|
help: appendReanimatedSharedValueHint(reasonDetail || help, rule, project)
|
|
39386
39404
|
};
|
|
39387
39405
|
}
|
|
@@ -41645,4 +41663,4 @@ const toJsonReport = (result, options) => buildJsonReport({
|
|
|
41645
41663
|
export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
|
|
41646
41664
|
|
|
41647
41665
|
//# sourceMappingURL=index.js.map
|
|
41648
|
-
//# debugId=
|
|
41666
|
+
//# debugId=1e049c6a-27f7-5c62-8be8-57ce0b987f6f
|
package/dist/lsp.js
CHANGED
|
@@ -35054,6 +35054,7 @@ const collectStringSet = (values) => {
|
|
|
35054
35054
|
if (!Array.isArray(values)) return /* @__PURE__ */ new Set();
|
|
35055
35055
|
return new Set(values.filter((value) => typeof value === "string"));
|
|
35056
35056
|
};
|
|
35057
|
+
const JSX_NO_UNDEF_IDENTIFIER_PATTERN = /^`([^`]+)`/;
|
|
35057
35058
|
/**
|
|
35058
35059
|
* Pre-compiles every stateful filter and returns a single
|
|
35059
35060
|
* `apply(diagnostic)` closure that runs (in order):
|
|
@@ -35087,8 +35088,10 @@ const buildDiagnosticPipeline = (input) => {
|
|
|
35087
35088
|
const compiledOverrides = compileIgnoreOverrides(userConfig);
|
|
35088
35089
|
const textComponentNames = collectStringSet(userConfig?.textComponents);
|
|
35089
35090
|
const rawTextWrapperComponentNames = collectStringSet(userConfig?.rawTextWrapperComponents);
|
|
35091
|
+
const runtimeGlobalNames = collectStringSet(userConfig?.runtimeGlobals);
|
|
35090
35092
|
const hasTextComponents = textComponentNames.size > 0;
|
|
35091
35093
|
const hasRawTextWrappers = rawTextWrapperComponentNames.size > 0;
|
|
35094
|
+
const hasRuntimeGlobals = runtimeGlobalNames.size > 0;
|
|
35092
35095
|
const fileLinesCache = /* @__PURE__ */ new Map();
|
|
35093
35096
|
const fileContextCache = /* @__PURE__ */ new Map();
|
|
35094
35097
|
const libraryFileCache = /* @__PURE__ */ new Map();
|
|
@@ -35140,6 +35143,12 @@ const buildDiagnosticPipeline = (input) => {
|
|
|
35140
35143
|
if (hasRawTextWrappers && isInsideStringOnlyWrapper(lines, diagnostic.line, diagnostic.column, rawTextWrapperComponentNames)) return true;
|
|
35141
35144
|
return false;
|
|
35142
35145
|
};
|
|
35146
|
+
const isJsxNoUndefSuppressedByConfig = (diagnostic) => {
|
|
35147
|
+
if (!hasRuntimeGlobals) return false;
|
|
35148
|
+
if (diagnostic.rule !== "jsx-no-undef") return false;
|
|
35149
|
+
const identifierMatch = JSX_NO_UNDEF_IDENTIFIER_PATTERN.exec(diagnostic.message);
|
|
35150
|
+
return identifierMatch !== null && runtimeGlobalNames.has(identifierMatch[1]);
|
|
35151
|
+
};
|
|
35143
35152
|
return { apply: (diagnostic) => {
|
|
35144
35153
|
if (shouldAutoSuppress(diagnostic)) return null;
|
|
35145
35154
|
let current = diagnostic;
|
|
@@ -35164,6 +35173,7 @@ const buildDiagnosticPipeline = (input) => {
|
|
|
35164
35173
|
if (isFileIgnoredByPatterns(current.filePath, rootDirectory, ignoredFilePatterns)) return null;
|
|
35165
35174
|
if (isDiagnosticIgnoredByOverrides(current, rootDirectory, compiledOverrides)) return null;
|
|
35166
35175
|
if (isRnRawTextSuppressedByConfig(current)) return null;
|
|
35176
|
+
if (isJsxNoUndefSuppressedByConfig(current)) return null;
|
|
35167
35177
|
}
|
|
35168
35178
|
if (respectInlineDisables && current.line > 0) {
|
|
35169
35179
|
const lines = getFileLines(current.filePath);
|
|
@@ -35619,6 +35629,7 @@ const STRING_ARRAY_FIELD_NAMES = [
|
|
|
35619
35629
|
"projects",
|
|
35620
35630
|
"textComponents",
|
|
35621
35631
|
"rawTextWrapperComponents",
|
|
35632
|
+
"runtimeGlobals",
|
|
35622
35633
|
"serverAuthFunctionNames"
|
|
35623
35634
|
];
|
|
35624
35635
|
const SURFACE_CONTROL_FIELD_NAMES = [
|
|
@@ -37275,6 +37286,11 @@ const toCanonicalPath = (filePath) => {
|
|
|
37275
37286
|
};
|
|
37276
37287
|
const DEAD_CODE_PLUGIN = "deslop";
|
|
37277
37288
|
const DEAD_CODE_CATEGORY = "Maintainability";
|
|
37289
|
+
const REACT_DOCTOR_TOOLCHAIN_PACKAGES = new Set([
|
|
37290
|
+
"react-doctor",
|
|
37291
|
+
"eslint-plugin-react-doctor",
|
|
37292
|
+
"oxlint-plugin-react-doctor"
|
|
37293
|
+
]);
|
|
37278
37294
|
const DEAD_CODE_WORKER_SCRIPT = `
|
|
37279
37295
|
const inputChunks = [];
|
|
37280
37296
|
process.stdin.on("data", (chunk) => inputChunks.push(chunk));
|
|
@@ -37580,6 +37596,7 @@ const checkDeadCode = async (options) => {
|
|
|
37580
37596
|
});
|
|
37581
37597
|
}
|
|
37582
37598
|
for (const unusedDependency of result.unusedDependencies) {
|
|
37599
|
+
if (REACT_DOCTOR_TOOLCHAIN_PACKAGES.has(unusedDependency.name)) continue;
|
|
37583
37600
|
const label = unusedDependency.isDevDependency ? "devDependency" : "dependency";
|
|
37584
37601
|
diagnostics.push({
|
|
37585
37602
|
filePath: "package.json",
|
|
@@ -39313,11 +39330,12 @@ const REACT_COMPILER_TITLE = "React Compiler can't optimize this";
|
|
|
39313
39330
|
const REACT_COMPILER_TODO_TITLE = "React Compiler doesn't support this syntax";
|
|
39314
39331
|
const REACT_COMPILER_IMPACT = "This component misses React Compiler's automatic memoization & re-renders more than it should";
|
|
39315
39332
|
const REACT_COMPILER_ACTION = "Rewrite the flagged code so the compiler can optimize it.";
|
|
39333
|
+
const REACT_COMPILER_INCOMPATIBLE_LIBRARY_ACTION = "It's how the library works, not a bug in your code. Memoize values you pass from it into other memoized components, or suppress it with `// react-doctor-disable-next-line react-hooks-js/incompatible-library`.";
|
|
39316
39334
|
const REACT_COMPILER_GENERIC_MESSAGE = `${REACT_COMPILER_IMPACT}. ${REACT_COMPILER_ACTION}`;
|
|
39317
|
-
const buildReactCompilerMessage = (reasonSummary) => {
|
|
39335
|
+
const buildReactCompilerMessage = (reasonSummary, action = REACT_COMPILER_ACTION) => {
|
|
39318
39336
|
const normalizedSummary = reasonSummary.replace(TRAILING_PERIOD_PATTERN, "");
|
|
39319
|
-
if (!normalizedSummary) return
|
|
39320
|
-
return `${REACT_COMPILER_IMPACT}: ${normalizedSummary}. ${
|
|
39337
|
+
if (!normalizedSummary) return `${REACT_COMPILER_IMPACT}. ${action}`;
|
|
39338
|
+
return `${REACT_COMPILER_IMPACT}: ${normalizedSummary}. ${action}`;
|
|
39321
39339
|
};
|
|
39322
39340
|
const PLUGIN_CATEGORY_MAP = {
|
|
39323
39341
|
react: "Bugs",
|
|
@@ -39366,7 +39384,7 @@ const resolveCleanedDiagnostic = (message, help, plugin, rule, project) => {
|
|
|
39366
39384
|
const [reasonSummary = "", ...reasonDetailLines] = bailoutReason.split("\n");
|
|
39367
39385
|
const reasonDetail = reasonDetailLines.join("\n").trim();
|
|
39368
39386
|
return {
|
|
39369
|
-
message: buildReactCompilerMessage(reasonSummary.trim()),
|
|
39387
|
+
message: buildReactCompilerMessage(reasonSummary.trim(), rule === "incompatible-library" ? REACT_COMPILER_INCOMPATIBLE_LIBRARY_ACTION : REACT_COMPILER_ACTION),
|
|
39370
39388
|
help: appendReanimatedSharedValueHint(reasonDetail || help, rule, project)
|
|
39371
39389
|
};
|
|
39372
39390
|
}
|
|
@@ -43041,13 +43059,17 @@ const METRIC = {
|
|
|
43041
43059
|
installWorkflow: "install.workflow",
|
|
43042
43060
|
installAgentHooks: "install.agent_hooks",
|
|
43043
43061
|
installDependency: "install.dependency",
|
|
43062
|
+
ciScaffolded: "ci.scaffolded",
|
|
43063
|
+
ciUpgraded: "ci.upgraded",
|
|
43064
|
+
ciConfigured: "ci.configured",
|
|
43044
43065
|
rulesChanged: "rules.changed",
|
|
43045
43066
|
rulesQueried: "rules.queried",
|
|
43046
43067
|
lspSessionStarted: "lsp.session.started",
|
|
43047
43068
|
lspScanCompleted: "lsp.scan.completed",
|
|
43048
43069
|
lspScanDuration: "lsp.scan.duration",
|
|
43049
43070
|
lspScanDiagnostics: "lsp.scan.diagnostics",
|
|
43050
|
-
aiTrainingWarningShown: "ai.training.warning_shown"
|
|
43071
|
+
aiTrainingWarningShown: "ai.training.warning_shown",
|
|
43072
|
+
jsonOutUsed: "json.out_used"
|
|
43051
43073
|
};
|
|
43052
43074
|
//#endregion
|
|
43053
43075
|
//#region src/cli/utils/to-category-key.ts
|
|
@@ -43364,5 +43386,5 @@ const startLanguageServer = () => {
|
|
|
43364
43386
|
};
|
|
43365
43387
|
//#endregion
|
|
43366
43388
|
export { startLanguageServer };
|
|
43367
|
-
!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]="
|
|
43368
|
-
//# debugId=
|
|
43389
|
+
!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]="5b21d2c0-25a8-52b7-ae5f-f4cc20771996")}catch(e){}}();
|
|
43390
|
+
//# debugId=5b21d2c0-25a8-52b7-ae5f-f4cc20771996
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-doctor",
|
|
3
|
-
"version": "0.5.8-dev.
|
|
3
|
+
"version": "0.5.8-dev.e2393c4",
|
|
4
4
|
"description": "Your agent writes bad React. This catches it",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"accessibility",
|
|
@@ -60,12 +60,13 @@
|
|
|
60
60
|
"magicast": "^0.5.3",
|
|
61
61
|
"oxlint": ">=1.66.0 <1.67.0",
|
|
62
62
|
"prompts": "^2.4.2",
|
|
63
|
-
"typescript": ">=5.0.4 <
|
|
63
|
+
"typescript": ">=5.0.4 <6",
|
|
64
64
|
"vscode-languageserver": "^9.0.1",
|
|
65
65
|
"vscode-languageserver-textdocument": "^1.0.12",
|
|
66
66
|
"vscode-uri": "^3.1.0",
|
|
67
|
+
"yaml": "^2.9.0",
|
|
67
68
|
"deslop-js": "0.5.8",
|
|
68
|
-
"oxlint-plugin-react-doctor": "0.5.8-dev.
|
|
69
|
+
"oxlint-plugin-react-doctor": "0.5.8-dev.e2393c4"
|
|
69
70
|
},
|
|
70
71
|
"devDependencies": {
|
|
71
72
|
"@types/babel__code-frame": "^7.27.0",
|