| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library test.domain.analysis.notification.navigation; | 5 library test.domain.analysis.notification.navigation; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:analysis_server/src/analysis_server.dart'; | 9 import 'package:analysis_server/src/analysis_server.dart'; |
| 10 import 'package:analysis_server/src/computer/element.dart'; |
| 10 import 'package:analysis_server/src/constants.dart'; | 11 import 'package:analysis_server/src/constants.dart'; |
| 11 import 'package:analysis_server/src/protocol.dart'; | 12 import 'package:analysis_server/src/protocol.dart'; |
| 12 import 'package:unittest/unittest.dart'; | 13 import 'package:unittest/unittest.dart'; |
| 13 | 14 |
| 14 import 'analysis_abstract.dart'; | 15 import 'analysis_abstract.dart'; |
| 15 import 'reflective_tests.dart'; | 16 import 'reflective_tests.dart'; |
| 16 | 17 |
| 17 | 18 |
| 18 main() { | 19 main() { |
| 19 group('notification.navigation', () { | 20 group('notification.navigation', () { |
| 20 runReflectiveTests(_AnalysisNotificationNavigationTest); | 21 runReflectiveTests(_AnalysisNotificationNavigationTest); |
| 21 }); | 22 }); |
| 22 } | 23 } |
| 23 | 24 |
| 24 | 25 |
| 25 @ReflectiveTestCase() | 26 @ReflectiveTestCase() |
| 26 class _AnalysisNotificationNavigationTest extends AbstractAnalysisTest { | 27 class _AnalysisNotificationNavigationTest extends AbstractAnalysisTest { |
| 27 List<_NavigationRegion> regions; | 28 List<_NavigationRegion> regions; |
| 28 _NavigationRegion testRegion; | 29 _NavigationRegion testRegion; |
| 29 List<_NavigationTarget> testTargets; | 30 List<_NavigationTarget> testTargets; |
| 31 _NavigationTarget testTarget; |
| 30 | 32 |
| 31 @override | 33 /** |
| 32 void setUp() { | 34 * Validates that there is a target in [testTargets] with [file], at [offset] |
| 33 super.setUp(); | 35 * and with the given [length]. |
| 34 createProject(); | 36 */ |
| 37 void assertHasFileTarget(String file, int offset, int length) { |
| 38 for (_NavigationTarget target in testTargets) { |
| 39 if (target.file == file && target.offset == offset && target.length == |
| 40 length) { |
| 41 testTarget = target; |
| 42 return; |
| 43 } |
| 44 } |
| 45 fail( |
| 46 'Expected to find target (file=$file; offset=$offset; length=$length) in
\n' |
| 47 '${testRegion} in\n' '${regions.join('\n')}'); |
| 35 } | 48 } |
| 36 | 49 |
| 37 void processNotification(Notification notification) { | 50 void assertHasOperatorRegion(String regionSearch, int regionLength, |
| 38 if (notification.event == ANALYSIS_NAVIGATION) { | 51 String targetSearch, int targetLength) { |
| 39 String file = notification.getParameter(FILE); | 52 assertHasRegion(regionSearch, regionLength); |
| 40 if (file == testFile) { | 53 assertHasTarget(targetSearch, targetLength); |
| 41 regions = []; | |
| 42 List<Map<String, Object>> regionsJson = notification.getParameter(REGION
S); | |
| 43 for (Map<String, Object> regionJson in regionsJson) { | |
| 44 var regionOffset = regionJson['offset']; | |
| 45 var regionLength = regionJson['length']; | |
| 46 List<_NavigationTarget> targets = []; | |
| 47 for (Map<String, Object> targetJson in regionJson['targets']) { | |
| 48 var targetFile = targetJson['file']; | |
| 49 var targetOffset = targetJson['offset']; | |
| 50 var targetLength = targetJson['length']; | |
| 51 targets.add(new _NavigationTarget(targetFile, targetOffset, targetLe
ngth)); | |
| 52 } | |
| 53 var region = new _NavigationRegion(regionOffset, regionLength, targets
); | |
| 54 regions.add(region); | |
| 55 } | |
| 56 } | |
| 57 } | |
| 58 } | |
| 59 | |
| 60 Future prepareNavigation(then()) { | |
| 61 addAnalysisSubscription(AnalysisService.NAVIGATION, testFile); | |
| 62 return waitForTasksFinished().then((_) { | |
| 63 then(); | |
| 64 }); | |
| 65 } | 54 } |
| 66 | 55 |
| 67 /** | 56 /** |
| 68 * Finds the navigation region with the given [offset] and [length]. | |
| 69 * If [length] is `-1`, then it is ignored. | |
| 70 * | |
| 71 * If [exists] is `true`, then fails if such region does not exist. | |
| 72 * Otherwise remembers this it into [testRegion]. | |
| 73 * Also fills [testTargets] with its targets. | |
| 74 * | |
| 75 * If [exists] is `false`, then fails if such region exists. | |
| 76 */ | |
| 77 void findRegion(int offset, int length, [bool exists]) { | |
| 78 for (_NavigationRegion region in regions) { | |
| 79 if (region.offset == offset && | |
| 80 (length == -1 || region.length == length)) { | |
| 81 if (exists == false) { | |
| 82 fail('Not expected to find (offset=$offset; length=$length) in\n' | |
| 83 '${regions.join('\n')}'); | |
| 84 } | |
| 85 testRegion = region; | |
| 86 testTargets = region.targets; | |
| 87 return; | |
| 88 } | |
| 89 } | |
| 90 if (exists == true) { | |
| 91 fail('Expected to find (offset=$offset; length=$length) in\n' | |
| 92 '${regions.join('\n')}'); | |
| 93 } | |
| 94 } | |
| 95 | |
| 96 /** | |
| 97 * Validates that there is a region at the offset of [search] in [testFile]. | 57 * Validates that there is a region at the offset of [search] in [testFile]. |
| 98 * If [length] is not specified explicitly, then length of an identifier | 58 * If [length] is not specified explicitly, then length of an identifier |
| 99 * from [search] is used. | 59 * from [search] is used. |
| 100 */ | 60 */ |
| 101 void assertHasRegion(String search, [int length = -1]) { | 61 void assertHasRegion(String search, [int length = -1]) { |
| 102 int offset = findOffset(search); | 62 int offset = findOffset(search); |
| 103 if (length == -1) { | 63 if (length == -1) { |
| 104 length = findIdentifierLength(search); | 64 length = findIdentifierLength(search); |
| 105 } | 65 } |
| 106 findRegion(offset, length, true); | 66 findRegion(offset, length, true); |
| 107 } | 67 } |
| 108 | 68 |
| 109 /** | 69 /** |
| 110 * Validates that there is a region at the offset of [search] in [testFile] | 70 * Validates that there is a region at the offset of [search] in [testFile] |
| 111 * with the length of [search]. | 71 * with the length of [search]. |
| 112 */ | 72 */ |
| 113 void assertHasRegionString(String search) { | 73 void assertHasRegionString(String search) { |
| 114 int offset = findOffset(search); | 74 int offset = findOffset(search); |
| 115 int length = search.length; | 75 int length = search.length; |
| 116 findRegion(offset, length, true); | 76 findRegion(offset, length, true); |
| 117 } | 77 } |
| 118 | 78 |
| 119 /** | 79 /** |
| 80 * Validates that there is an identifier region at [regionSearch] with target |
| 81 * at [targetSearch]. |
| 82 */ |
| 83 void assertHasRegionTarget(String regionSearch, String targetSearch) { |
| 84 assertHasRegion(regionSearch); |
| 85 assertHasTarget(targetSearch); |
| 86 } |
| 87 |
| 88 /** |
| 120 * Validates that there is a target in [testTargets] with [testFile], at the | 89 * Validates that there is a target in [testTargets] with [testFile], at the |
| 121 * offset of [search] in [testFile], and with the given [length] or the length | 90 * offset of [search] in [testFile], and with the given [length] or the length |
| 122 * of an leading identifier in [search]. | 91 * of an leading identifier in [search]. |
| 123 */ | 92 */ |
| 124 void assertHasTarget(String search, [int length = -1]) { | 93 void assertHasTarget(String search, [int length = -1]) { |
| 125 int offset = findOffset(search); | 94 int offset = findOffset(search); |
| 126 if (length == -1) { | 95 if (length == -1) { |
| 127 length = findIdentifierLength(search); | 96 length = findIdentifierLength(search); |
| 128 } | 97 } |
| 129 assertHasFileTarget(testFile, offset, length); | 98 assertHasFileTarget(testFile, offset, length); |
| 130 } | 99 } |
| 131 | 100 |
| 132 /** | 101 /** |
| 133 * Validates that there is a target in [testTargets] with [file], at [offset] | |
| 134 * and with the given [length]. | |
| 135 */ | |
| 136 void assertHasFileTarget(String file, int offset, int length) { | |
| 137 for (_NavigationTarget target in testTargets) { | |
| 138 if (target.file == file && | |
| 139 target.offset == offset && | |
| 140 target.length == length) { | |
| 141 return; | |
| 142 } | |
| 143 } | |
| 144 fail('Expected to find target (file=$file; offset=$offset; length=$length) i
n\n' | |
| 145 '${testRegion} in\n' | |
| 146 '${regions.join('\n')}'); | |
| 147 } | |
| 148 | |
| 149 /** | |
| 150 * Validates that there is an identifier region at [regionSearch] with target | |
| 151 * at [targetSearch]. | |
| 152 */ | |
| 153 void assertHasRegionTarget(String regionSearch, String targetSearch) { | |
| 154 assertHasRegion(regionSearch); | |
| 155 assertHasTarget(targetSearch); | |
| 156 } | |
| 157 | |
| 158 void assertHasOperatorRegion(String regionSearch, int regionLength, | |
| 159 String targetSearch, int targetLength) { | |
| 160 assertHasRegion(regionSearch, regionLength); | |
| 161 assertHasTarget(targetSearch, targetLength); | |
| 162 } | |
| 163 | |
| 164 /** | |
| 165 * Validates that there is no a region at [search] and with the given | 102 * Validates that there is no a region at [search] and with the given |
| 166 * [length]. | 103 * [length]. |
| 167 */ | 104 */ |
| 168 void assertNoRegion(String search, int length) { | 105 void assertNoRegion(String search, int length) { |
| 169 int offset = findOffset(search); | 106 int offset = findOffset(search); |
| 170 findRegion(offset, length, false); | 107 findRegion(offset, length, false); |
| 171 } | 108 } |
| 172 | 109 |
| 173 /** | 110 /** |
| 174 * Validates that there is no a region at [search] with any length. | 111 * Validates that there is no a region at [search] with any length. |
| 175 */ | 112 */ |
| 176 void assertNoRegionAt(String search) { | 113 void assertNoRegionAt(String search) { |
| 177 int offset = findOffset(search); | 114 int offset = findOffset(search); |
| 178 findRegion(offset, -1, false); | 115 findRegion(offset, -1, false); |
| 179 } | 116 } |
| 180 | 117 |
| 181 /** | 118 /** |
| 182 * Validates that there is no a region for [search] string. | 119 * Validates that there is no a region for [search] string. |
| 183 */ | 120 */ |
| 184 void assertNoRegionString(String search) { | 121 void assertNoRegionString(String search) { |
| 185 int offset = findOffset(search); | 122 int offset = findOffset(search); |
| 186 int length = search.length; | 123 int length = search.length; |
| 187 findRegion(offset, length, false); | 124 findRegion(offset, length, false); |
| 188 } | 125 } |
| 189 | 126 |
| 127 /** |
| 128 * Finds the navigation region with the given [offset] and [length]. |
| 129 * If [length] is `-1`, then it is ignored. |
| 130 * |
| 131 * If [exists] is `true`, then fails if such region does not exist. |
| 132 * Otherwise remembers this it into [testRegion]. |
| 133 * Also fills [testTargets] with its targets. |
| 134 * |
| 135 * If [exists] is `false`, then fails if such region exists. |
| 136 */ |
| 137 void findRegion(int offset, int length, [bool exists]) { |
| 138 for (_NavigationRegion region in regions) { |
| 139 if (region.offset == offset && (length == -1 || region.length == length)) |
| 140 { |
| 141 if (exists == false) { |
| 142 fail('Not expected to find (offset=$offset; length=$length) in\n' |
| 143 '${regions.join('\n')}'); |
| 144 } |
| 145 testRegion = region; |
| 146 testTargets = region.targets; |
| 147 return; |
| 148 } |
| 149 } |
| 150 if (exists == true) { |
| 151 fail('Expected to find (offset=$offset; length=$length) in\n' |
| 152 '${regions.join('\n')}'); |
| 153 } |
| 154 } |
| 155 |
| 156 Future prepareNavigation(then()) { |
| 157 addAnalysisSubscription(AnalysisService.NAVIGATION, testFile); |
| 158 return waitForTasksFinished().then((_) { |
| 159 then(); |
| 160 }); |
| 161 } |
| 162 |
| 163 void processNotification(Notification notification) { |
| 164 if (notification.event == ANALYSIS_NAVIGATION) { |
| 165 String file = notification.getParameter(FILE); |
| 166 if (file == testFile) { |
| 167 regions = []; |
| 168 List<Map<String, Object>> regionsJson = notification.getParameter( |
| 169 REGIONS); |
| 170 for (Map<String, Object> regionJson in regionsJson) { |
| 171 var regionOffset = regionJson[OFFSET]; |
| 172 var regionLength = regionJson[LENGTH]; |
| 173 List<_NavigationTarget> targets = []; |
| 174 for (Map<String, Object> targetJson in regionJson[TARGETS]) { |
| 175 var targetFile = targetJson[FILE]; |
| 176 var targetOffset = targetJson[OFFSET]; |
| 177 var targetLength = targetJson[LENGTH]; |
| 178 var elementJson = targetJson[ELEMENT]; |
| 179 targets.add(new _NavigationTarget(targetFile, targetOffset, |
| 180 targetLength, new Element.fromJson(elementJson))); |
| 181 } |
| 182 var region = new _NavigationRegion(regionOffset, regionLength, |
| 183 targets); |
| 184 regions.add(region); |
| 185 } |
| 186 } |
| 187 } |
| 188 } |
| 189 |
| 190 @override |
| 191 void setUp() { |
| 192 super.setUp(); |
| 193 createProject(); |
| 194 } |
| 195 |
| 196 test_afterAnalysis() { |
| 197 addTestFile(''' |
| 198 class AAA {} |
| 199 AAA aaa; |
| 200 '''); |
| 201 return waitForTasksFinished().then((_) { |
| 202 return prepareNavigation(() { |
| 203 assertHasRegionTarget('AAA aaa;', 'AAA {}'); |
| 204 }); |
| 205 }); |
| 206 } |
| 207 |
| 190 test_constructor_named() { | 208 test_constructor_named() { |
| 191 addTestFile(''' | 209 addTestFile(''' |
| 192 class A { | 210 class A { |
| 193 A.named(BBB p) {} | 211 A.named(BBB p) {} |
| 194 } | 212 } |
| 195 class BBB {} | 213 class BBB {} |
| 196 '''); | 214 '''); |
| 197 return prepareNavigation(() { | 215 return prepareNavigation(() { |
| 198 // has region for complete "A.named" | 216 // has region for complete "A.named" |
| 199 assertHasRegionString('A.named'); | 217 assertHasRegionString('A.named'); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 227 class AAA { | 245 class AAA { |
| 228 int fff = 123; | 246 int fff = 123; |
| 229 AAA(this.fff); | 247 AAA(this.fff); |
| 230 } | 248 } |
| 231 '''); | 249 '''); |
| 232 return prepareNavigation(() { | 250 return prepareNavigation(() { |
| 233 assertHasRegionTarget('fff);', 'fff = 123'); | 251 assertHasRegionTarget('fff);', 'fff = 123'); |
| 234 }); | 252 }); |
| 235 } | 253 } |
| 236 | 254 |
| 237 test_afterAnalysis() { | |
| 238 addTestFile(''' | |
| 239 class AAA {} | |
| 240 AAA aaa; | |
| 241 '''); | |
| 242 return waitForTasksFinished().then((_) { | |
| 243 return prepareNavigation(() { | |
| 244 assertHasRegionTarget('AAA aaa;', 'AAA {}'); | |
| 245 }); | |
| 246 }); | |
| 247 } | |
| 248 | |
| 249 test_identifier_resolved() { | 255 test_identifier_resolved() { |
| 250 addTestFile(''' | 256 addTestFile(''' |
| 251 class AAA {} | 257 class AAA {} |
| 252 main() { | 258 main() { |
| 253 AAA aaa = null; | 259 AAA aaa = null; |
| 254 print(aaa); | 260 print(aaa); |
| 255 } | 261 } |
| 256 '''); | 262 '''); |
| 257 return prepareNavigation(() { | 263 return prepareNavigation(() { |
| 258 assertHasRegionTarget('AAA aaa', 'AAA {}'); | 264 assertHasRegionTarget('AAA aaa', 'AAA {}'); |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 // TODO(scheglov) why do we throw MemoryResourceException here? | 453 // TODO(scheglov) why do we throw MemoryResourceException here? |
| 448 // This Source/File does not exist. | 454 // This Source/File does not exist. |
| 449 // addTestFile(''' | 455 // addTestFile(''' |
| 450 //library lib; | 456 //library lib; |
| 451 //part "test_unit.dart"; | 457 //part "test_unit.dart"; |
| 452 //'''); | 458 //'''); |
| 453 // return prepareNavigation(() { | 459 // return prepareNavigation(() { |
| 454 // assertNoRegionString('part "test_unit.dart"'); | 460 // assertNoRegionString('part "test_unit.dart"'); |
| 455 // }); | 461 // }); |
| 456 } | 462 } |
| 463 |
| 464 test_targetElement() { |
| 465 addTestFile(''' |
| 466 class AAA {} |
| 467 main() { |
| 468 AAA aaa = null; |
| 469 } |
| 470 '''); |
| 471 return prepareNavigation(() { |
| 472 assertHasRegionTarget('AAA aaa', 'AAA {}'); |
| 473 Element element = testTarget.element; |
| 474 expect(element.kind, ElementKind.CLASS); |
| 475 expect(element.name, 'AAA'); |
| 476 expect(element.isAbstract, false); |
| 477 expect(element.parameters, isNull); |
| 478 expect(element.returnType, isNull); |
| 479 }); |
| 480 } |
| 457 } | 481 } |
| 458 | 482 |
| 459 | 483 |
| 460 class _NavigationRegion { | 484 class _NavigationRegion { |
| 461 final int offset; | 485 final int offset; |
| 462 final int length; | 486 final int length; |
| 463 final List<_NavigationTarget> targets; | 487 final List<_NavigationTarget> targets; |
| 464 | 488 |
| 465 _NavigationRegion(this.offset, this.length, this.targets); | 489 _NavigationRegion(this.offset, this.length, this.targets); |
| 466 } | 490 } |
| 467 | 491 |
| 468 | 492 |
| 469 class _NavigationTarget { | 493 class _NavigationTarget { |
| 470 final String file; | 494 final String file; |
| 471 final int offset; | 495 final int offset; |
| 472 final int length; | 496 final int length; |
| 497 final Element element; |
| 473 | 498 |
| 474 _NavigationTarget(this.file, this.offset, this.length); | 499 _NavigationTarget(this.file, this.offset, this.length, this.element); |
| 475 } | 500 } |
| OLD | NEW |