// 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/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../dart/resolution/context_collection_resolution.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(TodoTest);
  });
}

@reflectiveTest
class TodoTest extends PubPackageResolutionTest {
  test_todo_multiLineComment() async {
    await assertErrorsInCode(r'''
main() {
  /* TODO: Implement */
  /* TODO: Implement*/
}
''', [
      error(TodoCode.TODO, 14, 15, text: 'TODO: Implement'),
      error(TodoCode.TODO, 38, 15, text: 'TODO: Implement'),
    ]);
  }

  test_todo_multiLineCommentWrapped() async {
    await assertErrorsInCode(r'''
main() {
  /* TODO(a): Implement something
   *  that is too long for one line
   * This line is not part of the todo
   */
  /* TODO: Implement something
   *  that is too long for one line
   * This line is not part of the todo
   */
  /* TODO(a): Implement something
   *  that is too long for one line
   * 
   *  This line is not part of the todo
   */
  /* TODO: Implement something
   *  that is too long for one line
   * 
   *  This line is not part of the todo
   */
}
''', [
      error(TodoCode.TODO, 14, 64,
          text: 'TODO(a): Implement something that is too long for one line'),
      error(TodoCode.TODO, 129, 61,
          text: 'TODO: Implement something that is too long for one line'),
      error(TodoCode.TODO, 241, 64,
          text: 'TODO(a): Implement something that is too long for one line'),
      error(TodoCode.TODO, 363, 61,
          text: 'TODO: Implement something that is too long for one line'),
    ]);
  }

  test_todo_singleLineComment() async {
    await assertErrorsInCode(r'''
main() {
  // TODO: Implement
}
''', [
      error(TodoCode.TODO, 14, 15, text: 'TODO: Implement'),
    ]);
  }

  test_todo_singleLineCommentDoubleCommented() async {
    // Continuations are ignored for code that looks like commented comments
    // although the original TODOs are still picked up.
    await assertErrorsInCode(r'''
main() {
//      // TODO: Implement something
//      //  that is too long for one line
//      main() {

//      // TODO: Implement something
//      // this is not a todo
//      main() {

//      // TODO: Implement something
//      main() {
}
''', [
      error(TodoCode.TODO, 20, 67,
          text: 'TODO: Implement something that is too long for one line'),
      error(TodoCode.TODO, 117, 25, text: 'TODO: Implement something'),
      error(TodoCode.TODO, 202, 25, text: 'TODO: Implement something'),
    ]);
  }

  test_todo_singleLineCommentLessIndentedContinuation() async {
    await assertErrorsInCode(r'''
main() {
  // TODO: Implement something
  //  that is too long for one line
//    this is not part of the todo
}
''', [
      error(TodoCode.TODO, 14, 61,
          text: 'TODO: Implement something that is too long for one line'),
    ]);
  }

  test_todo_singleLineCommentMoreIndentedContinuation() async {
    await assertErrorsInCode(r'''
main() {
  // TODO: Implement something
  //  that is too long for one line
  //      this is not part of the todo
}
''', [
      error(TodoCode.TODO, 14, 61,
          text: 'TODO: Implement something that is too long for one line'),
    ]);
  }

  test_todo_singleLineCommentNested() async {
    await assertErrorsInCode(r'''
main() {
  // TODO: Implement something
  //  that is too long for one line
  //  TODO: This is a seperate todo that is accidentally indented
}
''', [
      error(TodoCode.TODO, 14, 61,
          text: 'TODO: Implement something that is too long for one line'),
      error(TodoCode.TODO, 82, 59,
          text: 'TODO: This is a seperate todo that is accidentally indented'),
    ]);
  }

  test_todo_singleLineCommentWrapped() async {
    await assertErrorsInCode(r'''
main() {
  // TODO: Implement something
  //  that is too long for one line
  // this is not part of the todo

  // TODO: Implement something
  //  that is too long for one line
  
  //  this is not part of the todo

  // TODO: Implement something
  //  that is too long for one line
  // 
  //  this is not part of the todo
}
''', [
      error(TodoCode.TODO, 14, 61,
          text: 'TODO: Implement something that is too long for one line'),
      error(TodoCode.TODO, 116, 61,
          text: 'TODO: Implement something that is too long for one line'),
      error(TodoCode.TODO, 222, 61,
          text: 'TODO: Implement something that is too long for one line'),
    ]);
  }
}
