// 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),
      List<ErrorCode> expectedErrorsInValidCode}) {
    CompilationUnit validUnit;

    // Assert that the valid code is indeed valid.
    try {
      validUnit =
          parseCompilationUnit(validCode, codes: expectedErrorsInValidCode);
    } 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);
    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) {
      expect(token.end, lessThanOrEqualTo(token.next.offset));
      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');
    }
  }
}
