// Copyright (c) 2018, 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.md file.

library fasta.test.assert_locations_test;

import 'package:async_helper/async_helper.dart' show asyncTest;

import 'package:expect/expect.dart' show Expect;

import 'package:kernel/ast.dart'
    show Program, RecursiveVisitor, Procedure, AssertStatement;

import "package:front_end/src/api_prototype/compiler_options.dart"
    show CompilerOptions;

import 'package:front_end/src/testing/compiler_common.dart' show compileScript;

import 'package:front_end/src/fasta/fasta_codes.dart' show LocatedMessage;

import 'package:front_end/src/fasta/severity.dart' show Severity;

/// Span of the condition expression in the assert statement.
class ConditionSpan {
  final startOffset;
  final endOffset;
  ConditionSpan(this.startOffset, this.endOffset);
}

/// Generated test with multiple functions each containing a single
/// assertion statement inside. [spans] specifies the mapping
/// between function name and [ConditionSpan] for an [AssertionStatement]
/// inside that function.
class Test {
  final String source;
  final Map<String, ConditionSpan> spans;

  Test(this.source, this.spans);
}

Test generateTest() {
  final sb = new StringBuffer();
  final spans = new Map<String, ConditionSpan>();

  // Create a test case for assert statement with the given [condition] and
  // [message]. Argument list would contain a trailing comma if [trailingComma]
  // is [true].
  // [additionalOffset] specifies an offset in characters from the opening
  // parenthesis of the assert statement to the first character of the
  // condition.
  void makeAssertWithMessage(String condition,
      {String message, bool trailingComma: false, int additionalOffset: 0}) {
    final name = 'testCase${spans.length}';
    sb.writeln('void $name(x) {');
    sb.write('assert(');
    final startOffset = sb.length + additionalOffset;
    sb.write(condition);
    final endOffset = sb.length;
    if (message != null) {
      sb.write(', "${message}"');
    }
    if (trailingComma) {
      sb.write(',');
    }
    sb.writeln(');');
    sb.writeln('}');
    spans[name] = new ConditionSpan(startOffset, endOffset);
  }

  // Create test cases for various variants of the assert statement with
  // the given condition.
  void makeAssert(String condition, {int additionalOffset: 0}) {
    makeAssertWithMessage(condition, additionalOffset: additionalOffset);
    makeAssertWithMessage(condition,
        trailingComma: true, additionalOffset: additionalOffset);
    makeAssertWithMessage(condition,
        message: 'message message', additionalOffset: additionalOffset);
    makeAssertWithMessage(condition,
        message: 'message message',
        trailingComma: true,
        additionalOffset: additionalOffset);
  }

  // Create all test cases.
  makeAssert('''

  (
    x != null
  )''', additionalOffset: 3);
  makeAssert('''(x != null)''');
  makeAssert('''x''');
  makeAssert('''((x))''');
  makeAssert('''!x''');
  makeAssert('''((!x))''');
  makeAssert('''x.method("a", "b")''');

  // Add a dummy main to avoid compilation errors.
  sb.writeln('''
void main() {}
''');

  return new Test(sb.toString(), spans);
}

/// Visitor that verifies that all [AssertStatement]s in the Kernel AST
/// have expected spans for their conditions.
class VerifyingVisitor extends RecursiveVisitor<Null> {
  final Test test;

  /// Set of names of verified [Procedure]s.
  final Set<String> verified = new Set<String>();

  /// When [AssertStatement] is reached it is checked against this
  /// span.
  ConditionSpan expectedSpan;

  VerifyingVisitor(this.test);

  @override
  visitProcedure(Procedure node) {
    expectedSpan = test.spans[node.name.name];
    if (expectedSpan != null) {
      super.visitProcedure(node);
      verified.add(node.name.name);
      expectedSpan = null;
    }
  }

  @override
  visitAssertStatement(AssertStatement node) {
    Expect.equals(expectedSpan.startOffset, node.conditionStartOffset);
    Expect.equals(expectedSpan.endOffset, node.conditionEndOffset);
  }
}

void main() {
  asyncTest(() async {
    Test test = generateTest();
    CompilerOptions options = new CompilerOptions()
      ..onProblem = (LocatedMessage message, Severity severity,
          String formatted, int line, int column) {
        Expect.fail("Unexpected error: $formatted");
      }
      ..strongMode = true;
    Program p = await compileScript(test.source,
        options: options, fileName: 'synthetic-test.dart');
    Expect.isNotNull(p);
    VerifyingVisitor visitor = new VerifyingVisitor(test);
    p.mainMethod.enclosingLibrary.accept(visitor);
    Expect.setEquals(test.spans.keys, visitor.verified);
  });
}
