All files ignore-hints.ts

100% Statements 23/23
94.44% Branches 17/18
100% Functions 1/1
100% Lines 23/23

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72                          48x     976x 976x   976x 976x   976x 61544x               220x 220x 220x   220x     61544x       348x 348x                   348x 348x   348x 24x     324x 236x 236x       61520x     952x    
/*
 * Most parsers don't emit comments in AST like Acorn does,
 * so parse comments manually instead.
 */
 
import jsTokens from "js-tokens";
 
export interface IgnoreHint {
  type: "if" | "else" | "next" | "file";
  loc: { start: number; end: number };
}
 
const IGNORE_PATTERN =
  /^\s*(?:istanbul|[cv]8|node:coverage)\s+ignore\s+(if|else|next|file)(?=\W|$)/;
 
export function getIgnoreHints(code: string): IgnoreHint[] {
  const ignoreHints: IgnoreHint[] = [];
  const tokens = jsTokens(code);
 
  let current = 0;
  let previousTokenWasIgnoreHint = false;
 
  for (const token of tokens) {
    if (
      previousTokenWasIgnoreHint &&
      token.type !== "WhiteSpace" &&
      token.type !== "LineTerminatorSequence"
    ) {
      // Make the comment end reach all the way to the next node so that
      // it's easier to check for ignore hints when inspecting node, kind of like
      // leadingComments AST attribute.
      const previous = ignoreHints.at(-1);
      Eif (previous) {
        previous.loc.end = current;
      }
      previousTokenWasIgnoreHint = false;
    }
 
    if (
      token.type === "SingleLineComment" ||
      token.type === "MultiLineComment"
    ) {
      const loc = { start: current, end: current + token.value.length };
      const comment = token.value
        // Start of multiline comment
        .replace(/^\/\*\*/, "")
        .replace(/^\/\*/, "")
        // End of multiline comment
        .replace(/\*\*\/$/, "")
        .replace(/\*\/$/, "")
        // Inline comment
        .replace(/^\/\//, "");
 
      const groups = comment.match(IGNORE_PATTERN);
      const type = groups?.[1];
 
      if (type === "file") {
        return [{ type: "file", loc: { start: 0, end: 0 } }];
      }
 
      if (type === "if" || type === "else" || type === "next") {
        ignoreHints.push({ type, loc });
        previousTokenWasIgnoreHint = true;
      }
    }
 
    current += token.value.length;
  }
 
  return ignoreHints;
}