// Copyright (c) 2016, 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.

// @dart = 2.7

library jsinterop.abstract_test;

import 'package:expect/expect.dart';
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/common.dart';
import 'package:compiler/src/commandline_options.dart';
import '../helpers/memory_compiler.dart';

const List<Test> TESTS = const <Test>[
  const Test('Empty js-interop class.', '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
class A {}

main() => new A();
''', warnings: const []),
  const Test('Js-interop class with external method.', '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
class A {
  external method();
}

main() => new A();
'''),
  const Test(
      'Js-interop class with external method with required parameters.', '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
class A {
  external method(a, b);
}

main() => new A();
'''),
  const Test(
      'Js-interop class with external method with optional parameters.', '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
class A {
  external method([a, b]);
}

main() => new A();
'''),
  const Test(
      'Js-interop class with external method with optional parameters '
          'with default values.',
      '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
class A {
  external method([a = 1, b = 2]);
}

main() => new A();
'''),
  const Test('Js-interop class with static method.', '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
class A {
  static method() {}
}

main() => new A();
'''),
  const Test(
      'Js-interop class with abstract getter.',
      '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
class A {
  get foo;
}

main() => new A();
''',
      warnings: const [MessageKind.ABSTRACT_GETTER],
      skipForKernel: true),
  const Test('Js-interop class that extends a js-interop class.', '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
abstract class A {
  method();
}

@JS()
class B extends A {
  external method();
}

main() => new B();
'''),
  const Test(
      'Js-interop class that extends a js-interop class, '
          'reversed declaration order.',
      '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
class B extends A {
  external method();
}

@JS()
abstract class A {
  method();
}

main() => new B();
'''),
  const Test.multi(
      'Js-interop class that extends a js-interop class from a different '
      'library.',
      const {
        'main.dart': '''
@JS()
library test;

import 'package:js/js.dart';
import 'other.dart';

@JS()
class B extends A {
  external method();
}

main() => new B();
''',
        'other.dart': '''
@JS()
library other;

import 'package:js/js.dart';

@JS()
abstract class A {
  method();
}
'''
      }),
  const Test('Js-interop class that implements a regular class.', '''
@JS()
library test;

import 'package:js/js.dart';

abstract class A {
  method();
}

@JS()
class B implements A {
  external method();
}

main() => new B();
'''),
  const Test('Js-interop class that implements a js-interop class.', '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
abstract class A {
  method();
}

@JS()
class B implements A {
  external method();
}

main() => new B();
'''),
  const Test('Js-interop class with generative constructor.', '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
class A {
  external A();
}

main() => new A();
'''),
  const Test('Js-interop class with factory constructor.', '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
class A {
  factory A() => null;
}

main() => new A();
'''),
  const Test('Empty anonymous js-interop class.', '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
@anonymous
class A {}

main() => new A();
'''),
  const Test('Anonymous js-interop class with generative constructor.', '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
@anonymous
class A {
  external A();
}

main() => new A();
'''),
  const Test('Anonymous js-interop class with factory constructor.', '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
@anonymous
class A {
  factory A() => null;
}

main() => new A();
'''),
  const Test(
      'Anonymous js-interop class with external factory constructor.', '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
@anonymous
class A {
  external factory A();
}

main() => new A();
'''),
  const Test('External factory constructor with named parameters.', '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
@anonymous
class A {
  external factory A({a, b});
}

main() => new A(a: 1);
'''),
  const Test(
      'External factory constructor with named parameters '
          'with default parameters.',
      '''
@JS()
library test;

import 'package:js/js.dart';

@JS()
@anonymous
class A {
  external factory A({a: 1, b: 2});
}

main() => new A(a: 1);
'''),
  const Test('Function-typed return type', '''
@JS()
library lib;

import 'package:js/js.dart';

@JS('func')
external int Function() func();

main() {
  func();
}
'''),
  const Test(
    'Non-external field.',
    '''
@JS()
library lib;

import 'package:js/js.dart';

@JS()
@anonymous
class B {
  int Function() callback;
}

@JS('makeB')
external B makeB();

main() {
  makeB().callback();
}
''',
    // TODO(34174): Disallow js-interop fields.
    /*errors: const [MessageKind.IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED]*/
  ),
];

void main(List<String> args) {
  asyncTest(() async {
    for (Test test in TESTS) {
      bool run = true;
      if (args.isNotEmpty) {
        run = false;
        for (String arg in args) {
          if (test.name.contains(arg)) {
            run = true;
            break;
          }
        }
      }
      if (run) {
        await runTest(test);
      }
    }
  });
}

class Test {
  final String name;
  final String _source;
  final Map<String, String> _sources;
  final List<MessageKind> errors;
  final List<MessageKind> warnings;
  final bool skipForKernel;

  const Test(this.name, this._source,
      {this.errors: const <MessageKind>[],
      this.warnings: const <MessageKind>[],
      this.skipForKernel: false})
      : _sources = null;

  const Test.multi(this.name, this._sources,
      {this.errors: const <MessageKind>[],
      this.warnings: const <MessageKind>[],
      this.skipForKernel: false})
      : _source = null;

  String get source => _source != null ? _source : _sources['main.dart'];

  Map<String, String> get sources =>
      _source != null ? {'main.dart': _source} : _sources;
}

runTest(Test test) async {
  print('==${test.name}======================================================');
  print(test.source);
  if (!test.skipForKernel) {
    await runTestInternal(test);
  }
}

runTestInternal(Test test) async {
  DiagnosticCollector collector = new DiagnosticCollector();
  List<String> options = <String>[];
  // TODO(redemption): Enable inlining.
  options.add(Flags.disableInlining);
  await runCompiler(
      diagnosticHandler: collector,
      options: options,
      memorySourceFiles: test.sources);
  Expect.equals(
      test.errors.length, collector.errors.length, 'Unexpected error count.');
  Expect.equals(test.warnings.length, collector.warnings.length,
      'Unexpected warning count.');
  for (int index = 0; index < test.errors.length; index++) {
    Expect.equals(test.errors[index],
        collector.errors.elementAt(index).messageKind, 'Unexpected error.');
  }
  for (int index = 0; index < test.warnings.length; index++) {
    Expect.equals(test.warnings[index],
        collector.warnings.elementAt(index).messageKind, 'Unexpected warning.');
  }
}
