// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/error/codes.dart';

/// Instances of the class `ToDoFinder` find to-do comments in Dart code.
class TodoFinder {
  /// The error reporter by which to-do comments will be reported.
  final ErrorReporter _errorReporter;

  /// A regex for whitespace and comment markers to be removed from the text
  /// of multiline TODOs in multiline comments.
  final RegExp _commentNewlineAndMarker = RegExp('\\s*\\n\\s*\\*\\s*');

  /// A regex for any character that is not a comment marker `/` or whitespace
  /// used for finding the first "real" character of a comment to compare its
  /// indentation for wrapped todos.
  final RegExp _nonWhitespaceOrCommentMarker = RegExp('[^/ ]');

  /// Initialize a newly created to-do finder to report to-do comments to the
  /// given reporter.
  ///
  /// @param errorReporter the error reporter by which to-do comments will be
  ///        reported
  TodoFinder(this._errorReporter);

  /// Search the comments in the given compilation unit for to-do comments and
  /// report an error for each.
  ///
  /// @param unit the compilation unit containing the to-do comments
  void findIn(CompilationUnit unit) {
    _gatherTodoComments(unit.beginToken, unit.lineInfo!);
  }

  /// Search the comment tokens reachable from the given token and create errors
  /// for each to-do comment.
  ///
  /// @param token the head of the list of tokens being searched
  void _gatherTodoComments(Token? token, LineInfo lineInfo) {
    while (token != null && token.type != TokenType.EOF) {
      Token? commentToken = token.precedingComments;
      while (commentToken != null) {
        if (commentToken.type == TokenType.SINGLE_LINE_COMMENT ||
            commentToken.type == TokenType.MULTI_LINE_COMMENT) {
          commentToken = _scrapeTodoComment(commentToken, lineInfo);
        } else {
          commentToken = commentToken.next;
        }
      }
      token = token.next;
    }
  }

  /// Look for user defined tasks in comments starting [commentToken] and convert
  /// them into info level analysis issues.
  ///
  /// Subsequent comments that are indented with an additional space are
  /// considered continuations and will be included in a single analysis issue.
  ///
  /// Returns the next comment token to begin searching from (skipping over
  /// any continuations).
  Token? _scrapeTodoComment(Token commentToken, LineInfo lineInfo) {
    Iterable<RegExpMatch> matches =
        Todo.TODO_REGEX.allMatches(commentToken.lexeme);
    // Track the comment that will be returned for looking for the next todo.
    // This will be moved along if additional comments are consumed by multiline
    // TODOs.
    var nextComment = commentToken.next;
    final commentLocation = lineInfo.getLocation(commentToken.offset);

    for (RegExpMatch match in matches) {
      int offset = commentToken.offset + match.start + match.group(1)!.length;
      int column =
          commentLocation.columnNumber + match.start + match.group(1)!.length;
      String todoText = match.group(2)!;
      String todoKind = match.namedGroup('kind1') ?? match.namedGroup('kind2')!;
      int end = offset + todoText.length;

      if (commentToken.type == TokenType.MULTI_LINE_COMMENT) {
        // Remove any `*/` and trim any trailing whitespace.
        if (todoText.endsWith('*/')) {
          todoText = todoText.substring(0, todoText.length - 2).trimRight();
          end = offset + todoText.length;
        }

        // Replace out whitespace/comment markers to unwrap multiple lines.
        // Do not reset length after this, as length must include all characters.
        todoText = todoText.replaceAll(_commentNewlineAndMarker, ' ');
      } else if (commentToken.type == TokenType.SINGLE_LINE_COMMENT) {
        // Append any indented lines onto the end.
        var line = commentLocation.lineNumber;
        while (nextComment != null) {
          final nextCommentLocation = lineInfo.getLocation(nextComment.offset);
          final columnOfFirstNoneMarkerOrWhitespace =
              nextCommentLocation.columnNumber +
                  nextComment.lexeme.indexOf(_nonWhitespaceOrCommentMarker);

          final isContinuation =
              nextComment.type == TokenType.SINGLE_LINE_COMMENT &&
                  // Only consider TODOs on the very next line.
                  nextCommentLocation.lineNumber == line++ + 1 &&
                  // Only consider comment tokens starting at the same column.
                  nextCommentLocation.columnNumber ==
                      commentLocation.columnNumber &&
                  // And indented more than the original 'todo' text.
                  columnOfFirstNoneMarkerOrWhitespace == column + 1 &&
                  // And not their own todos.
                  !Todo.TODO_REGEX.hasMatch(nextComment.lexeme);
          if (!isContinuation) {
            break;
          }

          // Track the end of the continuation for the diagnostic range.
          end = nextComment.end;
          final lexemeTextOffset = columnOfFirstNoneMarkerOrWhitespace -
              nextCommentLocation.columnNumber;
          final continuationText =
              nextComment.lexeme.substring(lexemeTextOffset).trimRight();
          todoText = '$todoText $continuationText';
          nextComment = nextComment.next;
        }
      }

      _errorReporter.reportErrorForOffset(
          Todo.forKind(todoKind), offset, end - offset, [todoText]);
    }

    return nextComment;
  }
}
