react-doctor 0.5.6-dev.424d8f9 → 0.5.6-dev.44db3e0
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 +605 -366
- package/dist/index.d.ts +10 -0
- package/dist/index.js +237 -182
- package/dist/lsp.js +255 -204
- package/package.json +2 -2
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]="24b11cb3-4e8c-544c-bacf-6393dd5abd59")}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";
|
|
@@ -19298,6 +19298,7 @@ var JsonReportProjectEntry = class extends Class("JsonReportProjectEntry")({
|
|
|
19298
19298
|
score: Unknown,
|
|
19299
19299
|
skippedChecks: ArraySchema(String$1),
|
|
19300
19300
|
skippedCheckReasons: optional(Record$1(String$1, String$1)),
|
|
19301
|
+
scannedFileCount: optional(Number$1),
|
|
19301
19302
|
elapsedMilliseconds: Number$1
|
|
19302
19303
|
}) {};
|
|
19303
19304
|
/**
|
|
@@ -32724,6 +32725,7 @@ const isLargeMinifiedFile = (absolutePath) => {
|
|
|
32724
32725
|
if (sizeBytes < 2e4) return false;
|
|
32725
32726
|
return isMinifiedSource(absolutePath);
|
|
32726
32727
|
};
|
|
32728
|
+
const isErrnoException = (error) => error instanceof Error && "code" in error;
|
|
32727
32729
|
const IGNORABLE_READDIR_ERROR_CODES = new Set([
|
|
32728
32730
|
"EACCES",
|
|
32729
32731
|
"EPERM",
|
|
@@ -32733,11 +32735,7 @@ const IGNORABLE_READDIR_ERROR_CODES = new Set([
|
|
|
32733
32735
|
"ELOOP",
|
|
32734
32736
|
"ENAMETOOLONG"
|
|
32735
32737
|
]);
|
|
32736
|
-
const isIgnorableReaddirError = (error) =>
|
|
32737
|
-
if (typeof error !== "object" || error === null) return false;
|
|
32738
|
-
const errorCode = error.code;
|
|
32739
|
-
return typeof errorCode === "string" && IGNORABLE_READDIR_ERROR_CODES.has(errorCode);
|
|
32740
|
-
};
|
|
32738
|
+
const isIgnorableReaddirError = (error) => isErrnoException(error) && typeof error.code === "string" && IGNORABLE_READDIR_ERROR_CODES.has(error.code);
|
|
32741
32739
|
const readDirectoryEntries = (directoryPath) => {
|
|
32742
32740
|
try {
|
|
32743
32741
|
return NFS.readdirSync(directoryPath, { withFileTypes: true });
|
|
@@ -32787,7 +32785,7 @@ const readPackageJsonUncached = (packageJsonPath) => {
|
|
|
32787
32785
|
return JSON.parse(NFS.readFileSync(packageJsonPath, "utf-8"));
|
|
32788
32786
|
} catch (error) {
|
|
32789
32787
|
if (error instanceof SyntaxError) return {};
|
|
32790
|
-
if (error
|
|
32788
|
+
if (isErrnoException(error)) {
|
|
32791
32789
|
const { code } = error;
|
|
32792
32790
|
if (code === "EISDIR" || code === "EACCES" || code === "EPERM" || code === "ENOENT") return {};
|
|
32793
32791
|
}
|
|
@@ -33512,17 +33510,13 @@ const isPackageJsonReactNativeAware = (packageJson) => {
|
|
|
33512
33510
|
return false;
|
|
33513
33511
|
};
|
|
33514
33512
|
const hasReactNativeWorkspaceAnywhere = (rootDirectory, rootPackageJson) => someWorkspacePackageJson(rootDirectory, rootPackageJson, isPackageJsonReactNativeAware);
|
|
33515
|
-
const
|
|
33516
|
-
const spec = packageJson.dependencies?.
|
|
33513
|
+
const getDependencySpec = (packageJson, packageName) => {
|
|
33514
|
+
const spec = packageJson.dependencies?.[packageName] ?? packageJson.devDependencies?.[packageName] ?? packageJson.peerDependencies?.[packageName] ?? packageJson.optionalDependencies?.[packageName];
|
|
33517
33515
|
return typeof spec === "string" ? spec : null;
|
|
33518
33516
|
};
|
|
33519
|
-
const findExpoVersion = (rootDirectory, rootPackageJson) => findInWorkspacePackageJsons(rootDirectory, rootPackageJson,
|
|
33517
|
+
const findExpoVersion = (rootDirectory, rootPackageJson) => findInWorkspacePackageJsons(rootDirectory, rootPackageJson, (packageJson) => getDependencySpec(packageJson, "expo"));
|
|
33520
33518
|
const SHOPIFY_FLASH_LIST_PACKAGE_NAME = "@shopify/flash-list";
|
|
33521
|
-
const
|
|
33522
|
-
const spec = packageJson.dependencies?.["@shopify/flash-list"] ?? packageJson.devDependencies?.["@shopify/flash-list"] ?? packageJson.peerDependencies?.["@shopify/flash-list"] ?? packageJson.optionalDependencies?.["@shopify/flash-list"];
|
|
33523
|
-
return typeof spec === "string" ? spec : null;
|
|
33524
|
-
};
|
|
33525
|
-
const findShopifyFlashListVersion = (rootDirectory, rootPackageJson) => findInWorkspacePackageJsons(rootDirectory, rootPackageJson, getShopifyFlashListDependencySpec);
|
|
33519
|
+
const findShopifyFlashListVersion = (rootDirectory, rootPackageJson) => findInWorkspacePackageJsons(rootDirectory, rootPackageJson, (packageJson) => getDependencySpec(packageJson, SHOPIFY_FLASH_LIST_PACKAGE_NAME));
|
|
33526
33520
|
const resolveCatalogBackedDependencyVersion = ({ rootDirectory, rootPackageJson, packageName, version }) => {
|
|
33527
33521
|
if (version === null || !isCatalogReference(version)) return version;
|
|
33528
33522
|
const catalogName = extractCatalogName(version);
|
|
@@ -33534,11 +33528,7 @@ const resolveCatalogBackedDependencyVersion = ({ rootDirectory, rootPackageJson,
|
|
|
33534
33528
|
if (!isFile(monorepoPackageJsonPath)) return version;
|
|
33535
33529
|
return resolveCatalogVersion(readPackageJson(monorepoPackageJsonPath), packageName, monorepoRoot, catalogName) ?? version;
|
|
33536
33530
|
};
|
|
33537
|
-
const
|
|
33538
|
-
const spec = packageJson.dependencies?.next ?? packageJson.devDependencies?.next ?? packageJson.peerDependencies?.next ?? packageJson.optionalDependencies?.next;
|
|
33539
|
-
return typeof spec === "string" ? spec : null;
|
|
33540
|
-
};
|
|
33541
|
-
const findNextjsVersion = (rootDirectory, rootPackageJson) => findInWorkspacePackageJsons(rootDirectory, rootPackageJson, getNextjsDependencySpec);
|
|
33531
|
+
const findNextjsVersion = (rootDirectory, rootPackageJson) => findInWorkspacePackageJsons(rootDirectory, rootPackageJson, (packageJson) => getDependencySpec(packageJson, "next"));
|
|
33542
33532
|
const getPreactVersion = (packageJson) => {
|
|
33543
33533
|
return {
|
|
33544
33534
|
...packageJson.peerDependencies,
|
|
@@ -33620,6 +33610,11 @@ const ES_TARGET_YEAR_BY_NAME = {
|
|
|
33620
33610
|
esnext: 9999
|
|
33621
33611
|
};
|
|
33622
33612
|
/**
|
|
33613
|
+
* tsconfig filenames probed when resolving a project's TypeScript
|
|
33614
|
+
* compiler options — the root config first, then a monorepo base config.
|
|
33615
|
+
*/
|
|
33616
|
+
const TSCONFIG_FILENAMES = ["tsconfig.json", "tsconfig.base.json"];
|
|
33617
|
+
/**
|
|
33623
33618
|
* Project-config files that `StagedFiles.materialize` copies into
|
|
33624
33619
|
* the temp directory alongside staged sources so oxlint resolves
|
|
33625
33620
|
* `tsconfig` / `package.json` / lint configs the same way it would
|
|
@@ -34118,6 +34113,7 @@ const isTailwindAtLeast = (detected, required) => {
|
|
|
34118
34113
|
if (detected.major !== required.major) return detected.major > required.major;
|
|
34119
34114
|
return detected.minor >= required.minor;
|
|
34120
34115
|
};
|
|
34116
|
+
const messageFromUnknown = (error) => error instanceof Error ? error.message : String(error);
|
|
34121
34117
|
var InvalidGlobPatternError = class extends Error {
|
|
34122
34118
|
pattern;
|
|
34123
34119
|
reason;
|
|
@@ -34146,7 +34142,7 @@ const compileGlobPattern = (rawPattern) => {
|
|
|
34146
34142
|
try {
|
|
34147
34143
|
return import_picomatch.default.makeRe(normalizeGlobPattern(rawPattern), PICOMATCH_OPTIONS);
|
|
34148
34144
|
} catch (caughtError) {
|
|
34149
|
-
throw new InvalidGlobPatternError(rawPattern,
|
|
34145
|
+
throw new InvalidGlobPatternError(rawPattern, messageFromUnknown(caughtError));
|
|
34150
34146
|
}
|
|
34151
34147
|
};
|
|
34152
34148
|
const compileGlobPatternsLenient = (patterns, onInvalid) => {
|
|
@@ -34242,115 +34238,6 @@ const buildRuleSeverityControls = (config) => {
|
|
|
34242
34238
|
...config.buckets !== void 0 ? { buckets: config.buckets } : {}
|
|
34243
34239
|
};
|
|
34244
34240
|
};
|
|
34245
|
-
const JSX_OPENER_TAG_PATTERN = /<[A-Za-z][\w.]*/g;
|
|
34246
|
-
const JSX_TAG_NAME_FOLLOW = /[A-Za-z]/;
|
|
34247
|
-
const isOpenerMatchInsideLineComment = (line, openerCharIndex) => {
|
|
34248
|
-
let stringDelimiter = null;
|
|
34249
|
-
for (let charIndex = 0; charIndex < openerCharIndex; charIndex++) {
|
|
34250
|
-
const character = line[charIndex];
|
|
34251
|
-
if (stringDelimiter !== null) {
|
|
34252
|
-
if (character === "\\") {
|
|
34253
|
-
charIndex++;
|
|
34254
|
-
continue;
|
|
34255
|
-
}
|
|
34256
|
-
if (character === stringDelimiter) stringDelimiter = null;
|
|
34257
|
-
continue;
|
|
34258
|
-
}
|
|
34259
|
-
if (character === "\"" || character === "'" || character === "`") {
|
|
34260
|
-
stringDelimiter = character;
|
|
34261
|
-
continue;
|
|
34262
|
-
}
|
|
34263
|
-
if (character === "/" && line[charIndex + 1] === "/") return true;
|
|
34264
|
-
}
|
|
34265
|
-
return false;
|
|
34266
|
-
};
|
|
34267
|
-
const findOpenerTagOnLine = (line) => {
|
|
34268
|
-
for (const match of line.matchAll(JSX_OPENER_TAG_PATTERN)) {
|
|
34269
|
-
if (match.index === void 0) continue;
|
|
34270
|
-
if (!isOpenerMatchInsideLineComment(line, match.index)) return { startCharIndex: match.index + match[0].length };
|
|
34271
|
-
}
|
|
34272
|
-
return null;
|
|
34273
|
-
};
|
|
34274
|
-
const findJsxOpenerSpan = (lines, openerLineIndex) => {
|
|
34275
|
-
const openerLine = lines[openerLineIndex];
|
|
34276
|
-
if (openerLine === void 0) return null;
|
|
34277
|
-
const opener = findOpenerTagOnLine(openerLine);
|
|
34278
|
-
if (!opener) return null;
|
|
34279
|
-
const lookaheadLimit = Math.min(lines.length, openerLineIndex + 32);
|
|
34280
|
-
let braceDepth = 0;
|
|
34281
|
-
let innerAngleDepth = 0;
|
|
34282
|
-
let stringDelimiter = null;
|
|
34283
|
-
for (let lineIndex = openerLineIndex; lineIndex < lookaheadLimit; lineIndex++) {
|
|
34284
|
-
const currentLine = lines[lineIndex];
|
|
34285
|
-
const startCharForLine = lineIndex === openerLineIndex ? opener.startCharIndex : 0;
|
|
34286
|
-
for (let charIndex = startCharForLine; charIndex < currentLine.length; charIndex++) {
|
|
34287
|
-
const character = currentLine[charIndex];
|
|
34288
|
-
if (stringDelimiter !== null) {
|
|
34289
|
-
if (character === "\\") {
|
|
34290
|
-
charIndex++;
|
|
34291
|
-
continue;
|
|
34292
|
-
}
|
|
34293
|
-
if (character === stringDelimiter) stringDelimiter = null;
|
|
34294
|
-
continue;
|
|
34295
|
-
}
|
|
34296
|
-
if (character === "\"" || character === "'" || character === "`") {
|
|
34297
|
-
stringDelimiter = character;
|
|
34298
|
-
continue;
|
|
34299
|
-
}
|
|
34300
|
-
if (character === "{") {
|
|
34301
|
-
braceDepth++;
|
|
34302
|
-
continue;
|
|
34303
|
-
}
|
|
34304
|
-
if (character === "}") {
|
|
34305
|
-
braceDepth--;
|
|
34306
|
-
continue;
|
|
34307
|
-
}
|
|
34308
|
-
if (braceDepth !== 0) continue;
|
|
34309
|
-
if (character === "<") {
|
|
34310
|
-
const followCharacter = currentLine[charIndex + 1];
|
|
34311
|
-
if (followCharacter !== void 0 && JSX_TAG_NAME_FOLLOW.test(followCharacter)) innerAngleDepth++;
|
|
34312
|
-
continue;
|
|
34313
|
-
}
|
|
34314
|
-
if (character !== ">") continue;
|
|
34315
|
-
const previousCharacter = currentLine[charIndex - 1];
|
|
34316
|
-
const nextCharacter = currentLine[charIndex + 1];
|
|
34317
|
-
if (previousCharacter === "=" || nextCharacter === "=") continue;
|
|
34318
|
-
if (innerAngleDepth > 0) {
|
|
34319
|
-
innerAngleDepth--;
|
|
34320
|
-
continue;
|
|
34321
|
-
}
|
|
34322
|
-
return lineIndex;
|
|
34323
|
-
}
|
|
34324
|
-
}
|
|
34325
|
-
return null;
|
|
34326
|
-
};
|
|
34327
|
-
const findEnclosingMultilineJsxOpenerStart = (lines, diagnosticLineIndex) => {
|
|
34328
|
-
for (let candidateIndex = diagnosticLineIndex - 1; candidateIndex >= 0 && diagnosticLineIndex - candidateIndex <= 32; candidateIndex--) {
|
|
34329
|
-
const openerCloseIndex = findJsxOpenerSpan(lines, candidateIndex);
|
|
34330
|
-
if (openerCloseIndex !== null && openerCloseIndex >= diagnosticLineIndex) return candidateIndex;
|
|
34331
|
-
}
|
|
34332
|
-
return null;
|
|
34333
|
-
};
|
|
34334
|
-
const DISABLE_NEXT_LINE_PATTERN = /(?:\/\/|\/\*)\s*react-doctor-disable-next-line\b(?:\s+([^\r\n]*?))?\s*(?:\*\/)?\s*\}?\s*$/;
|
|
34335
|
-
const findStackedDisableCommentsAbove = (lines, anchorIndex) => {
|
|
34336
|
-
const collected = [];
|
|
34337
|
-
let isStillInChain = true;
|
|
34338
|
-
for (let candidateIndex = anchorIndex - 1; candidateIndex >= 0 && anchorIndex - candidateIndex <= 10; candidateIndex--) {
|
|
34339
|
-
const candidateLine = lines[candidateIndex];
|
|
34340
|
-
if (candidateLine === void 0) break;
|
|
34341
|
-
const match = candidateLine.match(DISABLE_NEXT_LINE_PATTERN);
|
|
34342
|
-
if (match) {
|
|
34343
|
-
collected.push({
|
|
34344
|
-
commentLineIndex: candidateIndex,
|
|
34345
|
-
ruleList: match[1],
|
|
34346
|
-
isInChain: isStillInChain
|
|
34347
|
-
});
|
|
34348
|
-
continue;
|
|
34349
|
-
}
|
|
34350
|
-
isStillInChain = false;
|
|
34351
|
-
}
|
|
34352
|
-
return collected;
|
|
34353
|
-
};
|
|
34354
34241
|
const LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY = {
|
|
34355
34242
|
"effect/no-adjust-state-on-prop-change": "react-doctor/no-adjust-state-on-prop-change",
|
|
34356
34243
|
"effect/no-chain-state-updates": "react-doctor/no-chain-state-updates",
|
|
@@ -34475,7 +34362,13 @@ for (const [legacyRuleKey, nativeRuleKey] of Object.entries(LEGACY_RULE_KEY_TO_N
|
|
|
34475
34362
|
}
|
|
34476
34363
|
const getLegacyRuleKeysForNative = (ruleKey) => NATIVE_RULE_KEY_TO_LEGACY_RULE_KEYS.get(ruleKey) ?? [];
|
|
34477
34364
|
const canonicalizeRuleKey = (ruleKey) => LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY[ruleKey] ?? ruleKey;
|
|
34478
|
-
const
|
|
34365
|
+
const isReactDoctorShortIdOf = (bareRuleKey, qualifiedRuleKey) => !bareRuleKey.includes("/") && qualifiedRuleKey === `react-doctor/${bareRuleKey}`;
|
|
34366
|
+
const isSameRuleKey = (candidateRuleKey, targetRuleKey) => {
|
|
34367
|
+
const canonicalCandidate = canonicalizeRuleKey(candidateRuleKey);
|
|
34368
|
+
const canonicalTarget = canonicalizeRuleKey(targetRuleKey);
|
|
34369
|
+
if (canonicalCandidate === canonicalTarget) return true;
|
|
34370
|
+
return isReactDoctorShortIdOf(canonicalCandidate, canonicalTarget) || isReactDoctorShortIdOf(canonicalTarget, canonicalCandidate);
|
|
34371
|
+
};
|
|
34479
34372
|
const getEquivalentRuleKeys = (ruleKey) => {
|
|
34480
34373
|
const nativeRuleKey = canonicalizeRuleKey(ruleKey);
|
|
34481
34374
|
return [nativeRuleKey, ...getLegacyRuleKeysForNative(nativeRuleKey)];
|
|
@@ -34485,12 +34378,182 @@ const stripDescriptionTail = (ruleList) => {
|
|
|
34485
34378
|
if (!descriptionMatch || descriptionMatch.index === void 0) return ruleList;
|
|
34486
34379
|
return ruleList.slice(0, descriptionMatch.index);
|
|
34487
34380
|
};
|
|
34488
|
-
const
|
|
34381
|
+
const tokenizeRuleList = (ruleList) => {
|
|
34489
34382
|
const trimmed = ruleList?.trim();
|
|
34490
|
-
if (!trimmed) return
|
|
34383
|
+
if (!trimmed) return [];
|
|
34491
34384
|
const ruleSection = stripDescriptionTail(trimmed).trim();
|
|
34492
|
-
if (!ruleSection) return
|
|
34493
|
-
return ruleSection.split(/[,\s]+/).
|
|
34385
|
+
if (!ruleSection) return [];
|
|
34386
|
+
return ruleSection.split(/[,\s]+/).map((token) => token.trim()).filter(Boolean);
|
|
34387
|
+
};
|
|
34388
|
+
const FOREIGN_INLINE_DISABLE_PATTERN = /(?:\/\/|\/\*)[ \t]*(eslint|oxlint)-disable-(next-line|line)(?![\w-])([^\r\n]*)/;
|
|
34389
|
+
const FOREIGN_BLOCK_DISABLE_PATTERN = /\/\*[ \t]*(eslint|oxlint)-disable(?![\w-])([^*\r\n]*)/;
|
|
34390
|
+
const FOREIGN_BLOCK_ENABLE_PATTERN = /\/\*[ \t]*(?:eslint|oxlint)-enable(?![\w-])([^*\r\n]*)/;
|
|
34391
|
+
const buildHint = (tool, token, ruleId) => `oxlint matches plugin rules only by their full name, so \`${token}\` in your ${tool}-disable comment does not silence \`${ruleId}\` — change it to \`${ruleId}\`.`;
|
|
34392
|
+
const tokenMisnamesRule = (token, ruleId) => token !== ruleId && isSameRuleKey(token, ruleId);
|
|
34393
|
+
const detectInlineNearMiss = (lines, diagnosticLineIndex, ruleId) => {
|
|
34394
|
+
const candidates = [{
|
|
34395
|
+
line: lines[diagnosticLineIndex],
|
|
34396
|
+
requiredScope: "line"
|
|
34397
|
+
}, {
|
|
34398
|
+
line: lines[diagnosticLineIndex - 1],
|
|
34399
|
+
requiredScope: "next-line"
|
|
34400
|
+
}];
|
|
34401
|
+
for (const { line, requiredScope } of candidates) {
|
|
34402
|
+
const match = line?.match(FOREIGN_INLINE_DISABLE_PATTERN);
|
|
34403
|
+
if (!match) continue;
|
|
34404
|
+
const [, tool, scope, ruleList] = match;
|
|
34405
|
+
if (scope !== requiredScope) continue;
|
|
34406
|
+
const tokens = tokenizeRuleList(ruleList);
|
|
34407
|
+
if (tokens.includes(ruleId)) continue;
|
|
34408
|
+
for (const token of tokens) if (tokenMisnamesRule(token, ruleId)) return buildHint(tool, token, ruleId);
|
|
34409
|
+
}
|
|
34410
|
+
return null;
|
|
34411
|
+
};
|
|
34412
|
+
const detectBlockNearMiss = (lines, diagnosticLineIndex, ruleId) => {
|
|
34413
|
+
let openMisname = null;
|
|
34414
|
+
const lastLineIndex = Math.min(diagnosticLineIndex, lines.length - 1);
|
|
34415
|
+
for (let lineIndex = 0; lineIndex <= lastLineIndex; lineIndex++) {
|
|
34416
|
+
const line = lines[lineIndex];
|
|
34417
|
+
if (line === void 0 || !line.includes("-disable") && !line.includes("-enable")) continue;
|
|
34418
|
+
const disableMatch = line.match(FOREIGN_BLOCK_DISABLE_PATTERN);
|
|
34419
|
+
if (disableMatch) {
|
|
34420
|
+
const [, tool, ruleList] = disableMatch;
|
|
34421
|
+
const tokens = tokenizeRuleList(ruleList);
|
|
34422
|
+
if (tokens.includes(ruleId)) openMisname = null;
|
|
34423
|
+
else {
|
|
34424
|
+
const misnamed = tokens.find((token) => tokenMisnamesRule(token, ruleId));
|
|
34425
|
+
if (misnamed) openMisname = {
|
|
34426
|
+
tool,
|
|
34427
|
+
token: misnamed
|
|
34428
|
+
};
|
|
34429
|
+
}
|
|
34430
|
+
continue;
|
|
34431
|
+
}
|
|
34432
|
+
const enableMatch = line.match(FOREIGN_BLOCK_ENABLE_PATTERN);
|
|
34433
|
+
if (enableMatch) {
|
|
34434
|
+
const enabledRules = tokenizeRuleList(enableMatch[1]);
|
|
34435
|
+
if (enabledRules.length === 0 || enabledRules.some((rule) => isSameRuleKey(rule, ruleId))) openMisname = null;
|
|
34436
|
+
}
|
|
34437
|
+
}
|
|
34438
|
+
return openMisname ? buildHint(openMisname.tool, openMisname.token, ruleId) : null;
|
|
34439
|
+
};
|
|
34440
|
+
const detectForeignDisableNearMiss = (lines, diagnosticLineIndex, ruleId) => {
|
|
34441
|
+
if (!ruleId.startsWith("react-doctor/")) return null;
|
|
34442
|
+
return detectInlineNearMiss(lines, diagnosticLineIndex, ruleId) ?? detectBlockNearMiss(lines, diagnosticLineIndex, ruleId);
|
|
34443
|
+
};
|
|
34444
|
+
const JSX_OPENER_TAG_PATTERN = /<[A-Za-z][\w.]*/g;
|
|
34445
|
+
const JSX_TAG_NAME_FOLLOW = /[A-Za-z]/;
|
|
34446
|
+
const isOpenerMatchInsideLineComment = (line, openerCharIndex) => {
|
|
34447
|
+
let stringDelimiter = null;
|
|
34448
|
+
for (let charIndex = 0; charIndex < openerCharIndex; charIndex++) {
|
|
34449
|
+
const character = line[charIndex];
|
|
34450
|
+
if (stringDelimiter !== null) {
|
|
34451
|
+
if (character === "\\") {
|
|
34452
|
+
charIndex++;
|
|
34453
|
+
continue;
|
|
34454
|
+
}
|
|
34455
|
+
if (character === stringDelimiter) stringDelimiter = null;
|
|
34456
|
+
continue;
|
|
34457
|
+
}
|
|
34458
|
+
if (character === "\"" || character === "'" || character === "`") {
|
|
34459
|
+
stringDelimiter = character;
|
|
34460
|
+
continue;
|
|
34461
|
+
}
|
|
34462
|
+
if (character === "/" && line[charIndex + 1] === "/") return true;
|
|
34463
|
+
}
|
|
34464
|
+
return false;
|
|
34465
|
+
};
|
|
34466
|
+
const findOpenerTagOnLine = (line) => {
|
|
34467
|
+
for (const match of line.matchAll(JSX_OPENER_TAG_PATTERN)) {
|
|
34468
|
+
if (match.index === void 0) continue;
|
|
34469
|
+
if (!isOpenerMatchInsideLineComment(line, match.index)) return { startCharIndex: match.index + match[0].length };
|
|
34470
|
+
}
|
|
34471
|
+
return null;
|
|
34472
|
+
};
|
|
34473
|
+
const findJsxOpenerSpan = (lines, openerLineIndex) => {
|
|
34474
|
+
const openerLine = lines[openerLineIndex];
|
|
34475
|
+
if (openerLine === void 0) return null;
|
|
34476
|
+
const opener = findOpenerTagOnLine(openerLine);
|
|
34477
|
+
if (!opener) return null;
|
|
34478
|
+
const lookaheadLimit = Math.min(lines.length, openerLineIndex + 32);
|
|
34479
|
+
let braceDepth = 0;
|
|
34480
|
+
let innerAngleDepth = 0;
|
|
34481
|
+
let stringDelimiter = null;
|
|
34482
|
+
for (let lineIndex = openerLineIndex; lineIndex < lookaheadLimit; lineIndex++) {
|
|
34483
|
+
const currentLine = lines[lineIndex];
|
|
34484
|
+
const startCharForLine = lineIndex === openerLineIndex ? opener.startCharIndex : 0;
|
|
34485
|
+
for (let charIndex = startCharForLine; charIndex < currentLine.length; charIndex++) {
|
|
34486
|
+
const character = currentLine[charIndex];
|
|
34487
|
+
if (stringDelimiter !== null) {
|
|
34488
|
+
if (character === "\\") {
|
|
34489
|
+
charIndex++;
|
|
34490
|
+
continue;
|
|
34491
|
+
}
|
|
34492
|
+
if (character === stringDelimiter) stringDelimiter = null;
|
|
34493
|
+
continue;
|
|
34494
|
+
}
|
|
34495
|
+
if (character === "\"" || character === "'" || character === "`") {
|
|
34496
|
+
stringDelimiter = character;
|
|
34497
|
+
continue;
|
|
34498
|
+
}
|
|
34499
|
+
if (character === "{") {
|
|
34500
|
+
braceDepth++;
|
|
34501
|
+
continue;
|
|
34502
|
+
}
|
|
34503
|
+
if (character === "}") {
|
|
34504
|
+
braceDepth--;
|
|
34505
|
+
continue;
|
|
34506
|
+
}
|
|
34507
|
+
if (braceDepth !== 0) continue;
|
|
34508
|
+
if (character === "<") {
|
|
34509
|
+
const followCharacter = currentLine[charIndex + 1];
|
|
34510
|
+
if (followCharacter !== void 0 && JSX_TAG_NAME_FOLLOW.test(followCharacter)) innerAngleDepth++;
|
|
34511
|
+
continue;
|
|
34512
|
+
}
|
|
34513
|
+
if (character !== ">") continue;
|
|
34514
|
+
const previousCharacter = currentLine[charIndex - 1];
|
|
34515
|
+
const nextCharacter = currentLine[charIndex + 1];
|
|
34516
|
+
if (previousCharacter === "=" || nextCharacter === "=") continue;
|
|
34517
|
+
if (innerAngleDepth > 0) {
|
|
34518
|
+
innerAngleDepth--;
|
|
34519
|
+
continue;
|
|
34520
|
+
}
|
|
34521
|
+
return lineIndex;
|
|
34522
|
+
}
|
|
34523
|
+
}
|
|
34524
|
+
return null;
|
|
34525
|
+
};
|
|
34526
|
+
const findEnclosingMultilineJsxOpenerStart = (lines, diagnosticLineIndex) => {
|
|
34527
|
+
for (let candidateIndex = diagnosticLineIndex - 1; candidateIndex >= 0 && diagnosticLineIndex - candidateIndex <= 32; candidateIndex--) {
|
|
34528
|
+
const openerCloseIndex = findJsxOpenerSpan(lines, candidateIndex);
|
|
34529
|
+
if (openerCloseIndex !== null && openerCloseIndex >= diagnosticLineIndex) return candidateIndex;
|
|
34530
|
+
}
|
|
34531
|
+
return null;
|
|
34532
|
+
};
|
|
34533
|
+
const DISABLE_NEXT_LINE_PATTERN = /(?:\/\/|\/\*)\s*react-doctor-disable-next-line\b(?:\s+([^\r\n]*?))?\s*(?:\*\/)?\s*\}?\s*$/;
|
|
34534
|
+
const findStackedDisableCommentsAbove = (lines, anchorIndex) => {
|
|
34535
|
+
const collected = [];
|
|
34536
|
+
let isStillInChain = true;
|
|
34537
|
+
for (let candidateIndex = anchorIndex - 1; candidateIndex >= 0 && anchorIndex - candidateIndex <= 10; candidateIndex--) {
|
|
34538
|
+
const candidateLine = lines[candidateIndex];
|
|
34539
|
+
if (candidateLine === void 0) break;
|
|
34540
|
+
const match = candidateLine.match(DISABLE_NEXT_LINE_PATTERN);
|
|
34541
|
+
if (match) {
|
|
34542
|
+
collected.push({
|
|
34543
|
+
commentLineIndex: candidateIndex,
|
|
34544
|
+
ruleList: match[1],
|
|
34545
|
+
isInChain: isStillInChain
|
|
34546
|
+
});
|
|
34547
|
+
continue;
|
|
34548
|
+
}
|
|
34549
|
+
isStillInChain = false;
|
|
34550
|
+
}
|
|
34551
|
+
return collected;
|
|
34552
|
+
};
|
|
34553
|
+
const isRuleListedInComment = (ruleList, ruleId) => {
|
|
34554
|
+
const tokens = tokenizeRuleList(ruleList);
|
|
34555
|
+
if (tokens.length === 0) return true;
|
|
34556
|
+
return tokens.some((token) => isSameRuleKey(token, ruleId));
|
|
34494
34557
|
};
|
|
34495
34558
|
const DISABLE_LINE_PATTERN = /(?:\/\/|\/\*)\s*react-doctor-disable-line\b(?:\s+([^\r\n]*?))?\s*(?:\*\/)?\s*\}?\s*$/;
|
|
34496
34559
|
const formatLineGap = (gapLineCount) => `${gapLineCount} line${gapLineCount === 1 ? "" : "s"}`;
|
|
@@ -34534,7 +34597,7 @@ const evaluateSuppression = (lines, diagnosticLineIndex, ruleId) => {
|
|
|
34534
34597
|
};
|
|
34535
34598
|
return {
|
|
34536
34599
|
isSuppressed: false,
|
|
34537
|
-
nearMissHint: classifyFromComments([directComments, openerComments], diagnosticLineIndex, ruleId)
|
|
34600
|
+
nearMissHint: classifyFromComments([directComments, openerComments], diagnosticLineIndex, ruleId) ?? detectForeignDisableNearMiss(lines, diagnosticLineIndex, ruleId)
|
|
34538
34601
|
};
|
|
34539
34602
|
};
|
|
34540
34603
|
/**
|
|
@@ -35328,7 +35391,6 @@ const PACKAGE_JSON_FILENAME = "package.json";
|
|
|
35328
35391
|
const PACKAGE_JSON_CONFIG_KEY = "reactDoctor";
|
|
35329
35392
|
const LEGACY_CONFIG_FILENAME = "react-doctor.config.json";
|
|
35330
35393
|
const jiti = createJiti(import.meta.url);
|
|
35331
|
-
const formatError = (error) => error instanceof Error ? error.message : String(error);
|
|
35332
35394
|
const importDefaultExport = async (jitiInstance, filePath) => {
|
|
35333
35395
|
const imported = await jitiInstance.import(filePath);
|
|
35334
35396
|
return imported?.default ?? imported;
|
|
@@ -35360,7 +35422,7 @@ const loadModuleConfig = async (filePath) => {
|
|
|
35360
35422
|
try {
|
|
35361
35423
|
return await importDefaultExport(aliasJiti, filePath);
|
|
35362
35424
|
} catch (retryError) {
|
|
35363
|
-
throw new Error(`${
|
|
35425
|
+
throw new Error(`${messageFromUnknown(error)} (retry with ${SELF_PACKAGE_IMPORT_SPECIFIER} aliased to the running react-doctor package also failed: ${messageFromUnknown(retryError)})`, { cause: retryError });
|
|
35364
35426
|
}
|
|
35365
35427
|
}
|
|
35366
35428
|
};
|
|
@@ -35409,7 +35471,7 @@ const loadLegacyConfig = (directory) => {
|
|
|
35409
35471
|
}
|
|
35410
35472
|
warn(`${LEGACY_CONFIG_FILENAME} must contain an object, ignoring.`);
|
|
35411
35473
|
} catch (error) {
|
|
35412
|
-
warn(`Failed to load ${LEGACY_CONFIG_FILENAME}: ${
|
|
35474
|
+
warn(`Failed to load ${LEGACY_CONFIG_FILENAME}: ${messageFromUnknown(error)}`);
|
|
35413
35475
|
}
|
|
35414
35476
|
return {
|
|
35415
35477
|
status: "invalid",
|
|
@@ -35436,7 +35498,7 @@ const loadConfigFromDirectory = async (directory) => {
|
|
|
35436
35498
|
warn(`${CONFIG_BASENAME}.${extension} must export an object, ignoring.`);
|
|
35437
35499
|
sawBrokenConfigFile = true;
|
|
35438
35500
|
} catch (error) {
|
|
35439
|
-
warn(`Failed to load ${CONFIG_BASENAME}.${extension}: ${
|
|
35501
|
+
warn(`Failed to load ${CONFIG_BASENAME}.${extension}: ${messageFromUnknown(error)}`);
|
|
35440
35502
|
sawBrokenConfigFile = true;
|
|
35441
35503
|
}
|
|
35442
35504
|
}
|
|
@@ -36472,15 +36534,10 @@ const buildCapabilities = (project) => {
|
|
|
36472
36534
|
}
|
|
36473
36535
|
if (project.tailwindVersion !== null) {
|
|
36474
36536
|
capabilities.add("tailwind");
|
|
36475
|
-
|
|
36476
|
-
if (isTailwindAtLeast(tailwind, {
|
|
36537
|
+
if (isTailwindAtLeast(parseTailwindMajorMinor(project.tailwindVersion), {
|
|
36477
36538
|
major: 3,
|
|
36478
36539
|
minor: 4
|
|
36479
36540
|
})) capabilities.add("tailwind:3.4");
|
|
36480
|
-
if (tailwind !== null && isTailwindAtLeast(tailwind, {
|
|
36481
|
-
major: 4,
|
|
36482
|
-
minor: 0
|
|
36483
|
-
})) capabilities.add("tailwind:4");
|
|
36484
36541
|
}
|
|
36485
36542
|
if (project.zodVersion !== null) {
|
|
36486
36543
|
capabilities.add("zod");
|
|
@@ -36669,7 +36726,7 @@ const readIgnoreFile = (filePath) => {
|
|
|
36669
36726
|
try {
|
|
36670
36727
|
content = NFS.readFileSync(filePath, "utf-8");
|
|
36671
36728
|
} catch (error) {
|
|
36672
|
-
const errnoCode = error
|
|
36729
|
+
const errnoCode = isErrnoException(error) ? error.code : void 0;
|
|
36673
36730
|
if (errnoCode && errnoCode !== "ENOENT") runSync(warn$1(`Could not read ignore file ${filePath}: ${errnoCode}`));
|
|
36674
36731
|
return [];
|
|
36675
36732
|
}
|
|
@@ -36710,8 +36767,8 @@ const collectIgnorePatterns = (rootDirectory) => {
|
|
|
36710
36767
|
cachedPatternsByRoot.set(rootDirectory, patterns);
|
|
36711
36768
|
return patterns;
|
|
36712
36769
|
};
|
|
36770
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36713
36771
|
const KNIP_JSON_FILENAME = "knip.json";
|
|
36714
|
-
const isRecord$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36715
36772
|
const readJsonFileSafe = (filePath) => {
|
|
36716
36773
|
let rawContents;
|
|
36717
36774
|
try {
|
|
@@ -36727,10 +36784,10 @@ const readJsonFileSafe = (filePath) => {
|
|
|
36727
36784
|
};
|
|
36728
36785
|
const readKnipConfig = (rootDirectory) => {
|
|
36729
36786
|
const knipJson = readJsonFileSafe(path.join(rootDirectory, KNIP_JSON_FILENAME));
|
|
36730
|
-
if (isRecord
|
|
36787
|
+
if (isRecord(knipJson)) return knipJson;
|
|
36731
36788
|
const packageJson = readJsonFileSafe(path.join(rootDirectory, "package.json"));
|
|
36732
|
-
const packageKnipConfig = isRecord
|
|
36733
|
-
return isRecord
|
|
36789
|
+
const packageKnipConfig = isRecord(packageJson) ? packageJson.knip : null;
|
|
36790
|
+
return isRecord(packageKnipConfig) ? packageKnipConfig : null;
|
|
36734
36791
|
};
|
|
36735
36792
|
const normalizePatternList = (value) => {
|
|
36736
36793
|
if (typeof value === "string" && value.length > 0) return [value];
|
|
@@ -36742,10 +36799,10 @@ const prefixWorkspacePatterns = (workspacePattern, patterns) => {
|
|
|
36742
36799
|
return patterns.map((pattern) => pattern.startsWith("!") ? `!${normalizedWorkspacePattern}/${pattern.slice(1)}` : `${normalizedWorkspacePattern}/${pattern}`);
|
|
36743
36800
|
};
|
|
36744
36801
|
const collectKnipWorkspacePatterns = (workspaces, settingName) => {
|
|
36745
|
-
if (!isRecord
|
|
36802
|
+
if (!isRecord(workspaces)) return [];
|
|
36746
36803
|
const patterns = [];
|
|
36747
36804
|
for (const [workspacePattern, workspaceConfig] of Object.entries(workspaces)) {
|
|
36748
|
-
if (!isRecord
|
|
36805
|
+
if (!isRecord(workspaceConfig)) continue;
|
|
36749
36806
|
patterns.push(...prefixWorkspacePatterns(workspacePattern, normalizePatternList(workspaceConfig[settingName])));
|
|
36750
36807
|
}
|
|
36751
36808
|
return patterns;
|
|
@@ -36790,8 +36847,6 @@ const toCanonicalPath = (filePath) => {
|
|
|
36790
36847
|
};
|
|
36791
36848
|
const DEAD_CODE_PLUGIN = "deslop";
|
|
36792
36849
|
const DEAD_CODE_CATEGORY = "Maintainability";
|
|
36793
|
-
const TSCONFIG_FILENAMES$1 = ["tsconfig.json", "tsconfig.base.json"];
|
|
36794
|
-
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36795
36850
|
const DEAD_CODE_WORKER_SCRIPT = `
|
|
36796
36851
|
const inputChunks = [];
|
|
36797
36852
|
process.stdin.on("data", (chunk) => inputChunks.push(chunk));
|
|
@@ -36849,7 +36904,7 @@ process.stdin.on("end", () => {
|
|
|
36849
36904
|
});
|
|
36850
36905
|
`;
|
|
36851
36906
|
const resolveTsConfigPath = (rootDirectory) => {
|
|
36852
|
-
for (const filename of TSCONFIG_FILENAMES
|
|
36907
|
+
for (const filename of TSCONFIG_FILENAMES) {
|
|
36853
36908
|
const candidate = Path.join(rootDirectory, filename);
|
|
36854
36909
|
if (NFS.existsSync(candidate)) return candidate;
|
|
36855
36910
|
}
|
|
@@ -37230,15 +37285,13 @@ var DeadCode = class DeadCode extends Service()("react-doctor/DeadCode") {
|
|
|
37230
37285
|
})()) }));
|
|
37231
37286
|
static layerOf = (diagnostics) => succeed$3(DeadCode, DeadCode.of({ run: () => fromIterable$1(diagnostics) }));
|
|
37232
37287
|
};
|
|
37233
|
-
const createNodeReadFileLinesSync = (rootDirectory) => {
|
|
37234
|
-
|
|
37235
|
-
|
|
37236
|
-
|
|
37237
|
-
|
|
37238
|
-
|
|
37239
|
-
|
|
37240
|
-
}
|
|
37241
|
-
};
|
|
37288
|
+
const createNodeReadFileLinesSync = (rootDirectory) => (filePath) => {
|
|
37289
|
+
const absolutePath = Path.isAbsolute(filePath) ? filePath : Path.join(rootDirectory, filePath);
|
|
37290
|
+
try {
|
|
37291
|
+
return NFS.readFileSync(absolutePath, "utf-8").split("\n");
|
|
37292
|
+
} catch {
|
|
37293
|
+
return null;
|
|
37294
|
+
}
|
|
37242
37295
|
};
|
|
37243
37296
|
var Files = class Files extends Service()("react-doctor/Files") {
|
|
37244
37297
|
static layerNode = succeed$3(Files, Files.of({
|
|
@@ -37449,7 +37502,10 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
37449
37502
|
directory: input.directory,
|
|
37450
37503
|
cause
|
|
37451
37504
|
}) });
|
|
37452
|
-
})
|
|
37505
|
+
}), withSpan("git.exec", { attributes: {
|
|
37506
|
+
"git.command": input.command,
|
|
37507
|
+
"git.subcommand": input.args[0] ?? ""
|
|
37508
|
+
} }));
|
|
37453
37509
|
const runGit = (directory, args) => runCommand({
|
|
37454
37510
|
command: "git",
|
|
37455
37511
|
args,
|
|
@@ -37477,7 +37533,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
37477
37533
|
]);
|
|
37478
37534
|
if (candidates.status !== 0) return null;
|
|
37479
37535
|
return trimOrNull(candidates.stdout.split("\n")[0] ?? "");
|
|
37480
|
-
});
|
|
37536
|
+
}).pipe(withSpan("Git.defaultBranch"));
|
|
37481
37537
|
const branchExists = (directory, branch) => runGit(directory, [
|
|
37482
37538
|
"rev-parse",
|
|
37483
37539
|
"--verify",
|
|
@@ -37524,7 +37580,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
37524
37580
|
const result = resultOption.value;
|
|
37525
37581
|
if (result.status !== 0) return null;
|
|
37526
37582
|
return parseGithubViewerPermission(result.stdout);
|
|
37527
|
-
}).pipe(catch_$1(() => succeed$2(null)));
|
|
37583
|
+
}).pipe(catch_$1(() => succeed$2(null)), withSpan("Git.githubViewerPermission"));
|
|
37528
37584
|
/**
|
|
37529
37585
|
* Resolves a `--diff A..B` / `A...B` commit range into a changed-file
|
|
37530
37586
|
* selection. Each endpoint is validated with `isSafeGitRevision`
|
|
@@ -37638,7 +37694,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
37638
37694
|
changedFiles: splitNullSeparated(diff.stdout),
|
|
37639
37695
|
isCurrentChanges: false
|
|
37640
37696
|
};
|
|
37641
|
-
}),
|
|
37697
|
+
}).pipe(withSpan("Git.diffSelection")),
|
|
37642
37698
|
stagedFilePaths: (directory) => runGit(directory, [
|
|
37643
37699
|
"diff",
|
|
37644
37700
|
"--cached",
|
|
@@ -37680,7 +37736,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
37680
37736
|
status: result.status,
|
|
37681
37737
|
stdout: result.stdout
|
|
37682
37738
|
};
|
|
37683
|
-
}),
|
|
37739
|
+
}).pipe(withSpan("Git.grep")),
|
|
37684
37740
|
changedLineRanges: ({ directory, baseRef, cached, files }) => gen(function* () {
|
|
37685
37741
|
if (files.length === 0) return [];
|
|
37686
37742
|
if (baseRef !== void 0 && !isSafeGitRevision(baseRef)) return null;
|
|
@@ -37696,7 +37752,7 @@ var Git = class Git extends Service()("react-doctor/Git") {
|
|
|
37696
37752
|
]);
|
|
37697
37753
|
if (result.status !== 0) return null;
|
|
37698
37754
|
return parseChangedLineRanges(result.stdout);
|
|
37699
|
-
})
|
|
37755
|
+
}).pipe(withSpan("Git.changedLineRanges"))
|
|
37700
37756
|
});
|
|
37701
37757
|
})).pipe(provide$2(layer$2.pipe(provide$2(mergeAll$1(layer$1, layer)))));
|
|
37702
37758
|
/**
|
|
@@ -37911,7 +37967,7 @@ const neutralizeDisableDirectives = async (rootDirectory, includePaths) => {
|
|
|
37911
37967
|
for (const [absolutePath, originalContent] of originalContents) try {
|
|
37912
37968
|
NFS.writeFileSync(absolutePath, originalContent);
|
|
37913
37969
|
} catch (error) {
|
|
37914
|
-
process.stderr.write(`[react-doctor] Failed to restore inline disable directives in ${absolutePath}: ${
|
|
37970
|
+
process.stderr.write(`[react-doctor] Failed to restore inline disable directives in ${absolutePath}: ${messageFromUnknown(error)}\n[react-doctor] Run: git checkout -- ${absolutePath}\n`);
|
|
37915
37971
|
}
|
|
37916
37972
|
};
|
|
37917
37973
|
const onExit = () => restore();
|
|
@@ -38017,7 +38073,7 @@ const resolveUserPlugin = (spec, configSourceDirectory) => {
|
|
|
38017
38073
|
try {
|
|
38018
38074
|
resolvedSpecifier = isRelative ? Path.resolve(configSourceDirectory, spec) : candidateRequire.resolve(spec);
|
|
38019
38075
|
} catch (error) {
|
|
38020
|
-
warnConfigIssue(`config.plugins entry "${spec}" could not be resolved from ${configSourceDirectory}: ${
|
|
38076
|
+
warnConfigIssue(`config.plugins entry "${spec}" could not be resolved from ${configSourceDirectory}: ${messageFromUnknown(error)}`);
|
|
38021
38077
|
return null;
|
|
38022
38078
|
}
|
|
38023
38079
|
const { name, ruleNames } = readPluginShape(resolvedSpecifier, (target) => candidateRequire(target));
|
|
@@ -38150,7 +38206,6 @@ const resolveOxlintBinary = () => {
|
|
|
38150
38206
|
return Path.join(oxlintPackageDirectory, "bin", "oxlint");
|
|
38151
38207
|
};
|
|
38152
38208
|
const resolvePluginPath = () => esmRequire.resolve("oxlint-plugin-react-doctor");
|
|
38153
|
-
const TSCONFIG_FILENAMES = ["tsconfig.json", "tsconfig.base.json"];
|
|
38154
38209
|
const resolveTsConfigRelativePath = (rootDirectory) => {
|
|
38155
38210
|
for (const filename of TSCONFIG_FILENAMES) if (NFS.existsSync(Path.join(rootDirectory, filename))) return `./${filename}`;
|
|
38156
38211
|
return null;
|
|
@@ -38522,7 +38577,7 @@ const scopeContainsNonImportBinding = (node, scopeNode, identifierName) => {
|
|
|
38522
38577
|
const isIdentifierShadowedByLocalBinding = (identifier, sourceFile) => {
|
|
38523
38578
|
let currentNode = identifier.parent;
|
|
38524
38579
|
while (currentNode) {
|
|
38525
|
-
if (
|
|
38580
|
+
if (isScopeBoundary(currentNode)) {
|
|
38526
38581
|
if (scopeContainsNonImportBinding(currentNode, currentNode, identifier.text)) return true;
|
|
38527
38582
|
}
|
|
38528
38583
|
if (currentNode === sourceFile) return false;
|
|
@@ -38613,11 +38668,10 @@ const findResolutionInScope = (scopeNode, identifierName, reactImportBindings, s
|
|
|
38613
38668
|
});
|
|
38614
38669
|
return resolution;
|
|
38615
38670
|
};
|
|
38616
|
-
const isScopeNode = isScopeBoundary;
|
|
38617
38671
|
const resolveIdentifierBinding = (identifier, reactImportBindings, sourceFile, visitedDeclarations = /* @__PURE__ */ new Set()) => {
|
|
38618
38672
|
let currentNode = identifier.parent;
|
|
38619
38673
|
while (currentNode) {
|
|
38620
|
-
if (
|
|
38674
|
+
if (isScopeBoundary(currentNode)) {
|
|
38621
38675
|
const resolution = findResolutionInScope(currentNode, identifier.text, reactImportBindings, sourceFile, visitedDeclarations);
|
|
38622
38676
|
if (resolution) return resolution;
|
|
38623
38677
|
}
|
|
@@ -38865,7 +38919,7 @@ const spawnOxlint = (args, rootDirectory, nodeBinaryPath, spawnTimeoutMs = OXLIN
|
|
|
38865
38919
|
child.kill("SIGKILL");
|
|
38866
38920
|
reject(new ReactDoctorError({ reason: new OxlintBatchExceeded({
|
|
38867
38921
|
kind: "timeout",
|
|
38868
|
-
detail: `${spawnTimeoutMs /
|
|
38922
|
+
detail: `${spawnTimeoutMs / MILLISECONDS_PER_SECOND}s budget exceeded`
|
|
38869
38923
|
}) }));
|
|
38870
38924
|
}, spawnTimeoutMs);
|
|
38871
38925
|
timeoutHandle.unref?.();
|
|
@@ -39987,7 +40041,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
|
|
|
39987
40041
|
}))))))));
|
|
39988
40042
|
const deadCodeFailureState = yield* get$2(deadCodeFailure);
|
|
39989
40043
|
const scanElapsedMilliseconds = Date.now() - scanStartTime;
|
|
39990
|
-
const scanElapsedSeconds = (scanElapsedMilliseconds /
|
|
40044
|
+
const scanElapsedSeconds = (scanElapsedMilliseconds / MILLISECONDS_PER_SECOND).toFixed(1);
|
|
39991
40045
|
if (!lintFailureState.didFail) if (deadCodeFailureState.didFail) yield* scanProgress.fail(DEAD_CODE_FAIL_TEXT);
|
|
39992
40046
|
else if (input.suppressScanSummary) yield* scanProgress.stop();
|
|
39993
40047
|
else yield* scanProgress.succeed(`Scanned ${scannedFilesLabel} in ${scanElapsedSeconds}s${workerCountSuffix}`);
|
|
@@ -40201,7 +40255,7 @@ const materializeSourceTree = (input) => gen(function* () {
|
|
|
40201
40255
|
static layerNode = effect(StagedFiles, gen(function* () {
|
|
40202
40256
|
const git = yield* Git;
|
|
40203
40257
|
return StagedFiles.of({
|
|
40204
|
-
discoverSourceFiles: (directory) => git.stagedFilePaths(directory).pipe(map$3((entries) => entries.filter(isLintableSourceFile))),
|
|
40258
|
+
discoverSourceFiles: (directory) => git.stagedFilePaths(directory).pipe(map$3((entries) => entries.filter(isLintableSourceFile)), withSpan("StagedFiles.discoverSourceFiles")),
|
|
40205
40259
|
materialize: ({ directory, stagedFiles, tempDirectory }) => materializeSourceTree({
|
|
40206
40260
|
directory,
|
|
40207
40261
|
files: stagedFiles,
|
|
@@ -40211,7 +40265,7 @@ const materializeSourceTree = (input) => gen(function* () {
|
|
|
40211
40265
|
tempDirectory: tree.tempDirectory,
|
|
40212
40266
|
stagedFiles: tree.materializedFiles,
|
|
40213
40267
|
cleanup: tree.cleanup
|
|
40214
|
-
})))
|
|
40268
|
+
})), withSpan("StagedFiles.materialize"))
|
|
40215
40269
|
});
|
|
40216
40270
|
}));
|
|
40217
40271
|
/**
|
|
@@ -40343,6 +40397,7 @@ const buildJsonReport = (input) => {
|
|
|
40343
40397
|
score: result.score,
|
|
40344
40398
|
skippedChecks: result.skippedChecks,
|
|
40345
40399
|
...result.skippedCheckReasons ? { skippedCheckReasons: result.skippedCheckReasons } : {},
|
|
40400
|
+
...typeof result.scannedFileCount === "number" ? { scannedFileCount: result.scannedFileCount } : {},
|
|
40346
40401
|
elapsedMilliseconds: result.elapsedMilliseconds
|
|
40347
40402
|
}));
|
|
40348
40403
|
const flattenedDiagnostics = projects.flatMap((entry) => entry.diagnostics);
|
|
@@ -40609,4 +40664,4 @@ const toJsonReport = (result, options) => buildJsonReport({
|
|
|
40609
40664
|
export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
|
|
40610
40665
|
|
|
40611
40666
|
//# sourceMappingURL=index.js.map
|
|
40612
|
-
//# debugId=
|
|
40667
|
+
//# debugId=24b11cb3-4e8c-544c-bacf-6393dd5abd59
|