Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1365)

Unified Diff: pkg/analysis_server/test/analysis_notification_navigation_test.dart

Issue 314493002: Navigation computer and two variants of tests for it. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
+ });
+}

Powered by Google App Engine
This is Rietveld 408576698