Skip to content

⬅️ Back to Table of Contents

📄 SourceCodeFixer

📊 Analysis Summary

Metric Count
🔧 Functions 4
📦 Imports 2
📊 Variables & Constants 1
📐 Interfaces 1
📑 Type Aliases 2

📚 Table of Contents

🛠️ File Location:

📂 packages/rule-tester/src/utils/SourceCodeFixer.ts

📦 Imports

Name Source
Linter @typescript-eslint/utils/ts-eslint
hasOwnProperty ./hasOwnProperty

Variables & Constants

Name Type Kind Value Exported
BOM " " const '\uFEFF'

Functions

applyFixes(sourceText: string, messages: readonly LintMessage[]): AppliedFixes

Applies the fixes specified by the messages to the given text. Tries to be smart about the fixes and won't apply fixes over the same area in the text.

Parameters:

  • sourceText any: The text to apply the changes to.
  • messages any: The array of messages reported by ESLint.

Returns: undefined An object containing the fixed text and any unfixed messages.

Raw JSDoc
/**
 * Applies the fixes specified by the messages to the given text. Tries to be
 * smart about the fixes and won't apply fixes over the same area in the text.
 * @param sourceText The text to apply the changes to.
 * @param  messages The array of messages reported by ESLint.
 * @returns An object containing the fixed text and any unfixed messages.
 */

Calls:

  • sourceText.startsWith
  • sourceText.slice
  • remainingMessages.push
  • fix.text.startsWith
  • text.slice
  • Math.max
  • messages.forEach
  • hasOwnProperty (from ./hasOwnProperty)
  • fixes.push
  • fixes.sort
  • attemptFix
  • remainingMessages.sort

Internal Comments:

// clone the array (x2)
/**
   * Try to use the 'fix' from a problem.
   * @param problem The message object to apply fixes from
   * @returns Whether fix was successfully applied
   */
// Remain it as a problem if it's overlapped or it's a negative range
// Remove BOM.
// Make output to this fix. (x3)
/*
       * The only time attemptFix will fail is if a previous fix was
       * applied which conflicts with it.  So we can mark this as true.
       */ (x3)

Code
export function applyFixes(
  sourceText: string,
  messages: readonly LintMessage[],
): AppliedFixes {
  // clone the array
  const remainingMessages: LintMessage[] = [];
  const fixes: LintMessageWithFix[] = [];
  const bom = sourceText.startsWith(BOM) ? BOM : '';
  const text = bom ? sourceText.slice(1) : sourceText;
  let lastPos = Number.NEGATIVE_INFINITY;
  let output = bom;

  /**
   * Try to use the 'fix' from a problem.
   * @param problem The message object to apply fixes from
   * @returns Whether fix was successfully applied
   */
  function attemptFix(problem: LintMessageWithFix): boolean {
    const fix = problem.fix;
    const start = fix.range[0];
    const end = fix.range[1];

    // Remain it as a problem if it's overlapped or it's a negative range
    if (lastPos >= start || start > end) {
      remainingMessages.push(problem);
      return false;
    }

    // Remove BOM.
    if ((start < 0 && end >= 0) || (start === 0 && fix.text.startsWith(BOM))) {
      output = '';
    }

    // Make output to this fix.
    output += text.slice(Math.max(0, lastPos), Math.max(0, start));
    output += fix.text;
    lastPos = end;
    return true;
  }

  messages.forEach(problem => {
    if (hasOwnProperty(problem, 'fix')) {
      fixes.push(problem);
    } else {
      remainingMessages.push(problem);
    }
  });

  if (fixes.length) {
    let fixesWereApplied = false;

    for (const problem of fixes.sort(compareMessagesByFixRange)) {
      attemptFix(problem);

      /*
       * The only time attemptFix will fail is if a previous fix was
       * applied which conflicts with it.  So we can mark this as true.
       */
      fixesWereApplied = true;
    }
    output += text.slice(Math.max(0, lastPos));

    return {
      fixed: fixesWereApplied,
      messages: remainingMessages.sort(compareMessagesByLocation),
      output,
    };
  }

  return {
    fixed: false,
    messages,
    output: bom + text,
  };
}

compareMessagesByFixRange(a: LintMessageWithFix, b: LintMessageWithFix): number

Compares items in a messages array by range.

Returns: undefined -1 if a comes before b, 1 if a comes after b, 0 if equal.

Raw JSDoc
/**
 * Compares items in a messages array by range.
 * @returns -1 if a comes before b, 1 if a comes after b, 0 if equal.
 */
Code
function compareMessagesByFixRange(
  a: LintMessageWithFix,
  b: LintMessageWithFix,
): number {
  return a.fix.range[0] - b.fix.range[0] || a.fix.range[1] - b.fix.range[1];
}

compareMessagesByLocation(a: LintMessage, b: LintMessage): number

Compares items in a messages array by line and column.

Returns: undefined -1 if a comes before b, 1 if a comes after b, 0 if equal.

Raw JSDoc
/**
 * Compares items in a messages array by line and column.
 * @returns -1 if a comes before b, 1 if a comes after b, 0 if equal.
 */

Internal Comments:

// @ts-expect-error -- it's not possible for suggestions to reach this location

Code
function compareMessagesByLocation(a: LintMessage, b: LintMessage): number {
  // @ts-expect-error -- it's not possible for suggestions to reach this location
  return a.line - b.line || a.column - b.column;
}

Internal helpers

Declared inside another function in this file.

attemptFix(problem: LintMessageWithFix): boolean

Try to use the 'fix' from a problem.

Parameters:

  • problem any: The message object to apply fixes from

Returns: undefined Whether fix was successfully applied

Raw JSDoc
/**
   * Try to use the 'fix' from a problem.
   * @param problem The message object to apply fixes from
   * @returns Whether fix was successfully applied
   */

Calls:

  • remainingMessages.push
  • fix.text.startsWith
  • text.slice
  • Math.max

Internal Comments:

// Remain it as a problem if it's overlapped or it's a negative range
// Remove BOM.
// Make output to this fix. (x3)

Code
function attemptFix(problem: LintMessageWithFix): boolean {
    const fix = problem.fix;
    const start = fix.range[0];
    const end = fix.range[1];

    // Remain it as a problem if it's overlapped or it's a negative range
    if (lastPos >= start || start > end) {
      remainingMessages.push(problem);
      return false;
    }

    // Remove BOM.
    if ((start < 0 && end >= 0) || (start === 0 && fix.text.startsWith(BOM))) {
      output = '';
    }

    // Make output to this fix.
    output += text.slice(Math.max(0, lastPos), Math.max(0, start));
    output += fix.text;
    lastPos = end;
    return true;
  }

Interfaces

AppliedFixes

Interface Code
export interface AppliedFixes {
  fixed: boolean;
  messages: readonly LintMessage[];
  output: string;
}

Properties

Name Type Optional Description
fixed boolean not shown
messages readonly LintMessage[] not shown
output string not shown

Type Aliases

LintMessage

type LintMessage = Linter.LintMessage | Linter.LintSuggestion;

LintMessageWithFix

type LintMessageWithFix = LintMessage & Required<Pick<LintMessage, 'fix'>>;

Generated by Syntax Scribe