// 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/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:test/test.dart';

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

/**
 * The base class for tests that test how well the parser recovers from various
 * syntactic errors.
 */
abstract class AbstractRecoveryTest extends FastaParserTestCase {
  void testRecovery(
      String invalidCode, List<ErrorCode> errorCodes, String validCode,
      {CompilationUnit adjustValidUnitBeforeComparison(CompilationUnit unit),
      bool enableControlFlowCollections,
      List<ErrorCode> expectedErrorsInValidCode}) {
    CompilationUnit validUnit;

    // Assert that the valid code is indeed valid.
    try {
      validUnit = parseCompilationUnit(validCode,
          codes: expectedErrorsInValidCode,
          enableControlFlowCollections: enableControlFlowCollections);
      validateTokenStream(validUnit.beginToken);
    } catch (e) {
//      print('');
//      print('  Errors in valid code.');
//      print('    Error: $e');
//      print('    Code: $validCode');
//      print('');
      rethrow;
    }

    // Compare the structures before asserting valid errors.
    GatheringErrorListener listener =
        new GatheringErrorListener(checkRanges: true);
    CompilationUnit invalidUnit = parseCompilationUnit2(invalidCode, listener,
        enableControlFlowCollections: enableControlFlowCollections);
    validateTokenStream(invalidUnit.beginToken);
    if (adjustValidUnitBeforeComparison != null) {
      validUnit = adjustValidUnitBeforeComparison(validUnit);
    }
    ResultComparator.compare(invalidUnit, validUnit);

    // Assert valid errors.
    if (errorCodes != null) {
      listener.assertErrorsWithCodes(errorCodes);
    } else {
      listener.assertNoErrors();
    }
  }

  void validateTokenStream(Token token) {
    while (!token.isEof) {
      Token next = token.next;
      expect(token.end, lessThanOrEqualTo(next.offset));
      if (next.isSynthetic) {
        if (const [')', ']', '}'].contains(next.lexeme)) {
          expect(next.beforeSynthetic, token);
        }
      }
      token = next;
    }
  }
}

/**
 * An object used to compare to AST structures and cause the test to fail if
 * they differ in any important ways.
 */
class ResultComparator extends AstComparator {
  bool failDifferentLength(List first, List second) {
    StringBuffer buffer = new StringBuffer();
    buffer.writeln('Expected a list of length ${second.length}');
    buffer.writeln('  $second');
    buffer.writeln('But found a list of length ${first.length}');
    buffer.writeln('  $first');
    if (first is NodeList) {
      _safelyWriteNodePath(buffer, first.owner);
    }
    fail(buffer.toString());
  }

  @override
  bool failIfNotNull(Object first, Object second) {
    if (second != null) {
      StringBuffer buffer = new StringBuffer();
      buffer.write('Expected null; found a ');
      buffer.writeln(second.runtimeType);
      if (second is AstNode) {
        _safelyWriteNodePath(buffer, second);
      }
      fail(buffer.toString());
    }
    return true;
  }

  @override
  bool failIsNull(Object first, Object second) {
    StringBuffer buffer = new StringBuffer();
    buffer.write('Expected a ');
    buffer.write(first.runtimeType);
    buffer.writeln('; found null');
    if (first is AstNode) {
      _safelyWriteNodePath(buffer, first);
    }
    fail(buffer.toString());
  }

  @override
  bool failRuntimeType(Object first, Object second) {
    StringBuffer buffer = new StringBuffer();
    buffer.write('Expected a ');
    buffer.writeln(second.runtimeType);
    buffer.write('; found ');
    buffer.writeln(first.runtimeType);
    if (first is AstNode) {
      _safelyWriteNodePath(buffer, first);
    }
    fail(buffer.toString());
  }

  /**
   * Overridden to allow the valid code to contain an explicit identifier where
   * a synthetic identifier is expected to be inserted by recovery.
   */
  @override
  bool isEqualNodes(AstNode first, AstNode second) {
    if (first is SimpleIdentifier && second is SimpleIdentifier) {
      if (first.isSynthetic && second.name == '_s_') {
        return true;
      }
    }
    return super.isEqualNodes(first, second);
  }

  /**
   * Overridden to ignore the offsets of tokens because these can legitimately
   * be different.
   */
  @override
  bool isEqualTokensNotNull(Token first, Token second) =>
      (first.isSynthetic && first.type == second.type) ||
      (first.length == second.length && first.lexeme == second.lexeme);

  void _safelyWriteNodePath(StringBuffer buffer, AstNode node) {
    buffer.write('  path: ');
    if (node == null) {
      buffer.write(' null');
    } else {
      _writeNodePath(buffer, node);
    }
  }

  void _writeNodePath(StringBuffer buffer, AstNode node) {
    AstNode parent = node.parent;
    if (parent != null) {
      _writeNodePath(buffer, parent);
      buffer.write(', ');
    }
    buffer.write(node.runtimeType);
  }

  /**
   * Compare the [actual] and [expected] nodes, failing the test if they are
   * different.
   */
  static void compare(AstNode actual, AstNode expected) {
    ResultComparator comparator = new ResultComparator();
    if (!comparator.isEqualNodes(actual, expected)) {
      fail('Expected: $expected\n   Found: $actual');
    }
  }
}
