react-doctor 0.5.6-dev.44db3e0 → 0.5.6-dev.4e06b2a
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 +120 -187
- package/dist/index.js +117 -184
- package/dist/lsp.js +117 -184
- package/package.json +2 -2
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]="f029f05b-4c71-52d3-b523-0834d67de2d4")}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";
|
|
@@ -37434,6 +37434,115 @@ const buildRuleSeverityControls = (config) => {
|
|
|
37434
37434
|
...config.buckets !== void 0 ? { buckets: config.buckets } : {}
|
|
37435
37435
|
};
|
|
37436
37436
|
};
|
|
37437
|
+
const JSX_OPENER_TAG_PATTERN = /<[A-Za-z][\w.]*/g;
|
|
37438
|
+
const JSX_TAG_NAME_FOLLOW = /[A-Za-z]/;
|
|
37439
|
+
const isOpenerMatchInsideLineComment = (line, openerCharIndex) => {
|
|
37440
|
+
let stringDelimiter = null;
|
|
37441
|
+
for (let charIndex = 0; charIndex < openerCharIndex; charIndex++) {
|
|
37442
|
+
const character = line[charIndex];
|
|
37443
|
+
if (stringDelimiter !== null) {
|
|
37444
|
+
if (character === "\\") {
|
|
37445
|
+
charIndex++;
|
|
37446
|
+
continue;
|
|
37447
|
+
}
|
|
37448
|
+
if (character === stringDelimiter) stringDelimiter = null;
|
|
37449
|
+
continue;
|
|
37450
|
+
}
|
|
37451
|
+
if (character === "\"" || character === "'" || character === "`") {
|
|
37452
|
+
stringDelimiter = character;
|
|
37453
|
+
continue;
|
|
37454
|
+
}
|
|
37455
|
+
if (character === "/" && line[charIndex + 1] === "/") return true;
|
|
37456
|
+
}
|
|
37457
|
+
return false;
|
|
37458
|
+
};
|
|
37459
|
+
const findOpenerTagOnLine = (line) => {
|
|
37460
|
+
for (const match of line.matchAll(JSX_OPENER_TAG_PATTERN)) {
|
|
37461
|
+
if (match.index === void 0) continue;
|
|
37462
|
+
if (!isOpenerMatchInsideLineComment(line, match.index)) return { startCharIndex: match.index + match[0].length };
|
|
37463
|
+
}
|
|
37464
|
+
return null;
|
|
37465
|
+
};
|
|
37466
|
+
const findJsxOpenerSpan = (lines, openerLineIndex) => {
|
|
37467
|
+
const openerLine = lines[openerLineIndex];
|
|
37468
|
+
if (openerLine === void 0) return null;
|
|
37469
|
+
const opener = findOpenerTagOnLine(openerLine);
|
|
37470
|
+
if (!opener) return null;
|
|
37471
|
+
const lookaheadLimit = Math.min(lines.length, openerLineIndex + 32);
|
|
37472
|
+
let braceDepth = 0;
|
|
37473
|
+
let innerAngleDepth = 0;
|
|
37474
|
+
let stringDelimiter = null;
|
|
37475
|
+
for (let lineIndex = openerLineIndex; lineIndex < lookaheadLimit; lineIndex++) {
|
|
37476
|
+
const currentLine = lines[lineIndex];
|
|
37477
|
+
const startCharForLine = lineIndex === openerLineIndex ? opener.startCharIndex : 0;
|
|
37478
|
+
for (let charIndex = startCharForLine; charIndex < currentLine.length; charIndex++) {
|
|
37479
|
+
const character = currentLine[charIndex];
|
|
37480
|
+
if (stringDelimiter !== null) {
|
|
37481
|
+
if (character === "\\") {
|
|
37482
|
+
charIndex++;
|
|
37483
|
+
continue;
|
|
37484
|
+
}
|
|
37485
|
+
if (character === stringDelimiter) stringDelimiter = null;
|
|
37486
|
+
continue;
|
|
37487
|
+
}
|
|
37488
|
+
if (character === "\"" || character === "'" || character === "`") {
|
|
37489
|
+
stringDelimiter = character;
|
|
37490
|
+
continue;
|
|
37491
|
+
}
|
|
37492
|
+
if (character === "{") {
|
|
37493
|
+
braceDepth++;
|
|
37494
|
+
continue;
|
|
37495
|
+
}
|
|
37496
|
+
if (character === "}") {
|
|
37497
|
+
braceDepth--;
|
|
37498
|
+
continue;
|
|
37499
|
+
}
|
|
37500
|
+
if (braceDepth !== 0) continue;
|
|
37501
|
+
if (character === "<") {
|
|
37502
|
+
const followCharacter = currentLine[charIndex + 1];
|
|
37503
|
+
if (followCharacter !== void 0 && JSX_TAG_NAME_FOLLOW.test(followCharacter)) innerAngleDepth++;
|
|
37504
|
+
continue;
|
|
37505
|
+
}
|
|
37506
|
+
if (character !== ">") continue;
|
|
37507
|
+
const previousCharacter = currentLine[charIndex - 1];
|
|
37508
|
+
const nextCharacter = currentLine[charIndex + 1];
|
|
37509
|
+
if (previousCharacter === "=" || nextCharacter === "=") continue;
|
|
37510
|
+
if (innerAngleDepth > 0) {
|
|
37511
|
+
innerAngleDepth--;
|
|
37512
|
+
continue;
|
|
37513
|
+
}
|
|
37514
|
+
return lineIndex;
|
|
37515
|
+
}
|
|
37516
|
+
}
|
|
37517
|
+
return null;
|
|
37518
|
+
};
|
|
37519
|
+
const findEnclosingMultilineJsxOpenerStart = (lines, diagnosticLineIndex) => {
|
|
37520
|
+
for (let candidateIndex = diagnosticLineIndex - 1; candidateIndex >= 0 && diagnosticLineIndex - candidateIndex <= 32; candidateIndex--) {
|
|
37521
|
+
const openerCloseIndex = findJsxOpenerSpan(lines, candidateIndex);
|
|
37522
|
+
if (openerCloseIndex !== null && openerCloseIndex >= diagnosticLineIndex) return candidateIndex;
|
|
37523
|
+
}
|
|
37524
|
+
return null;
|
|
37525
|
+
};
|
|
37526
|
+
const DISABLE_NEXT_LINE_PATTERN = /(?:\/\/|\/\*)\s*react-doctor-disable-next-line\b(?:\s+([^\r\n]*?))?\s*(?:\*\/)?\s*\}?\s*$/;
|
|
37527
|
+
const findStackedDisableCommentsAbove = (lines, anchorIndex) => {
|
|
37528
|
+
const collected = [];
|
|
37529
|
+
let isStillInChain = true;
|
|
37530
|
+
for (let candidateIndex = anchorIndex - 1; candidateIndex >= 0 && anchorIndex - candidateIndex <= 10; candidateIndex--) {
|
|
37531
|
+
const candidateLine = lines[candidateIndex];
|
|
37532
|
+
if (candidateLine === void 0) break;
|
|
37533
|
+
const match = candidateLine.match(DISABLE_NEXT_LINE_PATTERN);
|
|
37534
|
+
if (match) {
|
|
37535
|
+
collected.push({
|
|
37536
|
+
commentLineIndex: candidateIndex,
|
|
37537
|
+
ruleList: match[1],
|
|
37538
|
+
isInChain: isStillInChain
|
|
37539
|
+
});
|
|
37540
|
+
continue;
|
|
37541
|
+
}
|
|
37542
|
+
isStillInChain = false;
|
|
37543
|
+
}
|
|
37544
|
+
return collected;
|
|
37545
|
+
};
|
|
37437
37546
|
const LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY = {
|
|
37438
37547
|
"effect/no-adjust-state-on-prop-change": "react-doctor/no-adjust-state-on-prop-change",
|
|
37439
37548
|
"effect/no-chain-state-updates": "react-doctor/no-chain-state-updates",
|
|
@@ -37558,13 +37667,7 @@ for (const [legacyRuleKey, nativeRuleKey] of Object.entries(LEGACY_RULE_KEY_TO_N
|
|
|
37558
37667
|
}
|
|
37559
37668
|
const getLegacyRuleKeysForNative = (ruleKey) => NATIVE_RULE_KEY_TO_LEGACY_RULE_KEYS.get(ruleKey) ?? [];
|
|
37560
37669
|
const canonicalizeRuleKey = (ruleKey) => LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY[ruleKey] ?? ruleKey;
|
|
37561
|
-
const
|
|
37562
|
-
const isSameRuleKey = (candidateRuleKey, targetRuleKey) => {
|
|
37563
|
-
const canonicalCandidate = canonicalizeRuleKey(candidateRuleKey);
|
|
37564
|
-
const canonicalTarget = canonicalizeRuleKey(targetRuleKey);
|
|
37565
|
-
if (canonicalCandidate === canonicalTarget) return true;
|
|
37566
|
-
return isReactDoctorShortIdOf(canonicalCandidate, canonicalTarget) || isReactDoctorShortIdOf(canonicalTarget, canonicalCandidate);
|
|
37567
|
-
};
|
|
37670
|
+
const isSameRuleKey = (candidateRuleKey, targetRuleKey) => canonicalizeRuleKey(candidateRuleKey) === canonicalizeRuleKey(targetRuleKey);
|
|
37568
37671
|
const getEquivalentRuleKeys = (ruleKey) => {
|
|
37569
37672
|
const nativeRuleKey = canonicalizeRuleKey(ruleKey);
|
|
37570
37673
|
return [nativeRuleKey, ...getLegacyRuleKeysForNative(nativeRuleKey)];
|
|
@@ -37574,182 +37677,12 @@ const stripDescriptionTail = (ruleList) => {
|
|
|
37574
37677
|
if (!descriptionMatch || descriptionMatch.index === void 0) return ruleList;
|
|
37575
37678
|
return ruleList.slice(0, descriptionMatch.index);
|
|
37576
37679
|
};
|
|
37577
|
-
const
|
|
37680
|
+
const isRuleListedInComment = (ruleList, ruleId) => {
|
|
37578
37681
|
const trimmed = ruleList?.trim();
|
|
37579
|
-
if (!trimmed) return
|
|
37682
|
+
if (!trimmed) return true;
|
|
37580
37683
|
const ruleSection = stripDescriptionTail(trimmed).trim();
|
|
37581
|
-
if (!ruleSection) return
|
|
37582
|
-
return ruleSection.split(/[,\s]+/).
|
|
37583
|
-
};
|
|
37584
|
-
const FOREIGN_INLINE_DISABLE_PATTERN = /(?:\/\/|\/\*)[ \t]*(eslint|oxlint)-disable-(next-line|line)(?![\w-])([^\r\n]*)/;
|
|
37585
|
-
const FOREIGN_BLOCK_DISABLE_PATTERN = /\/\*[ \t]*(eslint|oxlint)-disable(?![\w-])([^*\r\n]*)/;
|
|
37586
|
-
const FOREIGN_BLOCK_ENABLE_PATTERN = /\/\*[ \t]*(?:eslint|oxlint)-enable(?![\w-])([^*\r\n]*)/;
|
|
37587
|
-
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}\`.`;
|
|
37588
|
-
const tokenMisnamesRule = (token, ruleId) => token !== ruleId && isSameRuleKey(token, ruleId);
|
|
37589
|
-
const detectInlineNearMiss = (lines, diagnosticLineIndex, ruleId) => {
|
|
37590
|
-
const candidates = [{
|
|
37591
|
-
line: lines[diagnosticLineIndex],
|
|
37592
|
-
requiredScope: "line"
|
|
37593
|
-
}, {
|
|
37594
|
-
line: lines[diagnosticLineIndex - 1],
|
|
37595
|
-
requiredScope: "next-line"
|
|
37596
|
-
}];
|
|
37597
|
-
for (const { line, requiredScope } of candidates) {
|
|
37598
|
-
const match = line?.match(FOREIGN_INLINE_DISABLE_PATTERN);
|
|
37599
|
-
if (!match) continue;
|
|
37600
|
-
const [, tool, scope, ruleList] = match;
|
|
37601
|
-
if (scope !== requiredScope) continue;
|
|
37602
|
-
const tokens = tokenizeRuleList(ruleList);
|
|
37603
|
-
if (tokens.includes(ruleId)) continue;
|
|
37604
|
-
for (const token of tokens) if (tokenMisnamesRule(token, ruleId)) return buildHint(tool, token, ruleId);
|
|
37605
|
-
}
|
|
37606
|
-
return null;
|
|
37607
|
-
};
|
|
37608
|
-
const detectBlockNearMiss = (lines, diagnosticLineIndex, ruleId) => {
|
|
37609
|
-
let openMisname = null;
|
|
37610
|
-
const lastLineIndex = Math.min(diagnosticLineIndex, lines.length - 1);
|
|
37611
|
-
for (let lineIndex = 0; lineIndex <= lastLineIndex; lineIndex++) {
|
|
37612
|
-
const line = lines[lineIndex];
|
|
37613
|
-
if (line === void 0 || !line.includes("-disable") && !line.includes("-enable")) continue;
|
|
37614
|
-
const disableMatch = line.match(FOREIGN_BLOCK_DISABLE_PATTERN);
|
|
37615
|
-
if (disableMatch) {
|
|
37616
|
-
const [, tool, ruleList] = disableMatch;
|
|
37617
|
-
const tokens = tokenizeRuleList(ruleList);
|
|
37618
|
-
if (tokens.includes(ruleId)) openMisname = null;
|
|
37619
|
-
else {
|
|
37620
|
-
const misnamed = tokens.find((token) => tokenMisnamesRule(token, ruleId));
|
|
37621
|
-
if (misnamed) openMisname = {
|
|
37622
|
-
tool,
|
|
37623
|
-
token: misnamed
|
|
37624
|
-
};
|
|
37625
|
-
}
|
|
37626
|
-
continue;
|
|
37627
|
-
}
|
|
37628
|
-
const enableMatch = line.match(FOREIGN_BLOCK_ENABLE_PATTERN);
|
|
37629
|
-
if (enableMatch) {
|
|
37630
|
-
const enabledRules = tokenizeRuleList(enableMatch[1]);
|
|
37631
|
-
if (enabledRules.length === 0 || enabledRules.some((rule) => isSameRuleKey(rule, ruleId))) openMisname = null;
|
|
37632
|
-
}
|
|
37633
|
-
}
|
|
37634
|
-
return openMisname ? buildHint(openMisname.tool, openMisname.token, ruleId) : null;
|
|
37635
|
-
};
|
|
37636
|
-
const detectForeignDisableNearMiss = (lines, diagnosticLineIndex, ruleId) => {
|
|
37637
|
-
if (!ruleId.startsWith("react-doctor/")) return null;
|
|
37638
|
-
return detectInlineNearMiss(lines, diagnosticLineIndex, ruleId) ?? detectBlockNearMiss(lines, diagnosticLineIndex, ruleId);
|
|
37639
|
-
};
|
|
37640
|
-
const JSX_OPENER_TAG_PATTERN = /<[A-Za-z][\w.]*/g;
|
|
37641
|
-
const JSX_TAG_NAME_FOLLOW = /[A-Za-z]/;
|
|
37642
|
-
const isOpenerMatchInsideLineComment = (line, openerCharIndex) => {
|
|
37643
|
-
let stringDelimiter = null;
|
|
37644
|
-
for (let charIndex = 0; charIndex < openerCharIndex; charIndex++) {
|
|
37645
|
-
const character = line[charIndex];
|
|
37646
|
-
if (stringDelimiter !== null) {
|
|
37647
|
-
if (character === "\\") {
|
|
37648
|
-
charIndex++;
|
|
37649
|
-
continue;
|
|
37650
|
-
}
|
|
37651
|
-
if (character === stringDelimiter) stringDelimiter = null;
|
|
37652
|
-
continue;
|
|
37653
|
-
}
|
|
37654
|
-
if (character === "\"" || character === "'" || character === "`") {
|
|
37655
|
-
stringDelimiter = character;
|
|
37656
|
-
continue;
|
|
37657
|
-
}
|
|
37658
|
-
if (character === "/" && line[charIndex + 1] === "/") return true;
|
|
37659
|
-
}
|
|
37660
|
-
return false;
|
|
37661
|
-
};
|
|
37662
|
-
const findOpenerTagOnLine = (line) => {
|
|
37663
|
-
for (const match of line.matchAll(JSX_OPENER_TAG_PATTERN)) {
|
|
37664
|
-
if (match.index === void 0) continue;
|
|
37665
|
-
if (!isOpenerMatchInsideLineComment(line, match.index)) return { startCharIndex: match.index + match[0].length };
|
|
37666
|
-
}
|
|
37667
|
-
return null;
|
|
37668
|
-
};
|
|
37669
|
-
const findJsxOpenerSpan = (lines, openerLineIndex) => {
|
|
37670
|
-
const openerLine = lines[openerLineIndex];
|
|
37671
|
-
if (openerLine === void 0) return null;
|
|
37672
|
-
const opener = findOpenerTagOnLine(openerLine);
|
|
37673
|
-
if (!opener) return null;
|
|
37674
|
-
const lookaheadLimit = Math.min(lines.length, openerLineIndex + 32);
|
|
37675
|
-
let braceDepth = 0;
|
|
37676
|
-
let innerAngleDepth = 0;
|
|
37677
|
-
let stringDelimiter = null;
|
|
37678
|
-
for (let lineIndex = openerLineIndex; lineIndex < lookaheadLimit; lineIndex++) {
|
|
37679
|
-
const currentLine = lines[lineIndex];
|
|
37680
|
-
const startCharForLine = lineIndex === openerLineIndex ? opener.startCharIndex : 0;
|
|
37681
|
-
for (let charIndex = startCharForLine; charIndex < currentLine.length; charIndex++) {
|
|
37682
|
-
const character = currentLine[charIndex];
|
|
37683
|
-
if (stringDelimiter !== null) {
|
|
37684
|
-
if (character === "\\") {
|
|
37685
|
-
charIndex++;
|
|
37686
|
-
continue;
|
|
37687
|
-
}
|
|
37688
|
-
if (character === stringDelimiter) stringDelimiter = null;
|
|
37689
|
-
continue;
|
|
37690
|
-
}
|
|
37691
|
-
if (character === "\"" || character === "'" || character === "`") {
|
|
37692
|
-
stringDelimiter = character;
|
|
37693
|
-
continue;
|
|
37694
|
-
}
|
|
37695
|
-
if (character === "{") {
|
|
37696
|
-
braceDepth++;
|
|
37697
|
-
continue;
|
|
37698
|
-
}
|
|
37699
|
-
if (character === "}") {
|
|
37700
|
-
braceDepth--;
|
|
37701
|
-
continue;
|
|
37702
|
-
}
|
|
37703
|
-
if (braceDepth !== 0) continue;
|
|
37704
|
-
if (character === "<") {
|
|
37705
|
-
const followCharacter = currentLine[charIndex + 1];
|
|
37706
|
-
if (followCharacter !== void 0 && JSX_TAG_NAME_FOLLOW.test(followCharacter)) innerAngleDepth++;
|
|
37707
|
-
continue;
|
|
37708
|
-
}
|
|
37709
|
-
if (character !== ">") continue;
|
|
37710
|
-
const previousCharacter = currentLine[charIndex - 1];
|
|
37711
|
-
const nextCharacter = currentLine[charIndex + 1];
|
|
37712
|
-
if (previousCharacter === "=" || nextCharacter === "=") continue;
|
|
37713
|
-
if (innerAngleDepth > 0) {
|
|
37714
|
-
innerAngleDepth--;
|
|
37715
|
-
continue;
|
|
37716
|
-
}
|
|
37717
|
-
return lineIndex;
|
|
37718
|
-
}
|
|
37719
|
-
}
|
|
37720
|
-
return null;
|
|
37721
|
-
};
|
|
37722
|
-
const findEnclosingMultilineJsxOpenerStart = (lines, diagnosticLineIndex) => {
|
|
37723
|
-
for (let candidateIndex = diagnosticLineIndex - 1; candidateIndex >= 0 && diagnosticLineIndex - candidateIndex <= 32; candidateIndex--) {
|
|
37724
|
-
const openerCloseIndex = findJsxOpenerSpan(lines, candidateIndex);
|
|
37725
|
-
if (openerCloseIndex !== null && openerCloseIndex >= diagnosticLineIndex) return candidateIndex;
|
|
37726
|
-
}
|
|
37727
|
-
return null;
|
|
37728
|
-
};
|
|
37729
|
-
const DISABLE_NEXT_LINE_PATTERN = /(?:\/\/|\/\*)\s*react-doctor-disable-next-line\b(?:\s+([^\r\n]*?))?\s*(?:\*\/)?\s*\}?\s*$/;
|
|
37730
|
-
const findStackedDisableCommentsAbove = (lines, anchorIndex) => {
|
|
37731
|
-
const collected = [];
|
|
37732
|
-
let isStillInChain = true;
|
|
37733
|
-
for (let candidateIndex = anchorIndex - 1; candidateIndex >= 0 && anchorIndex - candidateIndex <= 10; candidateIndex--) {
|
|
37734
|
-
const candidateLine = lines[candidateIndex];
|
|
37735
|
-
if (candidateLine === void 0) break;
|
|
37736
|
-
const match = candidateLine.match(DISABLE_NEXT_LINE_PATTERN);
|
|
37737
|
-
if (match) {
|
|
37738
|
-
collected.push({
|
|
37739
|
-
commentLineIndex: candidateIndex,
|
|
37740
|
-
ruleList: match[1],
|
|
37741
|
-
isInChain: isStillInChain
|
|
37742
|
-
});
|
|
37743
|
-
continue;
|
|
37744
|
-
}
|
|
37745
|
-
isStillInChain = false;
|
|
37746
|
-
}
|
|
37747
|
-
return collected;
|
|
37748
|
-
};
|
|
37749
|
-
const isRuleListedInComment = (ruleList, ruleId) => {
|
|
37750
|
-
const tokens = tokenizeRuleList(ruleList);
|
|
37751
|
-
if (tokens.length === 0) return true;
|
|
37752
|
-
return tokens.some((token) => isSameRuleKey(token, ruleId));
|
|
37684
|
+
if (!ruleSection) return true;
|
|
37685
|
+
return ruleSection.split(/[,\s]+/).some((token) => isSameRuleKey(token.trim(), ruleId));
|
|
37753
37686
|
};
|
|
37754
37687
|
const DISABLE_LINE_PATTERN = /(?:\/\/|\/\*)\s*react-doctor-disable-line\b(?:\s+([^\r\n]*?))?\s*(?:\*\/)?\s*\}?\s*$/;
|
|
37755
37688
|
const formatLineGap = (gapLineCount) => `${gapLineCount} line${gapLineCount === 1 ? "" : "s"}`;
|
|
@@ -37793,7 +37726,7 @@ const evaluateSuppression = (lines, diagnosticLineIndex, ruleId) => {
|
|
|
37793
37726
|
};
|
|
37794
37727
|
return {
|
|
37795
37728
|
isSuppressed: false,
|
|
37796
|
-
nearMissHint: classifyFromComments([directComments, openerComments], diagnosticLineIndex, ruleId)
|
|
37729
|
+
nearMissHint: classifyFromComments([directComments, openerComments], diagnosticLineIndex, ruleId)
|
|
37797
37730
|
};
|
|
37798
37731
|
};
|
|
37799
37732
|
/**
|
|
@@ -44111,7 +44044,7 @@ const makeNoopConsole = () => ({
|
|
|
44111
44044
|
});
|
|
44112
44045
|
//#endregion
|
|
44113
44046
|
//#region src/cli/utils/version.ts
|
|
44114
|
-
const VERSION = "0.5.6-dev.
|
|
44047
|
+
const VERSION = "0.5.6-dev.4e06b2a";
|
|
44115
44048
|
//#endregion
|
|
44116
44049
|
//#region src/cli/utils/json-mode.ts
|
|
44117
44050
|
let context = null;
|
|
@@ -44473,13 +44406,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
|
|
|
44473
44406
|
* uploads source-map artifacts under, so stack frames symbolicate. Honors the
|
|
44474
44407
|
* standard `SENTRY_RELEASE` override.
|
|
44475
44408
|
*/
|
|
44476
|
-
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.5.6-dev.
|
|
44409
|
+
const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.5.6-dev.4e06b2a`;
|
|
44477
44410
|
/**
|
|
44478
44411
|
* Deployment environment shown in Sentry's environment filter. Defaults to
|
|
44479
44412
|
* `production` for tagged releases and `development` for dev/unbuilt versions,
|
|
44480
44413
|
* overridable via the standard `SENTRY_ENVIRONMENT` env var.
|
|
44481
44414
|
*/
|
|
44482
|
-
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.5.6-dev.
|
|
44415
|
+
const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.5.6-dev.4e06b2a") ? "development" : "production");
|
|
44483
44416
|
/**
|
|
44484
44417
|
* Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
|
|
44485
44418
|
* (set to `0` to disable tracing) and falls back to
|
|
@@ -54223,4 +54156,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
|
|
|
54223
54156
|
export {};
|
|
54224
54157
|
|
|
54225
54158
|
//# sourceMappingURL=cli.js.map
|
|
54226
|
-
//# debugId=
|
|
54159
|
+
//# debugId=f029f05b-4c71-52d3-b523-0834d67de2d4
|
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]="efaa91ed-3659-50a5-b802-51753472b2d6")}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";
|
|
@@ -34238,6 +34238,115 @@ const buildRuleSeverityControls = (config) => {
|
|
|
34238
34238
|
...config.buckets !== void 0 ? { buckets: config.buckets } : {}
|
|
34239
34239
|
};
|
|
34240
34240
|
};
|
|
34241
|
+
const JSX_OPENER_TAG_PATTERN = /<[A-Za-z][\w.]*/g;
|
|
34242
|
+
const JSX_TAG_NAME_FOLLOW = /[A-Za-z]/;
|
|
34243
|
+
const isOpenerMatchInsideLineComment = (line, openerCharIndex) => {
|
|
34244
|
+
let stringDelimiter = null;
|
|
34245
|
+
for (let charIndex = 0; charIndex < openerCharIndex; charIndex++) {
|
|
34246
|
+
const character = line[charIndex];
|
|
34247
|
+
if (stringDelimiter !== null) {
|
|
34248
|
+
if (character === "\\") {
|
|
34249
|
+
charIndex++;
|
|
34250
|
+
continue;
|
|
34251
|
+
}
|
|
34252
|
+
if (character === stringDelimiter) stringDelimiter = null;
|
|
34253
|
+
continue;
|
|
34254
|
+
}
|
|
34255
|
+
if (character === "\"" || character === "'" || character === "`") {
|
|
34256
|
+
stringDelimiter = character;
|
|
34257
|
+
continue;
|
|
34258
|
+
}
|
|
34259
|
+
if (character === "/" && line[charIndex + 1] === "/") return true;
|
|
34260
|
+
}
|
|
34261
|
+
return false;
|
|
34262
|
+
};
|
|
34263
|
+
const findOpenerTagOnLine = (line) => {
|
|
34264
|
+
for (const match of line.matchAll(JSX_OPENER_TAG_PATTERN)) {
|
|
34265
|
+
if (match.index === void 0) continue;
|
|
34266
|
+
if (!isOpenerMatchInsideLineComment(line, match.index)) return { startCharIndex: match.index + match[0].length };
|
|
34267
|
+
}
|
|
34268
|
+
return null;
|
|
34269
|
+
};
|
|
34270
|
+
const findJsxOpenerSpan = (lines, openerLineIndex) => {
|
|
34271
|
+
const openerLine = lines[openerLineIndex];
|
|
34272
|
+
if (openerLine === void 0) return null;
|
|
34273
|
+
const opener = findOpenerTagOnLine(openerLine);
|
|
34274
|
+
if (!opener) return null;
|
|
34275
|
+
const lookaheadLimit = Math.min(lines.length, openerLineIndex + 32);
|
|
34276
|
+
let braceDepth = 0;
|
|
34277
|
+
let innerAngleDepth = 0;
|
|
34278
|
+
let stringDelimiter = null;
|
|
34279
|
+
for (let lineIndex = openerLineIndex; lineIndex < lookaheadLimit; lineIndex++) {
|
|
34280
|
+
const currentLine = lines[lineIndex];
|
|
34281
|
+
const startCharForLine = lineIndex === openerLineIndex ? opener.startCharIndex : 0;
|
|
34282
|
+
for (let charIndex = startCharForLine; charIndex < currentLine.length; charIndex++) {
|
|
34283
|
+
const character = currentLine[charIndex];
|
|
34284
|
+
if (stringDelimiter !== null) {
|
|
34285
|
+
if (character === "\\") {
|
|
34286
|
+
charIndex++;
|
|
34287
|
+
continue;
|
|
34288
|
+
}
|
|
34289
|
+
if (character === stringDelimiter) stringDelimiter = null;
|
|
34290
|
+
continue;
|
|
34291
|
+
}
|
|
34292
|
+
if (character === "\"" || character === "'" || character === "`") {
|
|
34293
|
+
stringDelimiter = character;
|
|
34294
|
+
continue;
|
|
34295
|
+
}
|
|
34296
|
+
if (character === "{") {
|
|
34297
|
+
braceDepth++;
|
|
34298
|
+
continue;
|
|
34299
|
+
}
|
|
34300
|
+
if (character === "}") {
|
|
34301
|
+
braceDepth--;
|
|
34302
|
+
continue;
|
|
34303
|
+
}
|
|
34304
|
+
if (braceDepth !== 0) continue;
|
|
34305
|
+
if (character === "<") {
|
|
34306
|
+
const followCharacter = currentLine[charIndex + 1];
|
|
34307
|
+
if (followCharacter !== void 0 && JSX_TAG_NAME_FOLLOW.test(followCharacter)) innerAngleDepth++;
|
|
34308
|
+
continue;
|
|
34309
|
+
}
|
|
34310
|
+
if (character !== ">") continue;
|
|
34311
|
+
const previousCharacter = currentLine[charIndex - 1];
|
|
34312
|
+
const nextCharacter = currentLine[charIndex + 1];
|
|
34313
|
+
if (previousCharacter === "=" || nextCharacter === "=") continue;
|
|
34314
|
+
if (innerAngleDepth > 0) {
|
|
34315
|
+
innerAngleDepth--;
|
|
34316
|
+
continue;
|
|
34317
|
+
}
|
|
34318
|
+
return lineIndex;
|
|
34319
|
+
}
|
|
34320
|
+
}
|
|
34321
|
+
return null;
|
|
34322
|
+
};
|
|
34323
|
+
const findEnclosingMultilineJsxOpenerStart = (lines, diagnosticLineIndex) => {
|
|
34324
|
+
for (let candidateIndex = diagnosticLineIndex - 1; candidateIndex >= 0 && diagnosticLineIndex - candidateIndex <= 32; candidateIndex--) {
|
|
34325
|
+
const openerCloseIndex = findJsxOpenerSpan(lines, candidateIndex);
|
|
34326
|
+
if (openerCloseIndex !== null && openerCloseIndex >= diagnosticLineIndex) return candidateIndex;
|
|
34327
|
+
}
|
|
34328
|
+
return null;
|
|
34329
|
+
};
|
|
34330
|
+
const DISABLE_NEXT_LINE_PATTERN = /(?:\/\/|\/\*)\s*react-doctor-disable-next-line\b(?:\s+([^\r\n]*?))?\s*(?:\*\/)?\s*\}?\s*$/;
|
|
34331
|
+
const findStackedDisableCommentsAbove = (lines, anchorIndex) => {
|
|
34332
|
+
const collected = [];
|
|
34333
|
+
let isStillInChain = true;
|
|
34334
|
+
for (let candidateIndex = anchorIndex - 1; candidateIndex >= 0 && anchorIndex - candidateIndex <= 10; candidateIndex--) {
|
|
34335
|
+
const candidateLine = lines[candidateIndex];
|
|
34336
|
+
if (candidateLine === void 0) break;
|
|
34337
|
+
const match = candidateLine.match(DISABLE_NEXT_LINE_PATTERN);
|
|
34338
|
+
if (match) {
|
|
34339
|
+
collected.push({
|
|
34340
|
+
commentLineIndex: candidateIndex,
|
|
34341
|
+
ruleList: match[1],
|
|
34342
|
+
isInChain: isStillInChain
|
|
34343
|
+
});
|
|
34344
|
+
continue;
|
|
34345
|
+
}
|
|
34346
|
+
isStillInChain = false;
|
|
34347
|
+
}
|
|
34348
|
+
return collected;
|
|
34349
|
+
};
|
|
34241
34350
|
const LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY = {
|
|
34242
34351
|
"effect/no-adjust-state-on-prop-change": "react-doctor/no-adjust-state-on-prop-change",
|
|
34243
34352
|
"effect/no-chain-state-updates": "react-doctor/no-chain-state-updates",
|
|
@@ -34362,13 +34471,7 @@ for (const [legacyRuleKey, nativeRuleKey] of Object.entries(LEGACY_RULE_KEY_TO_N
|
|
|
34362
34471
|
}
|
|
34363
34472
|
const getLegacyRuleKeysForNative = (ruleKey) => NATIVE_RULE_KEY_TO_LEGACY_RULE_KEYS.get(ruleKey) ?? [];
|
|
34364
34473
|
const canonicalizeRuleKey = (ruleKey) => LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY[ruleKey] ?? ruleKey;
|
|
34365
|
-
const
|
|
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
|
-
};
|
|
34474
|
+
const isSameRuleKey = (candidateRuleKey, targetRuleKey) => canonicalizeRuleKey(candidateRuleKey) === canonicalizeRuleKey(targetRuleKey);
|
|
34372
34475
|
const getEquivalentRuleKeys = (ruleKey) => {
|
|
34373
34476
|
const nativeRuleKey = canonicalizeRuleKey(ruleKey);
|
|
34374
34477
|
return [nativeRuleKey, ...getLegacyRuleKeysForNative(nativeRuleKey)];
|
|
@@ -34378,182 +34481,12 @@ const stripDescriptionTail = (ruleList) => {
|
|
|
34378
34481
|
if (!descriptionMatch || descriptionMatch.index === void 0) return ruleList;
|
|
34379
34482
|
return ruleList.slice(0, descriptionMatch.index);
|
|
34380
34483
|
};
|
|
34381
|
-
const
|
|
34484
|
+
const isRuleListedInComment = (ruleList, ruleId) => {
|
|
34382
34485
|
const trimmed = ruleList?.trim();
|
|
34383
|
-
if (!trimmed) return
|
|
34486
|
+
if (!trimmed) return true;
|
|
34384
34487
|
const ruleSection = stripDescriptionTail(trimmed).trim();
|
|
34385
|
-
if (!ruleSection) return
|
|
34386
|
-
return ruleSection.split(/[,\s]+/).
|
|
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));
|
|
34488
|
+
if (!ruleSection) return true;
|
|
34489
|
+
return ruleSection.split(/[,\s]+/).some((token) => isSameRuleKey(token.trim(), ruleId));
|
|
34557
34490
|
};
|
|
34558
34491
|
const DISABLE_LINE_PATTERN = /(?:\/\/|\/\*)\s*react-doctor-disable-line\b(?:\s+([^\r\n]*?))?\s*(?:\*\/)?\s*\}?\s*$/;
|
|
34559
34492
|
const formatLineGap = (gapLineCount) => `${gapLineCount} line${gapLineCount === 1 ? "" : "s"}`;
|
|
@@ -34597,7 +34530,7 @@ const evaluateSuppression = (lines, diagnosticLineIndex, ruleId) => {
|
|
|
34597
34530
|
};
|
|
34598
34531
|
return {
|
|
34599
34532
|
isSuppressed: false,
|
|
34600
|
-
nearMissHint: classifyFromComments([directComments, openerComments], diagnosticLineIndex, ruleId)
|
|
34533
|
+
nearMissHint: classifyFromComments([directComments, openerComments], diagnosticLineIndex, ruleId)
|
|
34601
34534
|
};
|
|
34602
34535
|
};
|
|
34603
34536
|
/**
|
|
@@ -40664,4 +40597,4 @@ const toJsonReport = (result, options) => buildJsonReport({
|
|
|
40664
40597
|
export { AmbiguousProjectError, NoReactDependencyError, NotADirectoryError, PackageJsonNotFoundError, ProjectNotFoundError, ReactDoctorError, buildJsonReport, buildJsonReportError, clearCaches, defineConfig, diagnose, filterSourceFiles, getDiffInfo, isProjectDiscoveryError, isReactDoctorError, summarizeDiagnostics, toJsonReport };
|
|
40665
40598
|
|
|
40666
40599
|
//# sourceMappingURL=index.js.map
|
|
40667
|
-
//# debugId=
|
|
40600
|
+
//# debugId=efaa91ed-3659-50a5-b802-51753472b2d6
|
package/dist/lsp.js
CHANGED
|
@@ -34298,6 +34298,115 @@ const buildRuleSeverityControls = (config) => {
|
|
|
34298
34298
|
...config.buckets !== void 0 ? { buckets: config.buckets } : {}
|
|
34299
34299
|
};
|
|
34300
34300
|
};
|
|
34301
|
+
const JSX_OPENER_TAG_PATTERN = /<[A-Za-z][\w.]*/g;
|
|
34302
|
+
const JSX_TAG_NAME_FOLLOW = /[A-Za-z]/;
|
|
34303
|
+
const isOpenerMatchInsideLineComment = (line, openerCharIndex) => {
|
|
34304
|
+
let stringDelimiter = null;
|
|
34305
|
+
for (let charIndex = 0; charIndex < openerCharIndex; charIndex++) {
|
|
34306
|
+
const character = line[charIndex];
|
|
34307
|
+
if (stringDelimiter !== null) {
|
|
34308
|
+
if (character === "\\") {
|
|
34309
|
+
charIndex++;
|
|
34310
|
+
continue;
|
|
34311
|
+
}
|
|
34312
|
+
if (character === stringDelimiter) stringDelimiter = null;
|
|
34313
|
+
continue;
|
|
34314
|
+
}
|
|
34315
|
+
if (character === "\"" || character === "'" || character === "`") {
|
|
34316
|
+
stringDelimiter = character;
|
|
34317
|
+
continue;
|
|
34318
|
+
}
|
|
34319
|
+
if (character === "/" && line[charIndex + 1] === "/") return true;
|
|
34320
|
+
}
|
|
34321
|
+
return false;
|
|
34322
|
+
};
|
|
34323
|
+
const findOpenerTagOnLine = (line) => {
|
|
34324
|
+
for (const match of line.matchAll(JSX_OPENER_TAG_PATTERN)) {
|
|
34325
|
+
if (match.index === void 0) continue;
|
|
34326
|
+
if (!isOpenerMatchInsideLineComment(line, match.index)) return { startCharIndex: match.index + match[0].length };
|
|
34327
|
+
}
|
|
34328
|
+
return null;
|
|
34329
|
+
};
|
|
34330
|
+
const findJsxOpenerSpan = (lines, openerLineIndex) => {
|
|
34331
|
+
const openerLine = lines[openerLineIndex];
|
|
34332
|
+
if (openerLine === void 0) return null;
|
|
34333
|
+
const opener = findOpenerTagOnLine(openerLine);
|
|
34334
|
+
if (!opener) return null;
|
|
34335
|
+
const lookaheadLimit = Math.min(lines.length, openerLineIndex + 32);
|
|
34336
|
+
let braceDepth = 0;
|
|
34337
|
+
let innerAngleDepth = 0;
|
|
34338
|
+
let stringDelimiter = null;
|
|
34339
|
+
for (let lineIndex = openerLineIndex; lineIndex < lookaheadLimit; lineIndex++) {
|
|
34340
|
+
const currentLine = lines[lineIndex];
|
|
34341
|
+
const startCharForLine = lineIndex === openerLineIndex ? opener.startCharIndex : 0;
|
|
34342
|
+
for (let charIndex = startCharForLine; charIndex < currentLine.length; charIndex++) {
|
|
34343
|
+
const character = currentLine[charIndex];
|
|
34344
|
+
if (stringDelimiter !== null) {
|
|
34345
|
+
if (character === "\\") {
|
|
34346
|
+
charIndex++;
|
|
34347
|
+
continue;
|
|
34348
|
+
}
|
|
34349
|
+
if (character === stringDelimiter) stringDelimiter = null;
|
|
34350
|
+
continue;
|
|
34351
|
+
}
|
|
34352
|
+
if (character === "\"" || character === "'" || character === "`") {
|
|
34353
|
+
stringDelimiter = character;
|
|
34354
|
+
continue;
|
|
34355
|
+
}
|
|
34356
|
+
if (character === "{") {
|
|
34357
|
+
braceDepth++;
|
|
34358
|
+
continue;
|
|
34359
|
+
}
|
|
34360
|
+
if (character === "}") {
|
|
34361
|
+
braceDepth--;
|
|
34362
|
+
continue;
|
|
34363
|
+
}
|
|
34364
|
+
if (braceDepth !== 0) continue;
|
|
34365
|
+
if (character === "<") {
|
|
34366
|
+
const followCharacter = currentLine[charIndex + 1];
|
|
34367
|
+
if (followCharacter !== void 0 && JSX_TAG_NAME_FOLLOW.test(followCharacter)) innerAngleDepth++;
|
|
34368
|
+
continue;
|
|
34369
|
+
}
|
|
34370
|
+
if (character !== ">") continue;
|
|
34371
|
+
const previousCharacter = currentLine[charIndex - 1];
|
|
34372
|
+
const nextCharacter = currentLine[charIndex + 1];
|
|
34373
|
+
if (previousCharacter === "=" || nextCharacter === "=") continue;
|
|
34374
|
+
if (innerAngleDepth > 0) {
|
|
34375
|
+
innerAngleDepth--;
|
|
34376
|
+
continue;
|
|
34377
|
+
}
|
|
34378
|
+
return lineIndex;
|
|
34379
|
+
}
|
|
34380
|
+
}
|
|
34381
|
+
return null;
|
|
34382
|
+
};
|
|
34383
|
+
const findEnclosingMultilineJsxOpenerStart = (lines, diagnosticLineIndex) => {
|
|
34384
|
+
for (let candidateIndex = diagnosticLineIndex - 1; candidateIndex >= 0 && diagnosticLineIndex - candidateIndex <= 32; candidateIndex--) {
|
|
34385
|
+
const openerCloseIndex = findJsxOpenerSpan(lines, candidateIndex);
|
|
34386
|
+
if (openerCloseIndex !== null && openerCloseIndex >= diagnosticLineIndex) return candidateIndex;
|
|
34387
|
+
}
|
|
34388
|
+
return null;
|
|
34389
|
+
};
|
|
34390
|
+
const DISABLE_NEXT_LINE_PATTERN = /(?:\/\/|\/\*)\s*react-doctor-disable-next-line\b(?:\s+([^\r\n]*?))?\s*(?:\*\/)?\s*\}?\s*$/;
|
|
34391
|
+
const findStackedDisableCommentsAbove = (lines, anchorIndex) => {
|
|
34392
|
+
const collected = [];
|
|
34393
|
+
let isStillInChain = true;
|
|
34394
|
+
for (let candidateIndex = anchorIndex - 1; candidateIndex >= 0 && anchorIndex - candidateIndex <= 10; candidateIndex--) {
|
|
34395
|
+
const candidateLine = lines[candidateIndex];
|
|
34396
|
+
if (candidateLine === void 0) break;
|
|
34397
|
+
const match = candidateLine.match(DISABLE_NEXT_LINE_PATTERN);
|
|
34398
|
+
if (match) {
|
|
34399
|
+
collected.push({
|
|
34400
|
+
commentLineIndex: candidateIndex,
|
|
34401
|
+
ruleList: match[1],
|
|
34402
|
+
isInChain: isStillInChain
|
|
34403
|
+
});
|
|
34404
|
+
continue;
|
|
34405
|
+
}
|
|
34406
|
+
isStillInChain = false;
|
|
34407
|
+
}
|
|
34408
|
+
return collected;
|
|
34409
|
+
};
|
|
34301
34410
|
const LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY = {
|
|
34302
34411
|
"effect/no-adjust-state-on-prop-change": "react-doctor/no-adjust-state-on-prop-change",
|
|
34303
34412
|
"effect/no-chain-state-updates": "react-doctor/no-chain-state-updates",
|
|
@@ -34422,13 +34531,7 @@ for (const [legacyRuleKey, nativeRuleKey] of Object.entries(LEGACY_RULE_KEY_TO_N
|
|
|
34422
34531
|
}
|
|
34423
34532
|
const getLegacyRuleKeysForNative = (ruleKey) => NATIVE_RULE_KEY_TO_LEGACY_RULE_KEYS.get(ruleKey) ?? [];
|
|
34424
34533
|
const canonicalizeRuleKey = (ruleKey) => LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY[ruleKey] ?? ruleKey;
|
|
34425
|
-
const
|
|
34426
|
-
const isSameRuleKey = (candidateRuleKey, targetRuleKey) => {
|
|
34427
|
-
const canonicalCandidate = canonicalizeRuleKey(candidateRuleKey);
|
|
34428
|
-
const canonicalTarget = canonicalizeRuleKey(targetRuleKey);
|
|
34429
|
-
if (canonicalCandidate === canonicalTarget) return true;
|
|
34430
|
-
return isReactDoctorShortIdOf(canonicalCandidate, canonicalTarget) || isReactDoctorShortIdOf(canonicalTarget, canonicalCandidate);
|
|
34431
|
-
};
|
|
34534
|
+
const isSameRuleKey = (candidateRuleKey, targetRuleKey) => canonicalizeRuleKey(candidateRuleKey) === canonicalizeRuleKey(targetRuleKey);
|
|
34432
34535
|
const getEquivalentRuleKeys = (ruleKey) => {
|
|
34433
34536
|
const nativeRuleKey = canonicalizeRuleKey(ruleKey);
|
|
34434
34537
|
return [nativeRuleKey, ...getLegacyRuleKeysForNative(nativeRuleKey)];
|
|
@@ -34438,182 +34541,12 @@ const stripDescriptionTail = (ruleList) => {
|
|
|
34438
34541
|
if (!descriptionMatch || descriptionMatch.index === void 0) return ruleList;
|
|
34439
34542
|
return ruleList.slice(0, descriptionMatch.index);
|
|
34440
34543
|
};
|
|
34441
|
-
const
|
|
34544
|
+
const isRuleListedInComment = (ruleList, ruleId) => {
|
|
34442
34545
|
const trimmed = ruleList?.trim();
|
|
34443
|
-
if (!trimmed) return
|
|
34546
|
+
if (!trimmed) return true;
|
|
34444
34547
|
const ruleSection = stripDescriptionTail(trimmed).trim();
|
|
34445
|
-
if (!ruleSection) return
|
|
34446
|
-
return ruleSection.split(/[,\s]+/).
|
|
34447
|
-
};
|
|
34448
|
-
const FOREIGN_INLINE_DISABLE_PATTERN = /(?:\/\/|\/\*)[ \t]*(eslint|oxlint)-disable-(next-line|line)(?![\w-])([^\r\n]*)/;
|
|
34449
|
-
const FOREIGN_BLOCK_DISABLE_PATTERN = /\/\*[ \t]*(eslint|oxlint)-disable(?![\w-])([^*\r\n]*)/;
|
|
34450
|
-
const FOREIGN_BLOCK_ENABLE_PATTERN = /\/\*[ \t]*(?:eslint|oxlint)-enable(?![\w-])([^*\r\n]*)/;
|
|
34451
|
-
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}\`.`;
|
|
34452
|
-
const tokenMisnamesRule = (token, ruleId) => token !== ruleId && isSameRuleKey(token, ruleId);
|
|
34453
|
-
const detectInlineNearMiss = (lines, diagnosticLineIndex, ruleId) => {
|
|
34454
|
-
const candidates = [{
|
|
34455
|
-
line: lines[diagnosticLineIndex],
|
|
34456
|
-
requiredScope: "line"
|
|
34457
|
-
}, {
|
|
34458
|
-
line: lines[diagnosticLineIndex - 1],
|
|
34459
|
-
requiredScope: "next-line"
|
|
34460
|
-
}];
|
|
34461
|
-
for (const { line, requiredScope } of candidates) {
|
|
34462
|
-
const match = line?.match(FOREIGN_INLINE_DISABLE_PATTERN);
|
|
34463
|
-
if (!match) continue;
|
|
34464
|
-
const [, tool, scope, ruleList] = match;
|
|
34465
|
-
if (scope !== requiredScope) continue;
|
|
34466
|
-
const tokens = tokenizeRuleList(ruleList);
|
|
34467
|
-
if (tokens.includes(ruleId)) continue;
|
|
34468
|
-
for (const token of tokens) if (tokenMisnamesRule(token, ruleId)) return buildHint(tool, token, ruleId);
|
|
34469
|
-
}
|
|
34470
|
-
return null;
|
|
34471
|
-
};
|
|
34472
|
-
const detectBlockNearMiss = (lines, diagnosticLineIndex, ruleId) => {
|
|
34473
|
-
let openMisname = null;
|
|
34474
|
-
const lastLineIndex = Math.min(diagnosticLineIndex, lines.length - 1);
|
|
34475
|
-
for (let lineIndex = 0; lineIndex <= lastLineIndex; lineIndex++) {
|
|
34476
|
-
const line = lines[lineIndex];
|
|
34477
|
-
if (line === void 0 || !line.includes("-disable") && !line.includes("-enable")) continue;
|
|
34478
|
-
const disableMatch = line.match(FOREIGN_BLOCK_DISABLE_PATTERN);
|
|
34479
|
-
if (disableMatch) {
|
|
34480
|
-
const [, tool, ruleList] = disableMatch;
|
|
34481
|
-
const tokens = tokenizeRuleList(ruleList);
|
|
34482
|
-
if (tokens.includes(ruleId)) openMisname = null;
|
|
34483
|
-
else {
|
|
34484
|
-
const misnamed = tokens.find((token) => tokenMisnamesRule(token, ruleId));
|
|
34485
|
-
if (misnamed) openMisname = {
|
|
34486
|
-
tool,
|
|
34487
|
-
token: misnamed
|
|
34488
|
-
};
|
|
34489
|
-
}
|
|
34490
|
-
continue;
|
|
34491
|
-
}
|
|
34492
|
-
const enableMatch = line.match(FOREIGN_BLOCK_ENABLE_PATTERN);
|
|
34493
|
-
if (enableMatch) {
|
|
34494
|
-
const enabledRules = tokenizeRuleList(enableMatch[1]);
|
|
34495
|
-
if (enabledRules.length === 0 || enabledRules.some((rule) => isSameRuleKey(rule, ruleId))) openMisname = null;
|
|
34496
|
-
}
|
|
34497
|
-
}
|
|
34498
|
-
return openMisname ? buildHint(openMisname.tool, openMisname.token, ruleId) : null;
|
|
34499
|
-
};
|
|
34500
|
-
const detectForeignDisableNearMiss = (lines, diagnosticLineIndex, ruleId) => {
|
|
34501
|
-
if (!ruleId.startsWith("react-doctor/")) return null;
|
|
34502
|
-
return detectInlineNearMiss(lines, diagnosticLineIndex, ruleId) ?? detectBlockNearMiss(lines, diagnosticLineIndex, ruleId);
|
|
34503
|
-
};
|
|
34504
|
-
const JSX_OPENER_TAG_PATTERN = /<[A-Za-z][\w.]*/g;
|
|
34505
|
-
const JSX_TAG_NAME_FOLLOW = /[A-Za-z]/;
|
|
34506
|
-
const isOpenerMatchInsideLineComment = (line, openerCharIndex) => {
|
|
34507
|
-
let stringDelimiter = null;
|
|
34508
|
-
for (let charIndex = 0; charIndex < openerCharIndex; charIndex++) {
|
|
34509
|
-
const character = line[charIndex];
|
|
34510
|
-
if (stringDelimiter !== null) {
|
|
34511
|
-
if (character === "\\") {
|
|
34512
|
-
charIndex++;
|
|
34513
|
-
continue;
|
|
34514
|
-
}
|
|
34515
|
-
if (character === stringDelimiter) stringDelimiter = null;
|
|
34516
|
-
continue;
|
|
34517
|
-
}
|
|
34518
|
-
if (character === "\"" || character === "'" || character === "`") {
|
|
34519
|
-
stringDelimiter = character;
|
|
34520
|
-
continue;
|
|
34521
|
-
}
|
|
34522
|
-
if (character === "/" && line[charIndex + 1] === "/") return true;
|
|
34523
|
-
}
|
|
34524
|
-
return false;
|
|
34525
|
-
};
|
|
34526
|
-
const findOpenerTagOnLine = (line) => {
|
|
34527
|
-
for (const match of line.matchAll(JSX_OPENER_TAG_PATTERN)) {
|
|
34528
|
-
if (match.index === void 0) continue;
|
|
34529
|
-
if (!isOpenerMatchInsideLineComment(line, match.index)) return { startCharIndex: match.index + match[0].length };
|
|
34530
|
-
}
|
|
34531
|
-
return null;
|
|
34532
|
-
};
|
|
34533
|
-
const findJsxOpenerSpan = (lines, openerLineIndex) => {
|
|
34534
|
-
const openerLine = lines[openerLineIndex];
|
|
34535
|
-
if (openerLine === void 0) return null;
|
|
34536
|
-
const opener = findOpenerTagOnLine(openerLine);
|
|
34537
|
-
if (!opener) return null;
|
|
34538
|
-
const lookaheadLimit = Math.min(lines.length, openerLineIndex + 32);
|
|
34539
|
-
let braceDepth = 0;
|
|
34540
|
-
let innerAngleDepth = 0;
|
|
34541
|
-
let stringDelimiter = null;
|
|
34542
|
-
for (let lineIndex = openerLineIndex; lineIndex < lookaheadLimit; lineIndex++) {
|
|
34543
|
-
const currentLine = lines[lineIndex];
|
|
34544
|
-
const startCharForLine = lineIndex === openerLineIndex ? opener.startCharIndex : 0;
|
|
34545
|
-
for (let charIndex = startCharForLine; charIndex < currentLine.length; charIndex++) {
|
|
34546
|
-
const character = currentLine[charIndex];
|
|
34547
|
-
if (stringDelimiter !== null) {
|
|
34548
|
-
if (character === "\\") {
|
|
34549
|
-
charIndex++;
|
|
34550
|
-
continue;
|
|
34551
|
-
}
|
|
34552
|
-
if (character === stringDelimiter) stringDelimiter = null;
|
|
34553
|
-
continue;
|
|
34554
|
-
}
|
|
34555
|
-
if (character === "\"" || character === "'" || character === "`") {
|
|
34556
|
-
stringDelimiter = character;
|
|
34557
|
-
continue;
|
|
34558
|
-
}
|
|
34559
|
-
if (character === "{") {
|
|
34560
|
-
braceDepth++;
|
|
34561
|
-
continue;
|
|
34562
|
-
}
|
|
34563
|
-
if (character === "}") {
|
|
34564
|
-
braceDepth--;
|
|
34565
|
-
continue;
|
|
34566
|
-
}
|
|
34567
|
-
if (braceDepth !== 0) continue;
|
|
34568
|
-
if (character === "<") {
|
|
34569
|
-
const followCharacter = currentLine[charIndex + 1];
|
|
34570
|
-
if (followCharacter !== void 0 && JSX_TAG_NAME_FOLLOW.test(followCharacter)) innerAngleDepth++;
|
|
34571
|
-
continue;
|
|
34572
|
-
}
|
|
34573
|
-
if (character !== ">") continue;
|
|
34574
|
-
const previousCharacter = currentLine[charIndex - 1];
|
|
34575
|
-
const nextCharacter = currentLine[charIndex + 1];
|
|
34576
|
-
if (previousCharacter === "=" || nextCharacter === "=") continue;
|
|
34577
|
-
if (innerAngleDepth > 0) {
|
|
34578
|
-
innerAngleDepth--;
|
|
34579
|
-
continue;
|
|
34580
|
-
}
|
|
34581
|
-
return lineIndex;
|
|
34582
|
-
}
|
|
34583
|
-
}
|
|
34584
|
-
return null;
|
|
34585
|
-
};
|
|
34586
|
-
const findEnclosingMultilineJsxOpenerStart = (lines, diagnosticLineIndex) => {
|
|
34587
|
-
for (let candidateIndex = diagnosticLineIndex - 1; candidateIndex >= 0 && diagnosticLineIndex - candidateIndex <= 32; candidateIndex--) {
|
|
34588
|
-
const openerCloseIndex = findJsxOpenerSpan(lines, candidateIndex);
|
|
34589
|
-
if (openerCloseIndex !== null && openerCloseIndex >= diagnosticLineIndex) return candidateIndex;
|
|
34590
|
-
}
|
|
34591
|
-
return null;
|
|
34592
|
-
};
|
|
34593
|
-
const DISABLE_NEXT_LINE_PATTERN = /(?:\/\/|\/\*)\s*react-doctor-disable-next-line\b(?:\s+([^\r\n]*?))?\s*(?:\*\/)?\s*\}?\s*$/;
|
|
34594
|
-
const findStackedDisableCommentsAbove = (lines, anchorIndex) => {
|
|
34595
|
-
const collected = [];
|
|
34596
|
-
let isStillInChain = true;
|
|
34597
|
-
for (let candidateIndex = anchorIndex - 1; candidateIndex >= 0 && anchorIndex - candidateIndex <= 10; candidateIndex--) {
|
|
34598
|
-
const candidateLine = lines[candidateIndex];
|
|
34599
|
-
if (candidateLine === void 0) break;
|
|
34600
|
-
const match = candidateLine.match(DISABLE_NEXT_LINE_PATTERN);
|
|
34601
|
-
if (match) {
|
|
34602
|
-
collected.push({
|
|
34603
|
-
commentLineIndex: candidateIndex,
|
|
34604
|
-
ruleList: match[1],
|
|
34605
|
-
isInChain: isStillInChain
|
|
34606
|
-
});
|
|
34607
|
-
continue;
|
|
34608
|
-
}
|
|
34609
|
-
isStillInChain = false;
|
|
34610
|
-
}
|
|
34611
|
-
return collected;
|
|
34612
|
-
};
|
|
34613
|
-
const isRuleListedInComment = (ruleList, ruleId) => {
|
|
34614
|
-
const tokens = tokenizeRuleList(ruleList);
|
|
34615
|
-
if (tokens.length === 0) return true;
|
|
34616
|
-
return tokens.some((token) => isSameRuleKey(token, ruleId));
|
|
34548
|
+
if (!ruleSection) return true;
|
|
34549
|
+
return ruleSection.split(/[,\s]+/).some((token) => isSameRuleKey(token.trim(), ruleId));
|
|
34617
34550
|
};
|
|
34618
34551
|
const DISABLE_LINE_PATTERN = /(?:\/\/|\/\*)\s*react-doctor-disable-line\b(?:\s+([^\r\n]*?))?\s*(?:\*\/)?\s*\}?\s*$/;
|
|
34619
34552
|
const formatLineGap = (gapLineCount) => `${gapLineCount} line${gapLineCount === 1 ? "" : "s"}`;
|
|
@@ -34657,7 +34590,7 @@ const evaluateSuppression = (lines, diagnosticLineIndex, ruleId) => {
|
|
|
34657
34590
|
};
|
|
34658
34591
|
return {
|
|
34659
34592
|
isSuppressed: false,
|
|
34660
|
-
nearMissHint: classifyFromComments([directComments, openerComments], diagnosticLineIndex, ruleId)
|
|
34593
|
+
nearMissHint: classifyFromComments([directComments, openerComments], diagnosticLineIndex, ruleId)
|
|
34661
34594
|
};
|
|
34662
34595
|
};
|
|
34663
34596
|
/**
|
|
@@ -42445,5 +42378,5 @@ const startLanguageServer = () => {
|
|
|
42445
42378
|
};
|
|
42446
42379
|
//#endregion
|
|
42447
42380
|
export { startLanguageServer };
|
|
42448
|
-
!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]="
|
|
42449
|
-
//# debugId=
|
|
42381
|
+
!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]="657a7bbf-22e5-505b-a956-410727faec39")}catch(e){}}();
|
|
42382
|
+
//# debugId=657a7bbf-22e5-505b-a956-410727faec39
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-doctor",
|
|
3
|
-
"version": "0.5.6-dev.
|
|
3
|
+
"version": "0.5.6-dev.4e06b2a",
|
|
4
4
|
"description": "Your agent writes bad React. This catches it",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"accessibility",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"vscode-languageserver": "^9.0.1",
|
|
65
65
|
"vscode-languageserver-textdocument": "^1.0.12",
|
|
66
66
|
"vscode-uri": "^3.1.0",
|
|
67
|
-
"oxlint-plugin-react-doctor": "0.5.6-dev.
|
|
67
|
+
"oxlint-plugin-react-doctor": "0.5.6-dev.4e06b2a"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@types/babel__code-frame": "^7.27.0",
|