replaceStringsAndComments method

void replaceStringsAndComments()

Replaces strings and comments by identifiers. The content of the strings and comments will be stored in two maps, so that can be restored.

Implementation

void replaceStringsAndComments() {
  engine.currentRegion.setAll();
  multiComments.clear();
  multiStrings.clear();
  final start = Position(0, 0, engine);
  final startPrefix = Position(0, 0, engine);
  final end = Position(0, 0, engine);
  final multiString1 = StringSearcher(engine, "'''");
  final multiString2 = StringSearcher(engine, '"""');
  final string1 = StringSearcher(engine, '"');
  final string2 = StringSearcher(engine, "'");
  final multiComment = StringSearcher(engine, '/*');
  final comment = StringSearcher(engine, '//');
  final commentOnly = RegExpSearcher(engine, pattern: r'^\s*//');
  final startSearcher = RegExpSearcher(engine, pattern: r'''/[*/]|["']''');
  final prefixR = StringSearcher(engine, 'r');
  while (engine.search(startSearcher,
      hitPosition: start, relativePosition: RelativePosition.belowLast)) {
    startPrefix.set(start.line, start.column == 0 ? 0 : start.column - 1);
    var isString = true;
    String? error;
    start.column--;
    final hasPrefixR = start.column >= 0 && engine.containsAt(start, prefixR);
    start.column++;
    if (engine.containsAt(start, multiString1)) {
      error = findEndOfMultilineItem(multiString1, end);
    } else if (engine.containsAt(start, multiString2)) {
      error = findEndOfMultilineItem(multiString2, end);
    } else if (engine.containsAt(start, multiComment)) {
      error = findEndOfMultilineItem(StringSearcher(engine, '*/'), end);
      isString = false;
    } else if (engine.containsAt(start, string1)) {
      error = findEndOfString(string1, hasPrefixR, end);
    } else if (engine.containsAt(start, string2)) {
      error = findEndOfString(string2, hasPrefixR, end);
    } else if (engine.containsAt(start, comment)) {
      isString = false;
      end.set(start.line + 1, 0);
      // Test whether the comment is not preceded by statement:
      if (commentOnly.next(engine.lines[start.line]) == 0) {
        // Combine all "comment only" lines:
        while (end.line < engine.lines.length &&
            commentOnly.next(engine.lines[end.line]) == 0) {
          end.line++;
        }
      }
    } else {
      error = 'unknown meta character';
      end.clone(engine.currentPosition);
      end.forward(1);
    }
    engine.currentPosition.clone(end);
    if (error != null) {
      engine.logger.error(error);
      continue;
    }
    if (hasPrefixR) {
      start.column--;
    }
    final content = engine.asString(start: start, end: end);
    final map = isString ? multiStrings : multiComments;
    final name = (isString ? prefixString : prefixComment) +
        map.length.toString() +
        '_';
    map[name] = content;
    engine.deleteFromTo(start: start, end: end);
    engine.insert(name, position: start);
    engine.currentPosition.set(0, 0);
  }
}