| Index: pkg/analysis_server/test/analysis_notification_navigation_test.dart
|
| diff --git a/pkg/analysis_server/test/analysis_notification_navigation_test.dart b/pkg/analysis_server/test/analysis_notification_navigation_test.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..62787b78074c684eef2a9af5172aba2b09caab7d
|
| --- /dev/null
|
| +++ b/pkg/analysis_server/test/analysis_notification_navigation_test.dart
|
| @@ -0,0 +1,420 @@
|
| +// 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.domain.analysis.notification.navigation;
|
| +
|
| +import 'dart:async';
|
| +
|
| +import 'package:analysis_server/src/constants.dart';
|
| +import 'package:analysis_server/src/protocol.dart';
|
| +import 'package:unittest/unittest.dart';
|
| +
|
| +import 'analysis_abstract_test.dart';
|
| +import 'reflective_tests.dart';
|
| +
|
| +
|
| +@ReflectiveTestCase()
|
| +class AnalysisNotificationNavigationTest extends AbstractAnalysisTest {
|
| + List<Map<String, Object>> regions;
|
| + Map<String, Object> testRegion;
|
| + List<Map<String, Object>> testTargets;
|
| +
|
| + void processNotification(Notification notification) {
|
| + if (notification.event == NOTIFICATION_NAVIGATION) {
|
| + String file = notification.getParameter(FILE);
|
| + if (file == testFile) {
|
| + regions = notification.getParameter(REGIONS);
|
| + }
|
| + }
|
| + }
|
| +
|
| + Future prepareNavigation(then()) {
|
| + // TODO(scheglov) add subscription
|
| +// addAnalysisSubscriptionHighlight(testFile);
|
| + return waitForTasksFinished().then((_) {
|
| + then();
|
| + });
|
| + }
|
| +
|
| + /**
|
| + * Finds the navigation region with the given [offset] and [length].
|
| + * If [length] is `-1`, then it is ignored.
|
| + *
|
| + * If [exists] is `true`, then fails if such region does not exist.
|
| + * Otherwise remembers this it into [testRegion].
|
| + * Also fills [testTargets] with its targets.
|
| + *
|
| + * If [exists] is `false`, then fails if such region exists.
|
| + */
|
| + void findRegion(int offset, int length, [bool exists]) {
|
| + for (Map<String, Object> region in regions) {
|
| + if (region['offset'] == offset &&
|
| + (length == -1 || region['length'] == length)) {
|
| + if (exists == false) {
|
| + fail('Not expected to find (offset=$offset; length=$length) in\n'
|
| + '${regions.join('\n')}');
|
| + }
|
| + testRegion = region;
|
| + testTargets = region['targets'];
|
| + return;
|
| + }
|
| + }
|
| + if (exists == true) {
|
| + fail('Expected to find (offset=$offset; length=$length) in\n'
|
| + '${regions.join('\n')}');
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Validates that there is a region at the offset of [search] in [testFile].
|
| + * If [length] is not specified explicitly, then length of an identifier
|
| + * from [search] is used.
|
| + */
|
| + void assertHasRegion(String search, [int length = -1]) {
|
| + int offset = findOffset(search);
|
| + if (length == -1) {
|
| + length = findIdentifierLength(search);
|
| + }
|
| + findRegion(offset, length, true);
|
| + }
|
| +
|
| + /**
|
| + * Validates that there is a region at the offset of [search] in [testFile]
|
| + * with the length of [search].
|
| + */
|
| + void assertHasRegionString(String search) {
|
| + int offset = findOffset(search);
|
| + int length = search.length;
|
| + findRegion(offset, length, true);
|
| + }
|
| +
|
| + /**
|
| + * Validates that there is a target in [testTargets] with [testFile], at the
|
| + * offset of [search] in [testFile], and with the given [length] or the length
|
| + * of an leading identifier in [search].
|
| + */
|
| + void assertHasTarget(String search, [int length = -1]) {
|
| + int offset = findOffset(search);
|
| + if (length == -1) {
|
| + length = findIdentifierLength(search);
|
| + }
|
| + for (Map<String, Object> target in testTargets) {
|
| + if (target['file'] == testFile &&
|
| + target['offset'] == offset &&
|
| + target['length'] == length) {
|
| + return;
|
| + }
|
| + }
|
| + fail('Expected to find target (offset=$offset; length=$length) in\n'
|
| + '${testRegion} in\n'
|
| + '${regions.join('\n')}');
|
| + }
|
| +
|
| + /**
|
| + * Validates that there is a target in [testTargets] with [file], at [offset]
|
| + * and with the given [length].
|
| + */
|
| + void assertHasFileTarget(String file, int offset, int length) {
|
| + for (Map<String, Object> target in testTargets) {
|
| + if (target['file'] == file &&
|
| + target['offset'] == offset &&
|
| + target['length'] == length) {
|
| + return;
|
| + }
|
| + }
|
| + fail('Expected to find target (file=$file; offset=$offset; length=$length) in\n'
|
| + '${testRegion} in\n'
|
| + '${regions.join('\n')}');
|
| + }
|
| +
|
| + /**
|
| + * Validates that there is an identifier region at [regionSearch] with target
|
| + * at [targetSearch].
|
| + */
|
| + void assertHasRegionTarget(String regionSearch, String targetSearch) {
|
| + assertHasRegion(regionSearch);
|
| + assertHasTarget(targetSearch);
|
| + }
|
| +
|
| + void assertHasOperatorRegion(String regionSearch, int regionLength,
|
| + String targetSearch, int targetLength) {
|
| + assertHasRegion(regionSearch, regionLength);
|
| + assertHasTarget(targetSearch, targetLength);
|
| + }
|
| +
|
| + /**
|
| + * Validates that there is no a region at [search] and with the given
|
| + * [length].
|
| + */
|
| + void assertNoRegion(String search, int length) {
|
| + int offset = findOffset(search);
|
| + findRegion(offset, length, false);
|
| + }
|
| +
|
| + /**
|
| + * Validates that there is no a region at [search] with any length.
|
| + */
|
| + void assertNoRegionAt(String search) {
|
| + int offset = findOffset(search);
|
| + findRegion(offset, -1, false);
|
| + }
|
| +
|
| + /**
|
| + * Validates that there is no a region for [search] string.
|
| + */
|
| + void assertNoRegionString(String search) {
|
| + int offset = findOffset(search);
|
| + int length = search.length;
|
| + findRegion(offset, length, false);
|
| + }
|
| +
|
| + test_constructor_named() {
|
| + addTestFile('''
|
| +class A {
|
| + A.named(BBB p) {}
|
| +}
|
| +class BBB {}
|
| +''');
|
| + return prepareNavigation(() {
|
| + // has region for complete "A.named"
|
| + assertHasRegionString('A.named');
|
| + assertHasTarget('named(BBB');
|
| + // no separate regions for "A" and "named"
|
| + assertNoRegion('A.named(', 'A'.length);
|
| + assertNoRegion('named(', 'named'.length);
|
| + // validate that we don't forget to resolve parameters
|
| + assertHasRegionTarget('BBB p', 'BBB {}');
|
| + });
|
| + }
|
| +
|
| + test_constructor_unnamed() {
|
| + addTestFile('''
|
| +class A {
|
| + A(BBB p) {}
|
| +}
|
| +class BBB {}
|
| +''');
|
| + return prepareNavigation(() {
|
| + // has region for complete "A.named"
|
| + assertHasRegion("A(BBB");
|
| + assertHasTarget("A(BBB", 0);
|
| + // validate that we don't forget to resolve parameters
|
| + assertHasRegionTarget('BBB p', 'BBB {}');
|
| + });
|
| + }
|
| +
|
| + test_fieldFormalParameter() {
|
| + addTestFile('''
|
| +class AAA {
|
| + int fff = 123;
|
| + AAA(this.fff);
|
| +}
|
| +''');
|
| + return prepareNavigation(() {
|
| + assertHasRegionTarget('fff);', 'fff = 123');
|
| + });
|
| + }
|
| +
|
| + test_identifier_resolved() {
|
| + addTestFile('''
|
| +class AAA {}
|
| +main() {
|
| + AAA aaa = null;
|
| + print(aaa);
|
| +}
|
| +''');
|
| + return prepareNavigation(() {
|
| + assertHasRegionTarget('AAA aaa', 'AAA {}');
|
| + assertHasRegionTarget('aaa);', 'aaa = null');
|
| + assertHasRegionTarget('main() {', 'main() {');
|
| + });
|
| + }
|
| +
|
| + test_identifier_unresolved() {
|
| + addTestFile('''
|
| +main() {
|
| + print(vvv);
|
| +}
|
| +''');
|
| + return prepareNavigation(() {
|
| + assertNoRegionString('vvv');
|
| + });
|
| + }
|
| +
|
| + test_instanceCreation_named() {
|
| + addTestFile('''
|
| +class A {
|
| + A.named() {}
|
| +}
|
| +main() {
|
| + new A.named();
|
| +}
|
| +''');
|
| + return prepareNavigation(() {
|
| + assertHasRegionString('new A.named');
|
| + assertHasTarget('named() {}');
|
| + });
|
| + }
|
| +
|
| + test_instanceCreation_unnamed() {
|
| + addTestFile('''
|
| +class A {
|
| + A() {}
|
| +}
|
| +main() {
|
| + new A();
|
| +}
|
| +''');
|
| + return prepareNavigation(() {
|
| + assertHasRegionString('new A');
|
| + assertHasTarget("A() {}", 0);
|
| + });
|
| + }
|
| +
|
| + test_operator_arithmetic() {
|
| + addTestFile('''
|
| +class A {
|
| + A operator +(other) => null;
|
| + A operator -() => null;
|
| + A operator -(other) => null;
|
| + A operator *(other) => null;
|
| + A operator /(other) => null;
|
| +}
|
| +main() {
|
| + var a = new A();
|
| + a - 1;
|
| + a + 2;
|
| + -a; // unary
|
| + --a;
|
| + ++a;
|
| + a--; // mm
|
| + a++; // pp
|
| + a -= 3;
|
| + a += 4;
|
| + a *= 5;
|
| + a /= 6;
|
| +}
|
| +''');
|
| + return prepareNavigation(() {
|
| + assertHasOperatorRegion('- 1', 1, '-(other) => null', 1);
|
| + assertHasOperatorRegion('+ 2', 1, '+(other) => null', 1);
|
| + assertHasOperatorRegion('-a; // unary', 1, '-() => null', 1);
|
| + assertHasOperatorRegion('--a;', 2, '-(other) => null', 1);
|
| + assertHasOperatorRegion('++a;', 2, '+(other) => null', 1);
|
| + assertHasOperatorRegion('--; // mm', 2, '-(other) => null', 1);
|
| + assertHasOperatorRegion('++; // pp', 2, '+(other) => null', 1);
|
| + assertHasOperatorRegion('-= 3', 2, '-(other) => null', 1);
|
| + assertHasOperatorRegion('+= 4', 2, '+(other) => null', 1);
|
| + assertHasOperatorRegion('*= 5', 2, '*(other) => null', 1);
|
| + assertHasOperatorRegion('/= 6', 2, '/(other) => null', 1);
|
| + });
|
| + }
|
| +
|
| + test_operator_index() {
|
| + addTestFile('''
|
| +class A {
|
| + A operator +(other) => null;
|
| +}
|
| +class B {
|
| + A operator [](index) => null;
|
| + operator []=(index, A value) {}
|
| +}
|
| +main() {
|
| + var b = new B();
|
| + b[0] // [];
|
| + b[1] = 1; // []=;
|
| + b[2] += 2;
|
| +}
|
| +''');
|
| + return prepareNavigation(() {
|
| + assertHasOperatorRegion('] // []', 1, '[](index)', 2);
|
| + assertHasOperatorRegion('] = 1;', 1, '[]=(index,', 3);
|
| + assertHasOperatorRegion('] += 2;', 1, '[]=(index,', 3);
|
| + assertHasOperatorRegion('+= 2;', 2, '+(other)', 1);
|
| + });
|
| + }
|
| +
|
| + test_partOf() {
|
| + var libCode = 'library lib; part "test.dart";';
|
| + var libFile = addFile('$projectPath/bin/lib.dart', libCode);
|
| + addTestFile('part of lib;');
|
| + return prepareNavigation(() {
|
| + assertHasRegionString('part of lib');
|
| + assertHasFileTarget(libFile, libCode.indexOf('lib;'), 'lib'.length);
|
| + });
|
| + }
|
| +
|
| + test_string_export() {
|
| + var libCode = 'library lib;';
|
| + var libFile = addFile('$projectPath/bin/lib.dart', libCode);
|
| + addTestFile('export "lib.dart";');
|
| + return prepareNavigation(() {
|
| + assertHasRegionString('export "lib.dart"');
|
| + assertHasFileTarget(libFile, libCode.indexOf('lib;'), 'lib'.length);
|
| + });
|
| + }
|
| +
|
| + test_string_export_unresolvedUri() {
|
| + addTestFile('export "no.dart";');
|
| + return prepareNavigation(() {
|
| + assertNoRegionString('export "no.dart"');
|
| + });
|
| + }
|
| +
|
| + test_string_import() {
|
| + var libCode = 'library lib;';
|
| + var libFile = addFile('$projectPath/bin/lib.dart', libCode);
|
| + addTestFile('import "lib.dart";');
|
| + return prepareNavigation(() {
|
| + assertHasRegionString('import "lib.dart"');
|
| + assertHasFileTarget(libFile, libCode.indexOf('lib;'), 'lib'.length);
|
| + });
|
| + }
|
| +
|
| + test_string_import_noUri() {
|
| + addTestFile('import ;');
|
| + return prepareNavigation(() {
|
| + assertNoRegionAt('import ;');
|
| + });
|
| + }
|
| +
|
| + test_string_import_unresolvedUri() {
|
| + addTestFile('import "no.dart";');
|
| + return prepareNavigation(() {
|
| + assertNoRegionString('import "no.dart"');
|
| + });
|
| + }
|
| +
|
| + test_string_part() {
|
| + var unitCode = 'part of lib; f() {}';
|
| + var unitFile = addFile('$projectPath/bin/test_unit.dart', unitCode);
|
| + addTestFile('''
|
| +library lib;
|
| +part "test_unit.dart";
|
| +''');
|
| + return prepareNavigation(() {
|
| + assertHasRegionString('part "test_unit.dart"');
|
| + assertHasFileTarget(unitFile, 0, 0);
|
| + });
|
| + }
|
| +
|
| + test_string_part_unresolvedUri() {
|
| + // TODO(scheglov) why do we throw MemoryResourceException here?
|
| + // This Source/File does not exist.
|
| +// addTestFile('''
|
| +//library lib;
|
| +//part "test_unit.dart";
|
| +//''');
|
| +// return prepareNavigation(() {
|
| +// assertNoRegionString('part "test_unit.dart"');
|
| +// });
|
| + }
|
| +}
|
| +
|
| +
|
| +main() {
|
| + group('notification.navigation', () {
|
| + runReflectiveTests(AnalysisNotificationNavigationTest);
|
| + });
|
| +}
|
|
|