export function scanText()

in src/typescript/ast-utils.ts [231:327]


export function scanText(text: string, start: number, end?: number): TextRange[] {
  const ret: TextRange[] = [];

  let pos = start;
  const stopAtCode = end === undefined;
  if (end === undefined) {
    end = text.length;
  }
  while (pos < end) {
    const ch = text[pos];

    if (WHITESPACE.includes(ch)) {
      pos++;
      continue;
    }

    if (ch === '/' && text[pos + 1] === '/') {
      accumulateTextBlock();
      scanSinglelineComment();
      continue;
    }

    if (ch === '/' && text[pos + 1] === '*') {
      accumulateTextBlock();
      scanMultilineComment();
      continue;
    }

    // Non-whitespace, non-comment, must be regular token. End if we're not scanning
    // to a particular location, otherwise continue.
    if (stopAtCode) {
      break;
    }

    pos++;
  }

  accumulateTextBlock();

  return ret;

  function scanMultilineComment() {
    const endOfComment = findNext('*/', pos + 2);
    ret.push({
      type: 'blockcomment',
      hasTrailingNewLine: ['\n', '\r'].includes(text[endOfComment + 2]),
      pos,
      end: endOfComment + 2,
    });
    pos = endOfComment + 2;
    start = pos;
  }

  function scanSinglelineComment() {
    const nl = Math.min(findNext('\r', pos + 2), findNext('\n', pos + 2));

    if (text[pos + 2] === '/') {
      // Special /// comment
      ret.push({
        type: 'directive',
        hasTrailingNewLine: true,
        pos: pos + 1,
        end: nl,
      });
    } else {
      // Regular // comment
      ret.push({
        type: 'linecomment',
        hasTrailingNewLine: true,
        pos,
        end: nl,
      });
    }
    pos = nl + 1;
    start = pos;
  }

  function accumulateTextBlock() {
    if (pos - start > 0) {
      ret.push({
        type: 'other',
        hasTrailingNewLine: false,
        pos: start,
        end: pos,
      });
      start = pos;
    }
  }

  function findNext(sub: string, startPos: number) {
    const f = text.indexOf(sub, startPos);
    if (f === -1) {
      return text.length;
    }
    return f;
  }
}