blob: 2dcb07420b3079f00159f2f206ebe9e72d63d82c [file] [log] [blame]
// 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 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../integration_tests.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AnalysisNavigationTest);
defineReflectiveTests(AnalysisNavigationTest_Driver);
});
}
class AbstractAnalysisNavigationTest
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);
});
}
}
@reflectiveTest
class AnalysisNavigationTest extends AbstractAnalysisNavigationTest {}
@reflectiveTest
class AnalysisNavigationTest_Driver extends AbstractAnalysisNavigationTest {
@override
bool get enableNewAnalysisDriver => true;
}