// Copyright (c) 2017, 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/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:test/test.dart';

import '../../../../generated/test_support.dart';
import '../recovery_test_support.dart';

typedef AdjustValidUnitBeforeComparison = CompilationUnit Function(
    CompilationUnit unit);

/**
 * A base class that adds support for tests that test how well the parser
 * recovers when the user has entered an incomplete (but otherwise correct)
 * construct (such as a top-level declaration, class member, or statement).
 *
 * Because users often add new constructs between two existing constructs, these
 * tests effectively test whether the parser is able to recognize where the
 * partially entered construct ends and where the next fully entered construct
 * begins. (The preceding construct is irrelevant.) Given the large number of
 * following constructs the are valid in most contexts, these tests are designed
 * to programmatically generate tests based on a list of possible following
 * constructs.
 */
abstract class PartialCodeTest extends AbstractRecoveryTest {
  /**
   * A list of suffixes that can be used by tests of class members.
   */
  static final List<TestSuffix> classMemberSuffixes = <TestSuffix>[
    TestSuffix('annotation', '@annotation var f;'),
    TestSuffix('field', 'var f;'),
    TestSuffix('fieldConst', 'const f = 0;'),
    TestSuffix('fieldFinal', 'final f = 0;'),
    TestSuffix('methodNonVoid', 'int a(b) => 0;'),
    TestSuffix('methodVoid', 'void a(b) {}'),
    TestSuffix('getter', 'int get a => 0;'),
    TestSuffix('setter', 'set a(b) {}')
  ];

  /**
   * A list of suffixes that can be used by tests of top-level constructs that
   * can validly be followed by any declaration.
   */
  static final List<TestSuffix> declarationSuffixes = <TestSuffix>[
    TestSuffix('class', 'class A {}'),
    TestSuffix('enum', 'enum E { v }'),
//    new TestSuffix('extension', 'extension E on A {}'),
    TestSuffix('mixin', 'mixin M {}'),
    TestSuffix('typedef', 'typedef A = B Function(C, D);'),
    TestSuffix('functionVoid', 'void f() {}'),
    TestSuffix('functionNonVoid', 'int f() {}'),
    TestSuffix('var', 'var a;'),
    TestSuffix('const', 'const a = 0;'),
    TestSuffix('final', 'final a = 0;'),
    TestSuffix('getter', 'int get a => 0;'),
    TestSuffix('setter', 'set a(b) {}')
  ];

  /**
   * A list of suffixes that can be used by tests of top-level constructs that
   * can validly be followed by anything that is valid after a part directive.
   */
  static final List<TestSuffix> postPartSuffixes = <TestSuffix>[
    TestSuffix('part', "part 'a.dart';"),
    ...declarationSuffixes
  ];

  /**
   * A list of suffixes that can be used by tests of top-level constructs that
   * can validly be followed by any directive or declaration other than a
   * library directive.
   */
  static final List<TestSuffix> prePartSuffixes = <TestSuffix>[
    TestSuffix('import', "import 'a.dart';"),
    TestSuffix('export', "export 'a.dart';"),
    ...postPartSuffixes
  ];

  /**
   * A list of suffixes that can be used by tests of statements.
   */
  static final List<TestSuffix> statementSuffixes = <TestSuffix>[
    TestSuffix('assert', "assert (true);"),
    TestSuffix('block', "{}"),
    TestSuffix('break', "break;"),
    TestSuffix('continue', "continue;"),
    TestSuffix('do', "do {} while (true);"),
    TestSuffix('if', "if (true) {}"),
    TestSuffix('for', "for (var x in y) {}"),
    TestSuffix('labeled', "l: {}"),
    TestSuffix('localFunctionNonVoid', "int f() {}"),
    TestSuffix('localFunctionVoid', "void f() {}"),
    TestSuffix('localVariable', "var x;"),
    TestSuffix('switch', "switch (x) {}"),
    TestSuffix('try', "try {} finally {}"),
    TestSuffix('return', "return;"),
    TestSuffix('while', "while (true) {}"),
  ];

  /**
   * Build a group of tests with the given [groupName]. There will be one test
   * for every combination of elements in the cross-product of the lists of
   * [descriptors] and [suffixes], and one additional test for every descriptor
   * where the suffix is the empty string (to test partial declarations at the
   * end of the file). In total, there will be
   * `descriptors.length * (suffixes.length + 1)` tests generated.
   */
  buildTests(String groupName, List<TestDescriptor> descriptors,
      List<TestSuffix> suffixes,
      {FeatureSet featureSet,
      String head,
      bool includeEof = true,
      String tail}) {
    group(groupName, () {
      for (TestDescriptor descriptor in descriptors) {
        if (includeEof) {
          _buildTestForDescriptorAndSuffix(
              descriptor, TestSuffix.eof, 0, head, tail,
              featureSet: featureSet);
        }
        for (int i = 0; i < suffixes.length; i++) {
          _buildTestForDescriptorAndSuffix(
              descriptor, suffixes[i], i + 1, head, tail,
              featureSet: featureSet);
        }
        if (descriptor.failing != null) {
          test('${descriptor.name}_failingList', () {
            Set<String> failing = Set.from(descriptor.failing);
            if (includeEof) {
              failing.remove('eof');
            }
            failing.removeAll(suffixes.map((TestSuffix suffix) => suffix.name));
            expect(failing, isEmpty,
                reason:
                    'There are tests marked as failing that are not being run');
          });
        }
      }
    });
  }

  /**
   * Build a single test based on the given [descriptor] and [suffix].
   */
  _buildTestForDescriptorAndSuffix(TestDescriptor descriptor, TestSuffix suffix,
      int suffixIndex, String head, String tail,
      {FeatureSet featureSet}) {
    test('${descriptor.name}_${suffix.name}', () {
      //
      // Compose the invalid and valid pieces of code.
      //
      StringBuffer invalid = StringBuffer();
      StringBuffer valid = StringBuffer();
      StringBuffer base = StringBuffer();
      if (head != null) {
        invalid.write(head);
        valid.write(head);
        base.write(head);
      }
      invalid.write(descriptor.invalid);
      valid.write(descriptor.valid);
      if (suffix.text.isNotEmpty) {
        invalid.write(' ');
        invalid.write(suffix.text);
        valid.write(' ');
        valid.write(suffix.text);
        base.write(' ');
        base.write(suffix.text);
      }
      if (tail != null) {
        invalid.write(tail);
        valid.write(tail);
        base.write(tail);
      }
      //
      // Determine the existing errors in the code without either valid or
      // invalid code.
      //
      GatheringErrorListener listener =
          GatheringErrorListener(checkRanges: true);
      parseCompilationUnit2(base.toString(), listener, featureSet: featureSet);
      var baseErrorCodes = <ErrorCode>[];
      listener.errors.forEach((AnalysisError error) {
        if (error.errorCode == ParserErrorCode.BREAK_OUTSIDE_OF_LOOP ||
            error.errorCode == ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP ||
            error.errorCode == ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE) {
          baseErrorCodes.add(error.errorCode);
        }
      });

      var expectedValidCodeErrors = <ErrorCode>[];
      expectedValidCodeErrors.addAll(baseErrorCodes);
      if (descriptor.expectedErrorsInValidCode != null) {
        expectedValidCodeErrors.addAll(descriptor.expectedErrorsInValidCode);
      }

      var expectedInvalidCodeErrors = <ErrorCode>[];
      expectedInvalidCodeErrors.addAll(baseErrorCodes);
      if (descriptor.errorCodes != null) {
        expectedInvalidCodeErrors.addAll(descriptor.errorCodes);
      }
      //
      // Run the test.
      //
      List<String> failing = descriptor.failing;
      if (descriptor.allFailing ||
          (failing != null && failing.contains(suffix.name))) {
        bool failed = false;
        try {
          testRecovery(
              invalid.toString(), expectedInvalidCodeErrors, valid.toString(),
              adjustValidUnitBeforeComparison:
                  descriptor.adjustValidUnitBeforeComparison,
              expectedErrorsInValidCode: expectedValidCodeErrors);
          failed = true;
        } catch (e) {
          // Expected to fail.
        }
        if (failed) {
          fail('Expected to fail, but passed');
        }
      } else {
        testRecovery(
            invalid.toString(), expectedInvalidCodeErrors, valid.toString(),
            adjustValidUnitBeforeComparison:
                descriptor.adjustValidUnitBeforeComparison,
            expectedErrorsInValidCode: expectedValidCodeErrors,
            featureSet: featureSet);
      }
    });
  }
}

/**
 * A description of a set of tests that are to be built.
 */
class TestDescriptor {
  /**
   * The name of the test.
   */
  final String name;

  /**
   * Invalid code that the parser is expected to recover from.
   */
  final String invalid;

  /**
   * Error codes that the parser is expected to produce.
   */
  final List<ErrorCode> errorCodes;

  /**
   * Valid code that is equivalent to what the parser should produce as part of
   * recovering from the invalid code.
   */
  final String valid;

  /**
   * Error codes that the parser is expected to produce in the valid code.
   */
  final List<ErrorCode> expectedErrorsInValidCode;

  /**
   * A flag indicating whether all of the tests are expected to fail.
   */
  final bool allFailing;

  /**
   * A list containing the names of the suffixes for which the test is expected
   * to fail.
   */
  final List<String> failing;

  /**
   * A function that modifies the valid compilation unit before it is compared
   * with the invalid compilation unit, or `null` if no modification needed.
   */
  AdjustValidUnitBeforeComparison adjustValidUnitBeforeComparison;

  /**
   * Initialize a newly created test descriptor.
   */
  TestDescriptor(this.name, this.invalid, this.errorCodes, this.valid,
      {this.allFailing = false,
      this.failing,
      this.expectedErrorsInValidCode,
      this.adjustValidUnitBeforeComparison});
}

/**
 * A description of a set of suffixes that are to be used to construct tests.
 */
class TestSuffix {
  static final TestSuffix eof = TestSuffix('eof', '');

  /**
   * The name of the suffix.
   */
  final String name;

  /**
   * The code to be appended to the test code.
   */
  final String text;

  /**
   * Initialize a newly created suffix.
   */
  TestSuffix(this.name, this.text);
}
