// 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);
  });
}

@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.
   */
  Future<AnalysisGetHoverResult> 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,
  }) {
    int offset = text.indexOf(target);
    return sendAnalysisGetHover(pathname, offset).then((result) async {
      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));
        }
      }
      return null;
    });
  }

  /**
   * 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));
      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: ['.*']));
      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);
    });
  }
}
