// 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.

library test.integration.analysis.navigation;

import 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:unittest/unittest.dart';

import '../../utils.dart';
import '../integration_tests.dart';

main() {
  initializeTestEnvironment();
  defineReflectiveTests(AnalysisNavigationTest);
}

@reflectiveTest
class AnalysisNavigationTest extends AbstractAnalysisServerIntegrationTest {
  test_navigation() {
    String pathname1 = sourcePath('test1.dart');
    String text1 = r'''
library foo;

import 'dart:async';
part 'test2.dart';

class Class<TypeParameter> {
  Class.constructor(); /* constructor declaration */

  TypeParameter field;

  method() {}
}

typedef FunctionTypeAlias();

function(FunctionTypeAlias parameter) {
  print(parameter());
}

int topLevelVariable;

main() {
  Class<int> localVariable = new Class<int>.constructor(); // usage
  function(() => localVariable.field);
  localVariable.method();
  localVariable.field = 1;
}
''';
    writeFile(pathname1, text1);
    String pathname2 = sourcePath('test2.dart');
    String text2 = r'''
part of foo;
''';
    writeFile(pathname2, text2);
    standardAnalysisSetup();
    sendAnalysisSetSubscriptions({
      AnalysisService.NAVIGATION: [pathname1]
    });
    List<NavigationRegion> regions;
    List<NavigationTarget> targets;
    List<String> targetFiles;
    onAnalysisNavigation.listen((AnalysisNavigationParams params) {
      expect(params.file, equals(pathname1));
      regions = params.regions;
      targets = params.targets;
      targetFiles = params.files;
    });
    return analysisFinished.then((_) {
      // There should be a single error, due to the fact that 'dart:async' is
      // not used.
      expect(currentAnalysisErrors[pathname1], hasLength(1));
      expect(currentAnalysisErrors[pathname2], isEmpty);
      NavigationTarget findTargetElement(int index) {
        for (NavigationRegion region in regions) {
          if (region.offset <= index && index < region.offset + region.length) {
            expect(region.targets, hasLength(1));
            int targetIndex = region.targets[0];
            return targets[targetIndex];
          }
        }
        fail('No element found for index $index');
        return null;
      }
      void checkLocal(
          String source, String expectedTarget, ElementKind expectedKind) {
        int sourceIndex = text1.indexOf(source);
        int targetIndex = text1.indexOf(expectedTarget);
        NavigationTarget element = findTargetElement(sourceIndex);
        expect(targetFiles[element.fileIndex], equals(pathname1));
        expect(element.offset, equals(targetIndex));
        expect(element.kind, equals(expectedKind));
      }
      void checkRemote(String source, String expectedTargetRegexp,
          ElementKind expectedKind) {
        int sourceIndex = text1.indexOf(source);
        NavigationTarget element = findTargetElement(sourceIndex);
        expect(targetFiles[element.fileIndex], matches(expectedTargetRegexp));
        expect(element.kind, equals(expectedKind));
      }
      // TODO(paulberry): will the element type 'CLASS_TYPE_ALIAS' ever appear
      // as a navigation target?
      checkLocal('Class<int>', 'Class<TypeParameter>', ElementKind.CLASS);
      checkRemote(
          "'test2.dart';", r'test2.dart$', ElementKind.COMPILATION_UNIT);
      checkLocal(
          'Class<int>.constructor',
          'constructor(); /* constructor declaration */',
          ElementKind.CONSTRUCTOR);
      checkLocal(
          'constructor(); // usage',
          'constructor(); /* constructor declaration */',
          ElementKind.CONSTRUCTOR);
      checkLocal('field;', 'field;', ElementKind.FIELD);
      checkLocal('function(() => localVariable.field)',
          'function(FunctionTypeAlias parameter)', ElementKind.FUNCTION);
      checkLocal('FunctionTypeAlias parameter', 'FunctionTypeAlias();',
          ElementKind.FUNCTION_TYPE_ALIAS);
      checkLocal('field)', 'field;', ElementKind.GETTER);
      checkRemote("'dart:async'", r'async\.dart$', ElementKind.LIBRARY);
      checkLocal(
          'localVariable.field', 'localVariable =', ElementKind.LOCAL_VARIABLE);
      checkLocal('method();', 'method() {', ElementKind.METHOD);
      checkLocal('parameter());', 'parameter) {', ElementKind.PARAMETER);
      checkLocal('field = 1', 'field;', ElementKind.SETTER);
      checkLocal('topLevelVariable;', 'topLevelVariable;',
          ElementKind.TOP_LEVEL_VARIABLE);
      checkLocal(
          'TypeParameter field;', 'TypeParameter>', ElementKind.TYPE_PARAMETER);
    });
  }
}
