OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 import 'package:analysis_server/src/services/index2/index2.dart'; | |
6 import 'package:analyzer/dart/ast/ast.dart'; | |
7 import 'package:analyzer/dart/element/element.dart'; | |
8 import 'package:analyzer/src/generated/source.dart'; | |
9 import 'package:analyzer/src/summary/idl.dart'; | |
10 import 'package:test_reflective_loader/test_reflective_loader.dart'; | |
11 import 'package:unittest/unittest.dart'; | |
12 | |
13 import '../../abstract_single_unit.dart'; | |
14 import '../../utils.dart'; | |
15 | |
16 main() { | |
17 initializeTestEnvironment(); | |
18 defineReflectiveTests(Index2Test); | |
19 } | |
20 | |
21 @reflectiveTest | |
22 class Index2Test extends AbstractSingleUnitTest { | |
23 Index2 index = createMemoryIndex2(); | |
24 | |
25 /** | |
26 * Return the [Location] with given properties, or fail. | |
27 */ | |
28 Location findLocation(List<Location> locations, String libraryUri, | |
29 String unitUri, int offset, int length, bool isQualified) { | |
30 for (Location location in locations) { | |
31 if (location.libraryUri == libraryUri && | |
32 location.unitUri == unitUri && | |
33 location.offset == offset && | |
34 location.length == length && | |
35 location.isQualified == isQualified) { | |
36 return location; | |
37 } | |
38 } | |
39 fail('No at $offset with length $length qualified=$isQualified in\n' | |
40 '${locations.join('\n')}'); | |
41 return null; | |
42 } | |
43 | |
44 /** | |
45 * Return the [Location] with given properties, or fail. | |
46 */ | |
47 Location findLocationSource( | |
48 List<Location> locations, Source source, String search, bool isQualified, | |
49 {int length}) { | |
50 String code = source.contents.data; | |
51 int offset = code.indexOf(search); | |
52 expect(offset, isNonNegative, reason: 'Not found "$search" in\n$code'); | |
53 length ??= getLeadingIdentifierLength(search); | |
54 String uri = source.uri.toString(); | |
55 return findLocation(locations, uri, uri, offset, length, isQualified); | |
56 } | |
57 | |
58 /** | |
59 * Return the [Location] with given properties, or fail. | |
60 */ | |
61 Location findLocationTest( | |
62 List<Location> locations, String search, bool isQualified, | |
63 {int length}) { | |
64 int offset = findOffset(search); | |
65 length ??= getLeadingIdentifierLength(search); | |
66 String testUri = testSource.uri.toString(); | |
67 return findLocation( | |
68 locations, testUri, testUri, offset, length, isQualified); | |
69 } | |
70 | |
71 void setUp() { | |
72 super.setUp(); | |
73 } | |
74 | |
75 void tearDown() { | |
76 super.tearDown(); | |
77 index = null; | |
78 } | |
79 | |
80 test_getDefinedNames_classMember() async { | |
81 _indexTestUnit(''' | |
82 class A { | |
83 test() {} | |
84 } | |
85 class B { | |
86 int test = 1; | |
87 main() { | |
88 int test = 2; | |
89 } | |
90 } | |
91 '''); | |
92 ClassElement classA = findElement('A'); | |
93 ClassElement classB = findElement('B'); | |
94 List<Location> locations = await index.getDefinedNames( | |
95 new RegExp(r'^test$'), IndexNameKind.classMember); | |
96 expect(locations, hasLength(2)); | |
97 _assertHasDefinedName(locations, classA.methods[0]); | |
98 _assertHasDefinedName(locations, classB.fields[0]); | |
99 } | |
100 | |
101 test_getDefinedNames_topLevel() async { | |
102 _indexTestUnit(''' | |
103 class A {} // A | |
104 class B = Object with A; | |
105 typedef C(); | |
106 D() {} | |
107 var E = null; | |
108 class NoMatchABCDE {} | |
109 '''); | |
110 Element topA = findElement('A'); | |
111 Element topB = findElement('B'); | |
112 Element topC = findElement('C'); | |
113 Element topD = findElement('D'); | |
114 Element topE = findElement('E'); | |
115 List<Location> locations = await index.getDefinedNames( | |
116 new RegExp(r'^[A-E]$'), IndexNameKind.topLevel); | |
117 expect(locations, hasLength(5)); | |
118 _assertHasDefinedName(locations, topA); | |
119 _assertHasDefinedName(locations, topB); | |
120 _assertHasDefinedName(locations, topC); | |
121 _assertHasDefinedName(locations, topD); | |
122 _assertHasDefinedName(locations, topE); | |
123 } | |
124 | |
125 test_getRelations_isExtendedBy() async { | |
126 _indexTestUnit(r''' | |
127 class A {} | |
128 class B extends A {} // B | |
129 '''); | |
130 Source source2 = _indexUnit( | |
131 '/test2.dart', | |
132 r''' | |
133 import 'test.dart'; | |
134 class C extends A {} // C | |
135 '''); | |
136 ClassElement elementA = testUnitElement.getType('A'); | |
137 List<Location> locations = | |
138 await index.getRelations(elementA, IndexRelationKind.IS_EXTENDED_BY); | |
139 findLocationTest(locations, 'A {} // B', false); | |
140 findLocationSource(locations, source2, 'A {} // C', false); | |
141 } | |
142 | |
143 test_getRelations_isReferencedBy() async { | |
144 _indexTestUnit(r''' | |
145 main(int a, int b) { | |
146 } | |
147 '''); | |
148 ClassElement intElement = context.typeProvider.intType.element; | |
149 List<Location> locations = await index.getRelations( | |
150 intElement, IndexRelationKind.IS_REFERENCED_BY); | |
151 findLocationTest(locations, 'int a', false); | |
152 findLocationTest(locations, 'int b', false); | |
153 } | |
154 | |
155 test_getUnresolvedMemberReferences_qualified_resolved() async { | |
156 _indexTestUnit(''' | |
157 class A { | |
158 var test; // A | |
159 } | |
160 main(A a) { | |
161 print(a.test); | |
162 a.test = 1; | |
163 a.test += 2; | |
164 a.test(); | |
165 } | |
166 '''); | |
167 List<Location> locations = | |
168 await index.getUnresolvedMemberReferences('test'); | |
169 expect(locations, isEmpty); | |
170 } | |
171 | |
172 test_getUnresolvedMemberReferences_qualified_unresolved() async { | |
173 _indexTestUnit(''' | |
174 class A { | |
175 var test; // A | |
176 } | |
177 main(p) { | |
178 print(p.test); | |
179 p.test = 1; | |
180 p.test += 2; | |
181 p.test(); | |
182 print(p.test2); // not requested | |
183 } | |
184 '''); | |
185 List<Location> locations = | |
186 await index.getUnresolvedMemberReferences('test'); | |
187 expect(locations, hasLength(4)); | |
188 findLocationTest(locations, 'test);', true); | |
189 findLocationTest(locations, 'test = 1;', true); | |
190 findLocationTest(locations, 'test += 2;', true); | |
191 findLocationTest(locations, 'test();', true); | |
192 } | |
193 | |
194 test_getUnresolvedMemberReferences_unqualified_resolved() async { | |
195 _indexTestUnit(''' | |
196 class A { | |
197 var test; | |
198 m() { | |
199 print(test); | |
200 test = 1; | |
201 test += 2; | |
202 test(); | |
203 } | |
204 } | |
205 '''); | |
206 List<Location> locations = | |
207 await index.getUnresolvedMemberReferences('test'); | |
208 expect(locations, isEmpty); | |
209 } | |
210 | |
211 test_getUnresolvedMemberReferences_unqualified_unresolved() async { | |
212 verifyNoTestUnitErrors = false; | |
213 _indexTestUnit(''' | |
214 class A { | |
215 m() { | |
216 print(test); | |
217 test = 1; | |
218 test += 2; | |
219 test(); | |
220 print(test2); // not requested | |
221 } | |
222 } | |
223 '''); | |
224 List<Location> locations = | |
225 await index.getUnresolvedMemberReferences('test'); | |
226 expect(locations, hasLength(4)); | |
227 findLocationTest(locations, 'test);', false); | |
228 findLocationTest(locations, 'test = 1;', false); | |
229 findLocationTest(locations, 'test += 2;', false); | |
230 findLocationTest(locations, 'test();', false); | |
231 } | |
232 | |
233 test_indexUnit_nullUnit() async { | |
234 index.indexUnit(null); | |
235 } | |
236 | |
237 test_indexUnit_nullUnitElement() async { | |
238 resolveTestUnit(''); | |
239 testUnit.element = null; | |
240 index.indexUnit(testUnit); | |
241 } | |
242 | |
243 test_removeContext() async { | |
244 _indexTestUnit(''' | |
245 class A {} | |
246 '''); | |
247 RegExp regExp = new RegExp(r'^A$'); | |
248 expect(await index.getDefinedNames(regExp, IndexNameKind.topLevel), | |
249 hasLength(1)); | |
250 // remove the context - no top-level declarations | |
251 index.removeContext(context); | |
252 expect( | |
253 await index.getDefinedNames(regExp, IndexNameKind.topLevel), isEmpty); | |
254 } | |
255 | |
256 test_removeUnit() async { | |
257 RegExp regExp = new RegExp(r'^[AB]$'); | |
258 Source sourceA = addSource('/a.dart', 'class A {}'); | |
259 Source sourceB = addSource('/b.dart', 'class B {}'); | |
260 CompilationUnit unitA = resolveLibraryUnit(sourceA); | |
261 CompilationUnit unitB = resolveLibraryUnit(sourceB); | |
262 index.indexUnit(unitA); | |
263 index.indexUnit(unitB); | |
264 { | |
265 List<Location> locations = | |
266 await index.getDefinedNames(regExp, IndexNameKind.topLevel); | |
267 expect(locations, hasLength(2)); | |
268 expect(locations.map((l) => l.libraryUri), | |
269 unorderedEquals([sourceA.uri.toString(), sourceB.uri.toString()])); | |
270 } | |
271 // remove a.dart - no a.dart location | |
272 index.removeUnit(context, sourceA, sourceA); | |
273 { | |
274 List<Location> locations = | |
275 await index.getDefinedNames(regExp, IndexNameKind.topLevel); | |
276 expect(locations, hasLength(1)); | |
277 expect(locations.map((l) => l.libraryUri), | |
278 unorderedEquals([sourceB.uri.toString()])); | |
279 } | |
280 } | |
281 | |
282 /** | |
283 * Assert that the given list of [locations] has a [Location] corresponding | |
284 * to the [element]. | |
285 */ | |
286 void _assertHasDefinedName(List<Location> locations, Element element) { | |
287 String libraryUri = element.library.source.uri.toString(); | |
288 String unitUri = element.source.uri.toString(); | |
289 for (Location location in locations) { | |
290 if (location.libraryUri == libraryUri && | |
291 location.unitUri == unitUri && | |
292 location.offset == element.nameOffset && | |
293 location.length == element.nameLength) { | |
294 return; | |
295 } | |
296 } | |
297 fail('No declaration of $element at ${element.nameOffset} in\n' | |
298 '${locations.join('\n')}'); | |
299 } | |
300 | |
301 void _indexTestUnit(String code) { | |
302 resolveTestUnit(code); | |
303 index.indexUnit(testUnit); | |
304 } | |
305 | |
306 Source _indexUnit(String path, String code) { | |
307 Source source = addSource(path, code); | |
308 CompilationUnit unit = resolveLibraryUnit(source); | |
309 index.indexUnit(unit); | |
310 return source; | |
311 } | |
312 } | |
OLD | NEW |