| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'dart:async'; |
| 6 |
| 5 import 'package:analysis_server/src/services/index/index.dart'; | 7 import 'package:analysis_server/src/services/index/index.dart'; |
| 6 import 'package:analyzer/dart/ast/ast.dart'; | 8 import 'package:analyzer/dart/ast/ast.dart'; |
| 7 import 'package:analyzer/dart/element/element.dart'; | 9 import 'package:analyzer/dart/element/element.dart'; |
| 8 import 'package:analyzer/src/generated/source.dart'; | 10 import 'package:analyzer/src/generated/source.dart'; |
| 9 import 'package:analyzer/src/summary/idl.dart'; | 11 import 'package:analyzer/src/summary/idl.dart'; |
| 10 import 'package:test/test.dart'; | 12 import 'package:test/test.dart'; |
| 11 import 'package:test_reflective_loader/test_reflective_loader.dart'; | 13 import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| 12 import 'package:typed_mock/typed_mock.dart'; | 14 import 'package:typed_mock/typed_mock.dart'; |
| 13 | 15 |
| 14 import '../../abstract_single_unit.dart'; | 16 import '../../abstract_single_unit.dart'; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 void setUp() { | 74 void setUp() { |
| 73 super.setUp(); | 75 super.setUp(); |
| 74 } | 76 } |
| 75 | 77 |
| 76 void tearDown() { | 78 void tearDown() { |
| 77 super.tearDown(); | 79 super.tearDown(); |
| 78 index = null; | 80 index = null; |
| 79 } | 81 } |
| 80 | 82 |
| 81 test_getDefinedNames_classMember() async { | 83 test_getDefinedNames_classMember() async { |
| 82 _indexTestUnit(''' | 84 await _indexTestUnit(''' |
| 83 class A { | 85 class A { |
| 84 test() {} | 86 test() {} |
| 85 } | 87 } |
| 86 class B { | 88 class B { |
| 87 int test = 1; | 89 int test = 1; |
| 88 main() { | 90 main() { |
| 89 int test = 2; | 91 int test = 2; |
| 90 } | 92 } |
| 91 } | 93 } |
| 92 '''); | 94 '''); |
| 93 ClassElement classA = findElement('A'); | 95 ClassElement classA = findElement('A'); |
| 94 ClassElement classB = findElement('B'); | 96 ClassElement classB = findElement('B'); |
| 95 List<Location> locations = await index.getDefinedNames( | 97 List<Location> locations = await index.getDefinedNames( |
| 96 new RegExp(r'^test$'), IndexNameKind.classMember); | 98 new RegExp(r'^test$'), IndexNameKind.classMember); |
| 97 expect(locations, hasLength(2)); | 99 expect(locations, hasLength(2)); |
| 98 _assertHasDefinedName(locations, classA.methods[0]); | 100 _assertHasDefinedName(locations, classA.methods[0]); |
| 99 _assertHasDefinedName(locations, classB.fields[0]); | 101 _assertHasDefinedName(locations, classB.fields[0]); |
| 100 } | 102 } |
| 101 | 103 |
| 102 test_getDefinedNames_topLevel() async { | 104 test_getDefinedNames_topLevel() async { |
| 103 _indexTestUnit(''' | 105 await _indexTestUnit(''' |
| 104 class A {} // A | 106 class A {} // A |
| 105 class B = Object with A; | 107 class B = Object with A; |
| 106 typedef C(); | 108 typedef C(); |
| 107 D() {} | 109 D() {} |
| 108 var E = null; | 110 var E = null; |
| 109 class NoMatchABCDE {} | 111 class NoMatchABCDE {} |
| 110 '''); | 112 '''); |
| 111 Element topA = findElement('A'); | 113 Element topA = findElement('A'); |
| 112 Element topB = findElement('B'); | 114 Element topB = findElement('B'); |
| 113 Element topC = findElement('C'); | 115 Element topC = findElement('C'); |
| 114 Element topD = findElement('D'); | 116 Element topD = findElement('D'); |
| 115 Element topE = findElement('E'); | 117 Element topE = findElement('E'); |
| 116 List<Location> locations = await index.getDefinedNames( | 118 List<Location> locations = await index.getDefinedNames( |
| 117 new RegExp(r'^[A-E]$'), IndexNameKind.topLevel); | 119 new RegExp(r'^[A-E]$'), IndexNameKind.topLevel); |
| 118 expect(locations, hasLength(5)); | 120 expect(locations, hasLength(5)); |
| 119 _assertHasDefinedName(locations, topA); | 121 _assertHasDefinedName(locations, topA); |
| 120 _assertHasDefinedName(locations, topB); | 122 _assertHasDefinedName(locations, topB); |
| 121 _assertHasDefinedName(locations, topC); | 123 _assertHasDefinedName(locations, topC); |
| 122 _assertHasDefinedName(locations, topD); | 124 _assertHasDefinedName(locations, topD); |
| 123 _assertHasDefinedName(locations, topE); | 125 _assertHasDefinedName(locations, topE); |
| 124 } | 126 } |
| 125 | 127 |
| 126 test_getDefinedNames_topLevel2() async { | 128 test_getDefinedNames_topLevel2() async { |
| 127 _indexTestUnit( | 129 await _indexTestUnit( |
| 128 ''' | 130 ''' |
| 129 class A {} // A | 131 class A {} // A |
| 130 class B = Object with A; | 132 class B = Object with A; |
| 131 class NoMatchABCDE {} | 133 class NoMatchABCDE {} |
| 132 ''', | 134 ''', |
| 133 declOnly: true); | 135 declOnly: true); |
| 134 Element topA = findElement('A'); | 136 Element topA = findElement('A'); |
| 135 Element topB = findElement('B'); | 137 Element topB = findElement('B'); |
| 136 List<Location> locations = await index.getDefinedNames( | 138 List<Location> locations = await index.getDefinedNames( |
| 137 new RegExp(r'^[A-E]$'), IndexNameKind.topLevel); | 139 new RegExp(r'^[A-E]$'), IndexNameKind.topLevel); |
| 138 expect(locations, hasLength(2)); | 140 expect(locations, hasLength(2)); |
| 139 _assertHasDefinedName(locations, topA); | 141 _assertHasDefinedName(locations, topA); |
| 140 _assertHasDefinedName(locations, topB); | 142 _assertHasDefinedName(locations, topB); |
| 141 } | 143 } |
| 142 | 144 |
| 143 test_getRelations_isExtendedBy() async { | 145 test_getRelations_isExtendedBy() async { |
| 144 _indexTestUnit(r''' | 146 await _indexTestUnit(r''' |
| 145 class A {} | 147 class A {} |
| 146 class B extends A {} // B | 148 class B extends A {} // B |
| 147 '''); | 149 '''); |
| 148 Source source2 = _indexUnit( | 150 Source source2 = await _indexUnit( |
| 149 '/test2.dart', | 151 '/test2.dart', |
| 150 r''' | 152 r''' |
| 151 import 'test.dart'; | 153 import 'test.dart'; |
| 152 class C extends A {} // C | 154 class C extends A {} // C |
| 153 '''); | 155 '''); |
| 154 ClassElement elementA = testUnitElement.getType('A'); | 156 ClassElement elementA = testUnitElement.getType('A'); |
| 155 List<Location> locations = | 157 List<Location> locations = |
| 156 await index.getRelations(elementA, IndexRelationKind.IS_EXTENDED_BY); | 158 await index.getRelations(elementA, IndexRelationKind.IS_EXTENDED_BY); |
| 157 findLocationTest(locations, 'A {} // B', false); | 159 findLocationTest(locations, 'A {} // B', false); |
| 158 findLocationSource(locations, source2, 'A {} // C', false); | 160 findLocationSource(locations, source2, 'A {} // C', false); |
| 159 } | 161 } |
| 160 | 162 |
| 161 test_getRelations_isReferencedBy() async { | 163 test_getRelations_isReferencedBy() async { |
| 162 _indexTestUnit(r''' | 164 await _indexTestUnit(r''' |
| 163 main(int a, int b) { | 165 main(int a, int b) { |
| 164 } | 166 } |
| 165 '''); | 167 '''); |
| 166 ClassElement intElement = context.typeProvider.intType.element; | 168 ClassElement intElement = context.typeProvider.intType.element; |
| 167 List<Location> locations = await index.getRelations( | 169 List<Location> locations = await index.getRelations( |
| 168 intElement, IndexRelationKind.IS_REFERENCED_BY); | 170 intElement, IndexRelationKind.IS_REFERENCED_BY); |
| 169 findLocationTest(locations, 'int a', false); | 171 findLocationTest(locations, 'int a', false); |
| 170 findLocationTest(locations, 'int b', false); | 172 findLocationTest(locations, 'int b', false); |
| 171 } | 173 } |
| 172 | 174 |
| 173 test_getUnresolvedMemberReferences_qualified_resolved() async { | 175 test_getUnresolvedMemberReferences_qualified_resolved() async { |
| 174 _indexTestUnit(''' | 176 await _indexTestUnit(''' |
| 175 class A { | 177 class A { |
| 176 var test; // A | 178 var test; // A |
| 177 } | 179 } |
| 178 main(A a) { | 180 main(A a) { |
| 179 print(a.test); | 181 print(a.test); |
| 180 a.test = 1; | 182 a.test = 1; |
| 181 a.test += 2; | 183 a.test += 2; |
| 182 a.test(); | 184 a.test(); |
| 183 } | 185 } |
| 184 '''); | 186 '''); |
| 185 List<Location> locations = | 187 List<Location> locations = |
| 186 await index.getUnresolvedMemberReferences('test'); | 188 await index.getUnresolvedMemberReferences('test'); |
| 187 expect(locations, isEmpty); | 189 expect(locations, isEmpty); |
| 188 } | 190 } |
| 189 | 191 |
| 190 test_getUnresolvedMemberReferences_qualified_unresolved() async { | 192 test_getUnresolvedMemberReferences_qualified_unresolved() async { |
| 191 _indexTestUnit(''' | 193 await _indexTestUnit(''' |
| 192 class A { | 194 class A { |
| 193 var test; // A | 195 var test; // A |
| 194 } | 196 } |
| 195 main(p) { | 197 main(p) { |
| 196 print(p.test); | 198 print(p.test); |
| 197 p.test = 1; | 199 p.test = 1; |
| 198 p.test += 2; | 200 p.test += 2; |
| 199 p.test(); | 201 p.test(); |
| 200 print(p.test2); // not requested | 202 print(p.test2); // not requested |
| 201 } | 203 } |
| 202 '''); | 204 '''); |
| 203 List<Location> locations = | 205 List<Location> locations = |
| 204 await index.getUnresolvedMemberReferences('test'); | 206 await index.getUnresolvedMemberReferences('test'); |
| 205 expect(locations, hasLength(4)); | 207 expect(locations, hasLength(4)); |
| 206 findLocationTest(locations, 'test);', true); | 208 findLocationTest(locations, 'test);', true); |
| 207 findLocationTest(locations, 'test = 1;', true); | 209 findLocationTest(locations, 'test = 1;', true); |
| 208 findLocationTest(locations, 'test += 2;', true); | 210 findLocationTest(locations, 'test += 2;', true); |
| 209 findLocationTest(locations, 'test();', true); | 211 findLocationTest(locations, 'test();', true); |
| 210 } | 212 } |
| 211 | 213 |
| 212 test_getUnresolvedMemberReferences_unqualified_resolved() async { | 214 test_getUnresolvedMemberReferences_unqualified_resolved() async { |
| 213 _indexTestUnit(''' | 215 await _indexTestUnit(''' |
| 214 class A { | 216 class A { |
| 215 var test; | 217 var test; |
| 216 m() { | 218 m() { |
| 217 print(test); | 219 print(test); |
| 218 test = 1; | 220 test = 1; |
| 219 test += 2; | 221 test += 2; |
| 220 test(); | 222 test(); |
| 221 } | 223 } |
| 222 } | 224 } |
| 223 '''); | 225 '''); |
| 224 List<Location> locations = | 226 List<Location> locations = |
| 225 await index.getUnresolvedMemberReferences('test'); | 227 await index.getUnresolvedMemberReferences('test'); |
| 226 expect(locations, isEmpty); | 228 expect(locations, isEmpty); |
| 227 } | 229 } |
| 228 | 230 |
| 229 test_getUnresolvedMemberReferences_unqualified_unresolved() async { | 231 test_getUnresolvedMemberReferences_unqualified_unresolved() async { |
| 230 verifyNoTestUnitErrors = false; | 232 verifyNoTestUnitErrors = false; |
| 231 _indexTestUnit(''' | 233 await _indexTestUnit(''' |
| 232 class A { | 234 class A { |
| 233 m() { | 235 m() { |
| 234 print(test); | 236 print(test); |
| 235 test = 1; | 237 test = 1; |
| 236 test += 2; | 238 test += 2; |
| 237 test(); | 239 test(); |
| 238 print(test2); // not requested | 240 print(test2); // not requested |
| 239 } | 241 } |
| 240 } | 242 } |
| 241 '''); | 243 '''); |
| 242 List<Location> locations = | 244 List<Location> locations = |
| 243 await index.getUnresolvedMemberReferences('test'); | 245 await index.getUnresolvedMemberReferences('test'); |
| 244 expect(locations, hasLength(4)); | 246 expect(locations, hasLength(4)); |
| 245 findLocationTest(locations, 'test);', false); | 247 findLocationTest(locations, 'test);', false); |
| 246 findLocationTest(locations, 'test = 1;', false); | 248 findLocationTest(locations, 'test = 1;', false); |
| 247 findLocationTest(locations, 'test += 2;', false); | 249 findLocationTest(locations, 'test += 2;', false); |
| 248 findLocationTest(locations, 'test();', false); | 250 findLocationTest(locations, 'test();', false); |
| 249 } | 251 } |
| 250 | 252 |
| 251 test_indexDeclarations_afterIndexUnit() async { | 253 test_indexDeclarations_afterIndexUnit() async { |
| 252 resolveTestUnit(''' | 254 await resolveTestUnit(''' |
| 253 var a = 0; | 255 var a = 0; |
| 254 var b = a + 1; | 256 var b = a + 1; |
| 255 '''); | 257 '''); |
| 256 index.indexUnit(testUnit); | 258 index.indexUnit(testUnit); |
| 257 TopLevelVariableElement a = findElement('a'); | 259 TopLevelVariableElement a = findElement('a'); |
| 258 // We can find references. | 260 // We can find references. |
| 259 { | 261 { |
| 260 List<Location> locations = await index.getRelations( | 262 List<Location> locations = await index.getRelations( |
| 261 a.getter, IndexRelationKind.IS_REFERENCED_BY); | 263 a.getter, IndexRelationKind.IS_REFERENCED_BY); |
| 262 findLocationTest(locations, 'a + 1', false); | 264 findLocationTest(locations, 'a + 1', false); |
| 263 } | 265 } |
| 264 // Attempt to index just declarations - we still can find references. | 266 // Attempt to index just declarations - we still can find references. |
| 265 index.indexDeclarations(testUnit); | 267 index.indexDeclarations(testUnit); |
| 266 { | 268 { |
| 267 List<Location> locations = await index.getRelations( | 269 List<Location> locations = await index.getRelations( |
| 268 a.getter, IndexRelationKind.IS_REFERENCED_BY); | 270 a.getter, IndexRelationKind.IS_REFERENCED_BY); |
| 269 findLocationTest(locations, 'a + 1', false); | 271 findLocationTest(locations, 'a + 1', false); |
| 270 } | 272 } |
| 271 } | 273 } |
| 272 | 274 |
| 273 test_indexDeclarations_nullUnit() async { | 275 test_indexDeclarations_nullUnit() async { |
| 274 index.indexDeclarations(null); | 276 index.indexDeclarations(null); |
| 275 } | 277 } |
| 276 | 278 |
| 277 test_indexDeclarations_nullUnitElement() async { | 279 test_indexDeclarations_nullUnitElement() async { |
| 278 resolveTestUnit(''); | 280 await resolveTestUnit(''); |
| 279 testUnit.element = null; | 281 testUnit.element = null; |
| 280 index.indexDeclarations(testUnit); | 282 index.indexDeclarations(testUnit); |
| 281 } | 283 } |
| 282 | 284 |
| 283 test_indexUnit_nullLibraryElement() async { | 285 test_indexUnit_nullLibraryElement() async { |
| 284 resolveTestUnit(''); | 286 await resolveTestUnit(''); |
| 285 CompilationUnitElement unitElement = new _CompilationUnitElementMock(); | 287 CompilationUnitElement unitElement = new _CompilationUnitElementMock(); |
| 286 expect(unitElement.library, isNull); | 288 expect(unitElement.library, isNull); |
| 287 testUnit.element = unitElement; | 289 testUnit.element = unitElement; |
| 288 index.indexUnit(testUnit); | 290 index.indexUnit(testUnit); |
| 289 } | 291 } |
| 290 | 292 |
| 291 test_indexUnit_nullUnit() async { | 293 test_indexUnit_nullUnit() async { |
| 292 index.indexUnit(null); | 294 index.indexUnit(null); |
| 293 } | 295 } |
| 294 | 296 |
| 295 test_indexUnit_nullUnitElement() async { | 297 test_indexUnit_nullUnitElement() async { |
| 296 resolveTestUnit(''); | 298 await resolveTestUnit(''); |
| 297 testUnit.element = null; | 299 testUnit.element = null; |
| 298 index.indexUnit(testUnit); | 300 index.indexUnit(testUnit); |
| 299 } | 301 } |
| 300 | 302 |
| 301 test_removeContext() async { | 303 test_removeContext() async { |
| 302 _indexTestUnit(''' | 304 await _indexTestUnit(''' |
| 303 class A {} | 305 class A {} |
| 304 '''); | 306 '''); |
| 305 RegExp regExp = new RegExp(r'^A$'); | 307 RegExp regExp = new RegExp(r'^A$'); |
| 306 expect(await index.getDefinedNames(regExp, IndexNameKind.topLevel), | 308 expect(await index.getDefinedNames(regExp, IndexNameKind.topLevel), |
| 307 hasLength(1)); | 309 hasLength(1)); |
| 308 // remove the context - no top-level declarations | 310 // remove the context - no top-level declarations |
| 309 index.removeContext(context); | 311 index.removeContext(context); |
| 310 expect( | 312 expect( |
| 311 await index.getDefinedNames(regExp, IndexNameKind.topLevel), isEmpty); | 313 await index.getDefinedNames(regExp, IndexNameKind.topLevel), isEmpty); |
| 312 } | 314 } |
| 313 | 315 |
| 314 test_removeUnit() async { | 316 test_removeUnit() async { |
| 315 RegExp regExp = new RegExp(r'^[AB]$'); | 317 RegExp regExp = new RegExp(r'^[AB]$'); |
| 316 Source sourceA = addSource('/a.dart', 'class A {}'); | 318 Source sourceA = addSource('/a.dart', 'class A {}'); |
| 317 Source sourceB = addSource('/b.dart', 'class B {}'); | 319 Source sourceB = addSource('/b.dart', 'class B {}'); |
| 318 CompilationUnit unitA = resolveLibraryUnit(sourceA); | 320 CompilationUnit unitA = await resolveLibraryUnit(sourceA); |
| 319 CompilationUnit unitB = resolveLibraryUnit(sourceB); | 321 CompilationUnit unitB = await resolveLibraryUnit(sourceB); |
| 320 index.indexUnit(unitA); | 322 index.indexUnit(unitA); |
| 321 index.indexUnit(unitB); | 323 index.indexUnit(unitB); |
| 322 { | 324 { |
| 323 List<Location> locations = | 325 List<Location> locations = |
| 324 await index.getDefinedNames(regExp, IndexNameKind.topLevel); | 326 await index.getDefinedNames(regExp, IndexNameKind.topLevel); |
| 325 expect(locations, hasLength(2)); | 327 expect(locations, hasLength(2)); |
| 326 expect(locations.map((l) => l.libraryUri), | 328 expect(locations.map((l) => l.libraryUri), |
| 327 unorderedEquals([sourceA.uri.toString(), sourceB.uri.toString()])); | 329 unorderedEquals([sourceA.uri.toString(), sourceB.uri.toString()])); |
| 328 } | 330 } |
| 329 // remove a.dart - no a.dart location | 331 // remove a.dart - no a.dart location |
| (...skipping 19 matching lines...) Expand all Loading... |
| 349 location.unitUri == unitUri && | 351 location.unitUri == unitUri && |
| 350 location.offset == element.nameOffset && | 352 location.offset == element.nameOffset && |
| 351 location.length == element.nameLength) { | 353 location.length == element.nameLength) { |
| 352 return; | 354 return; |
| 353 } | 355 } |
| 354 } | 356 } |
| 355 fail('No declaration of $element at ${element.nameOffset} in\n' | 357 fail('No declaration of $element at ${element.nameOffset} in\n' |
| 356 '${locations.join('\n')}'); | 358 '${locations.join('\n')}'); |
| 357 } | 359 } |
| 358 | 360 |
| 359 void _indexTestUnit(String code, {bool declOnly: false}) { | 361 Future<Null> _indexTestUnit(String code, {bool declOnly: false}) async { |
| 360 resolveTestUnit(code); | 362 await resolveTestUnit(code); |
| 361 if (declOnly) { | 363 if (declOnly) { |
| 362 index.indexDeclarations(testUnit); | 364 index.indexDeclarations(testUnit); |
| 363 } else { | 365 } else { |
| 364 index.indexUnit(testUnit); | 366 index.indexUnit(testUnit); |
| 365 } | 367 } |
| 366 } | 368 } |
| 367 | 369 |
| 368 Source _indexUnit(String path, String code) { | 370 Future<Source> _indexUnit(String path, String code) async { |
| 369 Source source = addSource(path, code); | 371 Source source = addSource(path, code); |
| 370 CompilationUnit unit = resolveLibraryUnit(source); | 372 CompilationUnit unit = await resolveLibraryUnit(source); |
| 371 index.indexUnit(unit); | 373 index.indexUnit(unit); |
| 372 return source; | 374 return source; |
| 373 } | 375 } |
| 374 } | 376 } |
| 375 | 377 |
| 376 class _CompilationUnitElementMock extends TypedMock | 378 class _CompilationUnitElementMock extends TypedMock |
| 377 implements CompilationUnitElement {} | 379 implements CompilationUnitElement {} |
| OLD | NEW |