// Copyright (c) 2014, 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 'dart:async';

import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../support/integration_tests.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(AnalysisGetHoverIntegrationTest);
    defineReflectiveTests(AnalysisGetHoverIntegrationTest_UseCFE);
  });
}

@reflectiveTest
class AnalysisGetHoverIntegrationTest
    extends AbstractAnalysisServerIntegrationTest {
  /**
   * Pathname of the file containing Dart code.
   */
  String pathname;

  /**
   * Dart code under test.
   */
  final String text = r'''
library lib.test;

List topLevelVar;

/**
 * Documentation for func
 */
void func(int param) {
  num localVar = topLevelVar.length;
  topLevelVar.length = param;
  topLevelVar.add(localVar);
}

main() {
  // comment
  func(35);
}
''';

  /**
   * Check that a getHover request on the substring [target] produces a result
   * which has length [length], has an elementDescription matching every
   * regexp in [descriptionRegexps], has a kind of [kind], and has a staticType
   * matching [staticTypeRegexps].
   *
   * [isCore] means the hover info should indicate that the element is defined
   * in dart.core.  [docRegexp], if specified, should match the documentation
   * string of the element.  [isLiteral] means the hover should indicate a
   * literal value.  [parameterRegexps] means is a set of regexps which should
   * match the hover parameters.  [propagatedType], if specified, is the
   * expected propagated type of the element.
   */
  checkHover(String target, int length, List<String> descriptionRegexps,
      String kind, List<String> staticTypeRegexps,
      {bool isLocal: false,
      bool isCore: false,
      String docRegexp: null,
      bool isLiteral: false,
      List<String> parameterRegexps: null,
      propagatedType: null}) {
    int offset = text.indexOf(target);
    return sendAnalysisGetHover(pathname, offset).then((result) {
      expect(result.hovers, hasLength(1));
      HoverInformation info = result.hovers[0];
      expect(info.offset, equals(offset));
      expect(info.length, equals(length));
      if (isCore) {
        expect(path.basename(info.containingLibraryPath), equals('core.dart'));
        expect(info.containingLibraryName, equals('dart.core'));
      } else if (isLocal || isLiteral) {
        expect(info.containingLibraryPath, isNull);
        expect(info.containingLibraryName, isNull);
      } else {
        expect(info.containingLibraryPath, equals(pathname));
        expect(info.containingLibraryName, equals('lib.test'));
      }
      if (docRegexp == null) {
        expect(info.dartdoc, isNull);
      } else {
        expect(info.dartdoc, matches(docRegexp));
      }
      if (descriptionRegexps == null) {
        expect(info.elementDescription, isNull);
      } else {
        expect(info.elementDescription, isString);
        for (String descriptionRegexp in descriptionRegexps) {
          expect(info.elementDescription, matches(descriptionRegexp));
        }
      }
      expect(info.elementKind, equals(kind));
      if (parameterRegexps == null) {
        expect(info.parameter, isNull);
      } else {
        expect(info.parameter, isString);
        for (String parameterRegexp in parameterRegexps) {
          expect(info.parameter, matches(parameterRegexp));
        }
      }
      if (staticTypeRegexps == null) {
        expect(info.staticType, isNull);
      } else {
        expect(info.staticType, isString);
        for (String staticTypeRegexp in staticTypeRegexps) {
          expect(info.staticType, matches(staticTypeRegexp));
        }
      }
    });
  }

  /**
   * Check that a getHover request on the substring [target] produces no
   * results.
   */
  Future checkNoHover(String target) {
    int offset = text.indexOf(target);
    return sendAnalysisGetHover(pathname, offset).then((result) {
      expect(result.hovers, hasLength(0));
    });
  }

  setUp() {
    return super.setUp().then((_) {
      pathname = sourcePath('test.dart');
    });
  }

  test_getHover() {
    writeFile(pathname, text);
    standardAnalysisSetup();

    // Note: analysis.getHover doesn't wait for analysis to complete--it simply
    // returns the latest results that are available at the time that the
    // request is made.  So wait for analysis to finish before testing anything.
    return analysisFinished.then((_) {
      List<Future> tests = [];
      tests.add(checkHover('topLevelVar;', 11, ['List', 'topLevelVar'],
          'top level variable', ['List']));
      tests.add(checkHover(
          'func(', 4, ['func', 'int', 'param'], 'function', null,
          docRegexp: 'Documentation for func'));
      tests.add(checkHover('int param', 3, ['int'], 'class', null,
          isCore: true, docRegexp: '.*'));
      tests.add(checkHover('param)', 5, ['int', 'param'], 'parameter', ['int'],
          isLocal: true, docRegexp: 'Documentation for func'));
      tests.add(checkHover('num localVar', 3, ['num'], 'class', null,
          isCore: true, docRegexp: '.*'));
      tests.add(checkHover(
          'localVar =', 8, ['num', 'localVar'], 'local variable', ['num'],
          isLocal: true, propagatedType: 'int'));
      tests.add(checkHover('topLevelVar.length;', 11, ['List', 'topLevelVar'],
          'top level variable', ['List']));
      tests.add(checkHover(
          'length;', 6, ['get', 'length', 'int'], 'getter', null,
          isCore: true, docRegexp: '.*'));
      tests.add(checkHover(
          'length =', 6, ['set', 'length', 'int'], 'setter', null,
          isCore: true, docRegexp: '.*'));
      tests.add(checkHover('param;', 5, ['int', 'param'], 'parameter', ['int'],
          isLocal: true,
          docRegexp: 'Documentation for func',
          parameterRegexps: ['.*']));
      tests.add(checkHover(
          'add(', 3, ['List', 'add'], 'method', ['dynamic', 'void'],
          isCore: true, docRegexp: '.*'));
      tests.add(checkHover(
          'localVar)', 8, ['num', 'localVar'], 'local variable', ['num'],
          isLocal: true, parameterRegexps: ['.*'], propagatedType: 'int'));
      tests.add(checkHover(
          'func(35', 4, ['func', 'int', 'param'], 'function', ['int', 'void'],
          docRegexp: 'Documentation for func'));
      tests.add(checkHover('35', 2, null, null, ['int'],
          isLiteral: true, parameterRegexps: ['int', 'param']));
      tests.add(checkNoHover('comment'));
      return Future.wait(tests);
    });
  }
}

@reflectiveTest
class AnalysisGetHoverIntegrationTest_UseCFE
    extends AnalysisGetHoverIntegrationTest {
  @override
  bool get useCFE => true;

  @override
  @failingTest
  test_getHover() {
    // TODO(devoncarew): NoSuchMethodError: The getter 'canonicalName' was called on null.
    return super.test_getHover();
  }
}
