React-Doctor Inline Suppression System: How Stacked Comments Work

React-Doctor's inline suppression system evaluates stacked disable-next-line comments by walking upward from a diagnostic to build a chain of contiguous directives, using the isInChain flag to determine active suppressors while generating actionable hints for rule mismatches or excessive distance via evaluateSuppression in src/utils/evaluate-suppression.ts.

React-Doctor, an open-source diagnostic tool maintained at millionco/react-doctor, provides a robust inline suppression system that allows developers to silence specific linting rules directly within source code. Unlike basic line-by-line disable comments, the system supports stacked comments—multiple directives placed consecutively above a diagnostic—that collectively determine whether a rule fires. Understanding the mechanism behind these stacked comments, including how the engine detects chains and surfaces "near-miss" hints, is essential for effective diagnostic management.

Core Suppression Directives and Syntax

React-Doctor recognizes two primary inline suppression patterns controlled by regex constants defined in src/constants.ts:

  • // react-doctor-disable-line – Suppresses a rule on the same line where the comment appears. The scanner matches this against DISABLE_LINE_PATTERN.
  • // react-doctor-disable-next-line – Suppresses a rule on the following line. This matches DISABLE_NEXT_LINE_PATTERN, which uses a permissive [^\r\n]*? capture to include optional explanatory text after --.

Block-style JSX variants {/* react-doctor-disable-next-line */} function identically within JSX contexts. When multiple disable-next-line comments appear directly above a diagnostic, the stacked comment logic groups them to determine if the diagnostic is truly suppressed.

Detecting Stacked Comments

The Upward Walk Algorithm

The engine identifies stacked comments through findStackedDisableCommentsAbove in src/utils/find-stacked-disable-comments.ts. Starting from the diagnostic line (the anchor index), the function walks upward through the source array passed from scan.ts, collecting matches for up to SUPPRESSION_NEAR_MISS_MAX_LINES lines.

Each match produces a StackedDisableComment object containing:

  • The line index of the comment
  • The raw rule list (e.g., no-console, react-doctor/no-useless-memo)
  • The isInChain boolean flag

The Role of isInChain

The isInChain flag is the critical mechanism enabling stacked behavior. As the walker encounters consecutive disable-next-line comments, it marks each with isInChain: true. If a non-matching line interrupts the sequence—such as a blank line or code—subsequent comments receive isInChain: false. Only comments where isInChain remains true can suppress the current diagnostic, ensuring that separated comment blocks do not unintentionally disable unrelated code.

Evaluating Suppression Logic

Same-Line Suppression Checks

In src/utils/evaluate-suppression.ts, the evaluateSuppression function first checks for same-line directives. If DISABLE_LINE_PATTERN matches the current line and isRuleListedInComment (from src/utils/is-rule-listed-in-comment.ts) confirms the rule ID is present—including stripping any -- description tail—the diagnostic is immediately suppressed.

Chain Suppression and JSX Handling

For disable-next-line directives, the evaluator checks two potential chains:

  1. Direct chain – Uses hasChainSuppressor to verify if any collected StackedDisableComment with isInChain: true lists the fired rule.
  2. JSX opener chain – For attribute-level diagnostics, the engine calls findEnclosingMultilineJsxOpenerStart from src/utils/find-enclosing-multiline-jsx-opener.ts to locate the opening tag line, allowing suppressions placed above the tag to affect attributes within it.

If neither chain contains a matching rule, the diagnostic reports, but the system proceeds to generate helpful hints.

Near-Miss Hint System

When suppression fails, React-Doctor analyzes the collected comments to distinguish between adjacent mismatches and distance violations, outputting guidance via src/cli.ts in --json or --audit mode.

Adjacent Rule-List Mismatch

If a comment remains in the chain (isInChain: true) but its rule list excludes the fired rule—detected by isRuleListedInComment—the system invokes buildAdjacentMismatchHint. This produces a message indicating which rules are present and suggests using comma-separated IDs to combine suppressions.

Gap Detection Using SUPPRESSION_NEAR_MISS_MAX_LINES

If the nearest matching comment exceeds SUPPRESSION_NEAR_MISS_MAX_LINES (defined in src/constants.ts), the engine triggers buildGapHint. This informs the user that the comment is too distant from the diagnostic, recommending they move the directive adjacent to the target line or refactor the code into a helper function.

Practical Implementation Examples

Example 1: Same-Line Suppression

// react-doctor-disable-line no-console
console.log('debug'); // Diagnostic suppressed via direct line match

The scanner matches DISABLE_LINE_PATTERN and isRuleListedInComment returns true, yielding a SuppressionEvaluation with isSuppressed: true.

Example 2: Stacked disable-next-line Comments

// react-doctor-disable-next-line no-console
// react-doctor-disable-next-line react-doctor/no-useless-memo
const value = expensiveComputation(); // Both rules suppressed

findStackedDisableCommentsAbove returns two objects with isInChain: true. hasChainSuppressor identifies that each rule is covered by at least one comment in the chain.

Example 3: Rule-List Mismatch

// react-doctor-disable-next-line no-console
const value = expensiveComputation(); // react-doctor/no-useless-memo fires

The comment is in-chain, but isRuleListedInComment detects the absence of react-doctor/no-useless-memo. buildAdjacentMismatchHint generates a message suggesting the comma form to include both rules.

Example 4: Comment Distance Violation

// react-doctor-disable-next-line react-doctor/no-useless-memo

function helper() {
  return null;
}

const value = expensiveComputation(); // Gap hint triggered

With three lines separating the comment from the diagnostic, exceeding SUPPRESSION_NEAR_MISS_MAX_LINES, hasChainSuppressor returns false and buildGapHint advises moving the comment to line 9.

Summary

  • Stacked comments are detected by findStackedDisableCommentsAbove in src/utils/find-stacked-disable-comments.ts, which walks upward from the diagnostic to collect contiguous disable-next-line directives.
  • The isInChain flag determines whether a comment remains part of an uninterrupted block; once broken, subsequent comments cannot suppress the current diagnostic.
  • Suppression evaluation in src/utils/evaluate-suppression.ts checks same-line patterns via DISABLE_LINE_PATTERN, then validates chains using hasChainSuppressor and JSX opener logic.
  • Near-miss hints distinguish between adjacent rule mismatches (fixed by updating the rule list) and gap violations (fixed by repositioning the comment within SUPPRESSION_NEAR_MISS_MAX_LINES).
  • Rule parsing occurs in src/utils/is-rule-listed-in-comment.ts, which strips descriptive text after -- to accurately identify suppression targets.

Frequently Asked Questions

How does React-Doctor distinguish between stacked and separated disable-next-line comments?

The system uses the isInChain boolean flag set by findStackedDisableCommentsAbove. Comments are marked isInChain: true only while consecutive disable-next-line matches continue uninterrupted; any non-matching line breaks the chain, setting subsequent comments to isInChain: false and excluding them from suppression evaluation.

Can I suppress multiple rules with a single stacked comment block?

Yes. By placing multiple // react-doctor-disable-next-line comments consecutively above a diagnostic—each listing different rules—the engine treats them as a single chain. hasChainSuppressor checks the aggregate rule lists of all in-chain comments, suppressing the diagnostic if any comment includes the fired rule.

What happens if my disable-next-line comment is too far from the diagnostic?

If the comment exceeds SUPPRESSION_NEAR_MISS_MAX_LINES (defined in src/constants.ts), the engine classifies it as a gap violation. While the comment remains in the chain, hasChainSuppressor returns false, and buildGapHint generates a message advising you to move the comment adjacent to the diagnostic line.

How does the system handle JSX attribute-level suppressions?

For diagnostics targeting JSX attributes, evaluateSuppression calls findEnclosingMultilineJsxOpenerStart from src/utils/find-enclosing-multiline-jsx-opener.ts to locate the opening tag line. This allows disable-next-line comments placed above the JSX tag itself to suppress attribute-level rules within the tag, treating the opener as part of the suppression chain.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →