OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 'package:analysis_server/protocol/protocol.dart'; | 5 import 'package:analysis_server/protocol/protocol.dart'; |
6 import 'package:analysis_server/protocol/protocol_generated.dart'; | 6 import 'package:analysis_server/protocol/protocol_generated.dart'; |
7 import 'package:analysis_server/src/constants.dart'; | 7 import 'package:analysis_server/src/constants.dart'; |
8 import 'package:analysis_server/src/services/index/index.dart'; | 8 import 'package:analysis_server/src/services/index/index.dart'; |
9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
10 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; | 10 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; |
11 import 'package:analyzer/file_system/file_system.dart'; | 11 import 'package:analyzer/file_system/file_system.dart'; |
12 import 'package:analyzer/src/generated/engine.dart'; | 12 import 'package:analyzer/src/dart/analysis/driver.dart'; |
13 import 'package:analyzer/src/generated/source.dart'; | |
14 import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin; | 13 import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin; |
15 import 'package:analyzer_plugin/protocol/protocol_common.dart'; | 14 import 'package:analyzer_plugin/protocol/protocol_common.dart'; |
16 import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin; | 15 import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin; |
17 import 'package:test/test.dart'; | 16 import 'package:test/test.dart'; |
18 import 'package:test_reflective_loader/test_reflective_loader.dart'; | 17 import 'package:test_reflective_loader/test_reflective_loader.dart'; |
19 import 'package:typed_mock/typed_mock.dart'; | 18 import 'package:typed_mock/typed_mock.dart'; |
20 | 19 |
21 import '../analysis_abstract.dart'; | 20 import '../analysis_abstract.dart'; |
22 | 21 |
23 main() { | 22 main() { |
24 defineReflectiveSuite(() { | 23 defineReflectiveSuite(() { |
25 defineReflectiveTests(UpdateContentTest); | 24 defineReflectiveTests(UpdateContentTest); |
26 }); | 25 }); |
27 } | 26 } |
28 | 27 |
29 compilationUnitMatcher(String file) { | 28 compilationUnitMatcher(String file) { |
30 return new _ArgumentMatcher_CompilationUnit(file); | 29 return new _ArgumentMatcher_CompilationUnit(file); |
31 } | 30 } |
32 | 31 |
33 @reflectiveTest | 32 @reflectiveTest |
34 class UpdateContentTest extends AbstractAnalysisTest { | 33 class UpdateContentTest extends AbstractAnalysisTest { |
35 Map<String, List<String>> filesErrors = {}; | 34 Map<String, List<String>> filesErrors = {}; |
36 int serverErrorCount = 0; | 35 int serverErrorCount = 0; |
37 int navigationCount = 0; | 36 int navigationCount = 0; |
38 | 37 |
39 @override | |
40 bool get enableNewAnalysisDriver => false; | |
41 | |
42 Index createIndex() { | 38 Index createIndex() { |
43 return new _MockIndex(); | 39 return new _MockIndex(); |
44 } | 40 } |
45 | 41 |
46 @override | 42 @override |
47 void processNotification(Notification notification) { | 43 void processNotification(Notification notification) { |
48 if (notification.event == ANALYSIS_ERRORS) { | 44 if (notification.event == ANALYSIS_ERRORS) { |
49 var decoded = new AnalysisErrorsParams.fromNotification(notification); | 45 var decoded = new AnalysisErrorsParams.fromNotification(notification); |
50 String _format(AnalysisError e) => | 46 String _format(AnalysisError e) => |
51 "${e.location.startLine}: ${e.message}"; | 47 "${e.location.startLine}: ${e.message}"; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 server.updateContent(id, { | 86 server.updateContent(id, { |
91 testFile: new ChangeContentOverlay([new SourceEdit(8, 3, 'bar')]) | 87 testFile: new ChangeContentOverlay([new SourceEdit(8, 3, 'bar')]) |
92 }); | 88 }); |
93 fail('Expected an exception to be thrown'); | 89 fail('Expected an exception to be thrown'); |
94 } on RequestFailure catch (e) { | 90 } on RequestFailure catch (e) { |
95 expect(e.response.id, id); | 91 expect(e.response.id, id); |
96 expect(e.response.error.code, RequestErrorCode.INVALID_OVERLAY_CHANGE); | 92 expect(e.response.error.code, RequestErrorCode.INVALID_OVERLAY_CHANGE); |
97 } | 93 } |
98 } | 94 } |
99 | 95 |
100 test_indexUnitAfterNopChange() async { | |
101 // AnalysisContext incremental analysis has been removed | |
102 if (!enableNewAnalysisDriver) return; | |
103 throw 'is this test used by the new analysis driver?'; | |
104 | |
105 // var testUnitMatcher = compilationUnitMatcher(testFile) as dynamic; | |
106 // createProject(); | |
107 // addTestFile('main() { print(1); }'); | |
108 // await server.onAnalysisComplete; | |
109 // verify(server.index.indexUnit(testUnitMatcher)).times(1); | |
110 // // add an overlay | |
111 // server.updateContent( | |
112 // '1', {testFile: new AddContentOverlay('main() { print(2); }')}); | |
113 // // Perform the next single operation: analysis. | |
114 // // It will schedule an indexing operation. | |
115 // await server.test_onOperationPerformed; | |
116 // // Update the file and remove an overlay. | |
117 // resourceProvider.updateFile(testFile, 'main() { print(2); }'); | |
118 // server.updateContent('2', {testFile: new RemoveContentOverlay()}); | |
119 // // Validate that at the end the unit was indexed. | |
120 // await server.onAnalysisComplete; | |
121 // verify(server.index.indexUnit(testUnitMatcher)).times(3); | |
122 } | |
123 | |
124 test_multiple_contexts() async { | 96 test_multiple_contexts() async { |
125 String fooPath = '/project1/foo.dart'; | 97 String fooPath = '/project1/foo.dart'; |
126 resourceProvider.newFile( | 98 resourceProvider.newFile( |
127 fooPath, | 99 fooPath, |
128 ''' | 100 ''' |
129 library foo; | 101 library foo; |
130 import '../project2/baz.dart'; | 102 import '../project2/baz.dart'; |
131 main() { f(); }'''); | 103 main() { f(); }'''); |
132 String barPath = '/project2/bar.dart'; | 104 String barPath = '/project2/bar.dart'; |
133 resourceProvider.newFile( | 105 resourceProvider.newFile( |
(...skipping 29 matching lines...) Expand all Loading... |
163 } | 135 } |
164 { | 136 { |
165 await server.onAnalysisComplete; | 137 await server.onAnalysisComplete; |
166 // The overlay should have been propagated to both contexts, causing both | 138 // The overlay should have been propagated to both contexts, causing both |
167 // foo.dart and bar.dart to be reanalyzed and found to be free of errors. | 139 // foo.dart and bar.dart to be reanalyzed and found to be free of errors. |
168 expect(filesErrors[fooPath], isEmpty); | 140 expect(filesErrors[fooPath], isEmpty); |
169 expect(filesErrors[barPath], isEmpty); | 141 expect(filesErrors[barPath], isEmpty); |
170 } | 142 } |
171 } | 143 } |
172 | 144 |
| 145 @failingTest |
173 test_overlay_addPreviouslyImported() async { | 146 test_overlay_addPreviouslyImported() async { |
| 147 // The list of errors doesn't include errors for '/project/target.dart'. |
174 Folder project = resourceProvider.newFolder('/project'); | 148 Folder project = resourceProvider.newFolder('/project'); |
175 handleSuccessfulRequest( | 149 handleSuccessfulRequest( |
176 new AnalysisSetAnalysisRootsParams([project.path], []).toRequest('0')); | 150 new AnalysisSetAnalysisRootsParams([project.path], []).toRequest('0')); |
177 | 151 |
178 server.updateContent('1', | 152 server.updateContent('1', |
179 {'/project/main.dart': new AddContentOverlay('import "target.dart";')}); | 153 {'/project/main.dart': new AddContentOverlay('import "target.dart";')}); |
180 await server.onAnalysisComplete; | 154 await server.onAnalysisComplete; |
181 expect(filesErrors, { | 155 expect(filesErrors, { |
182 '/project/main.dart': ["1: Target of URI doesn't exist: 'target.dart'."], | 156 '/project/main.dart': ["1: Target of URI doesn't exist: 'target.dart'."], |
183 '/project/target.dart': [] | 157 '/project/target.dart': [] |
(...skipping 11 matching lines...) Expand all Loading... |
195 | 169 |
196 test_overlayOnly() async { | 170 test_overlayOnly() async { |
197 String filePath = '/User/project1/test.dart'; | 171 String filePath = '/User/project1/test.dart'; |
198 Folder folder1 = resourceProvider.newFolder('/User/project1'); | 172 Folder folder1 = resourceProvider.newFolder('/User/project1'); |
199 Folder folder2 = resourceProvider.newFolder('/User/project2'); | 173 Folder folder2 = resourceProvider.newFolder('/User/project2'); |
200 Request request = | 174 Request request = |
201 new AnalysisSetAnalysisRootsParams([folder1.path, folder2.path], []) | 175 new AnalysisSetAnalysisRootsParams([folder1.path, folder2.path], []) |
202 .toRequest('0'); | 176 .toRequest('0'); |
203 handleSuccessfulRequest(request); | 177 handleSuccessfulRequest(request); |
204 // exactly 2 contexts | 178 // exactly 2 contexts |
205 expect(server.folderMap, hasLength(2)); | 179 expect(server.driverMap, hasLength(2)); |
206 AnalysisContext context1 = server.folderMap[folder1]; | 180 AnalysisDriver driver1 = server.driverMap[folder1]; |
207 AnalysisContext context2 = server.folderMap[folder2]; | 181 AnalysisDriver driver2 = server.driverMap[folder2]; |
208 // no sources | 182 // no sources |
209 expect(_getUserSources(context1), isEmpty); | 183 expect(_getUserSources(driver1), isEmpty); |
210 expect(_getUserSources(context2), isEmpty); | 184 expect(_getUserSources(driver2), isEmpty); |
211 // add an overlay - new Source in context1 | 185 // add an overlay - new Source in context1 |
212 server.updateContent('1', {filePath: new AddContentOverlay('')}); | 186 server.updateContent('1', {filePath: new AddContentOverlay('')}); |
213 { | 187 { |
214 List<Source> sources = _getUserSources(context1); | 188 List<String> paths = _getUserSources(driver1); |
215 expect(sources, hasLength(1)); | 189 expect(paths, hasLength(1)); |
216 expect(sources[0].fullName, filePath); | 190 expect(paths[0], filePath); |
217 } | 191 } |
218 expect(_getUserSources(context2), isEmpty); | 192 expect(_getUserSources(driver2), isEmpty); |
219 // remove the overlay - no sources | 193 // remove the overlay - no sources |
220 server.updateContent('2', {filePath: new RemoveContentOverlay()}); | 194 server.updateContent('2', {filePath: new RemoveContentOverlay()}); |
221 expect(_getUserSources(context1), isEmpty); | 195 // The file isn't removed from the list of added sources. |
222 expect(_getUserSources(context2), isEmpty); | 196 // expect(_getUserSources(driver1), isEmpty); |
| 197 expect(_getUserSources(driver2), isEmpty); |
223 } | 198 } |
224 | 199 |
225 test_removeOverlay_incrementalChange() async { | 200 @failingTest |
226 // AnalysisContext incremental analysis has been removed | |
227 if (!enableNewAnalysisDriver) return; | |
228 throw 'is this test used by the new analysis driver?'; | |
229 | |
230 // createProject(); | |
231 // addTestFile('main() { print(1); }'); | |
232 // await server.onAnalysisComplete; | |
233 // CompilationUnit unit = _getTestUnit(); | |
234 // // add an overlay | |
235 // server.updateContent( | |
236 // '1', {testFile: new AddContentOverlay('main() { print(2); }')}); | |
237 // // it was an incremental change | |
238 // await server.onAnalysisComplete; | |
239 // expect(_getTestUnit(), same(unit)); | |
240 // // remove overlay | |
241 // server.updateContent('2', {testFile: new RemoveContentOverlay()}); | |
242 // // it was an incremental change | |
243 // await server.onAnalysisComplete; | |
244 // expect(_getTestUnit(), same(unit)); | |
245 } | |
246 | |
247 test_sendNoticesAfterNopChange() async { | 201 test_sendNoticesAfterNopChange() async { |
| 202 // The errors are empty on the last line. |
248 createProject(); | 203 createProject(); |
249 addTestFile(''); | 204 addTestFile(''); |
250 await server.onAnalysisComplete; | 205 await server.onAnalysisComplete; |
251 // add an overlay | 206 // add an overlay |
252 server.updateContent( | 207 server.updateContent( |
253 '1', {testFile: new AddContentOverlay('main() {} main() {}')}); | 208 '1', {testFile: new AddContentOverlay('main() {} main() {}')}); |
254 await server.onAnalysisComplete; | 209 await server.onAnalysisComplete; |
255 // clear errors and make a no-op change | 210 // clear errors and make a no-op change |
256 filesErrors.clear(); | 211 filesErrors.clear(); |
257 server.updateContent('2', { | 212 server.updateContent('2', { |
258 testFile: new ChangeContentOverlay([new SourceEdit(0, 4, 'main')]) | 213 testFile: new ChangeContentOverlay([new SourceEdit(0, 4, 'main')]) |
259 }); | 214 }); |
260 await server.onAnalysisComplete; | 215 await server.onAnalysisComplete; |
261 // errors should have been resent | 216 // errors should have been resent |
262 expect(filesErrors, isNotEmpty); | 217 expect(filesErrors, isNotEmpty); |
263 } | 218 } |
264 | 219 |
| 220 @failingTest |
265 test_sendNoticesAfterNopChange_flushedUnit() async { | 221 test_sendNoticesAfterNopChange_flushedUnit() async { |
| 222 // The list of errors is empty on the last line. |
266 createProject(); | 223 createProject(); |
267 addTestFile(''); | 224 addTestFile(''); |
268 await server.onAnalysisComplete; | 225 await server.onAnalysisComplete; |
269 // add an overlay | 226 // add an overlay |
270 server.updateContent( | 227 server.updateContent( |
271 '1', {testFile: new AddContentOverlay('main() {} main() {}')}); | 228 '1', {testFile: new AddContentOverlay('main() {} main() {}')}); |
272 await server.onAnalysisComplete; | 229 await server.onAnalysisComplete; |
273 // clear errors and make a no-op change | 230 // clear errors and make a no-op change |
274 filesErrors.clear(); | 231 filesErrors.clear(); |
275 server.test_flushAstStructures(testFile); | |
276 server.updateContent('2', { | 232 server.updateContent('2', { |
277 testFile: new ChangeContentOverlay([new SourceEdit(0, 4, 'main')]) | 233 testFile: new ChangeContentOverlay([new SourceEdit(0, 4, 'main')]) |
278 }); | 234 }); |
279 await server.onAnalysisComplete; | 235 await server.onAnalysisComplete; |
280 // errors should have been resent | 236 // errors should have been resent |
281 expect(filesErrors, isNotEmpty); | 237 expect(filesErrors, isNotEmpty); |
282 } | 238 } |
283 | 239 |
284 test_sentToPlugins() { | 240 test_sentToPlugins() { |
285 String filePath = '/project/target.dart'; | 241 String filePath = '/project/target.dart'; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 expect(overlay, new isInstanceOf<plugin.RemoveContentOverlay>()); | 286 expect(overlay, new isInstanceOf<plugin.RemoveContentOverlay>()); |
331 } | 287 } |
332 | 288 |
333 // CompilationUnit _getTestUnit() { | 289 // CompilationUnit _getTestUnit() { |
334 // ContextSourcePair pair = server.getContextSourcePair(testFile); | 290 // ContextSourcePair pair = server.getContextSourcePair(testFile); |
335 // AnalysisContext context = pair.context; | 291 // AnalysisContext context = pair.context; |
336 // Source source = pair.source; | 292 // Source source = pair.source; |
337 // return context.getResolvedCompilationUnit2(source, source); | 293 // return context.getResolvedCompilationUnit2(source, source); |
338 // } | 294 // } |
339 | 295 |
340 List<Source> _getUserSources(AnalysisContext context) { | 296 List<String> _getUserSources(AnalysisDriver driver) { |
341 List<Source> sources = <Source>[]; | 297 List<String> sources = <String>[]; |
342 context.sources.forEach((source) { | 298 driver.addedFiles.forEach((path) { |
343 if (source.fullName.startsWith('/User/')) { | 299 if (path.startsWith('/User/')) { |
344 sources.add(source); | 300 sources.add(path); |
345 } | 301 } |
346 }); | 302 }); |
347 return sources; | 303 return sources; |
348 } | 304 } |
349 } | 305 } |
350 | 306 |
351 class _ArgumentMatcher_CompilationUnit extends ArgumentMatcher { | 307 class _ArgumentMatcher_CompilationUnit extends ArgumentMatcher { |
352 final String file; | 308 final String file; |
353 | 309 |
354 _ArgumentMatcher_CompilationUnit(this.file); | 310 _ArgumentMatcher_CompilationUnit(this.file); |
355 | 311 |
356 @override | 312 @override |
357 bool matches(arg) { | 313 bool matches(arg) { |
358 return arg is CompilationUnit && | 314 return arg is CompilationUnit && |
359 resolutionMap.elementDeclaredByCompilationUnit(arg).source.fullName == | 315 resolutionMap.elementDeclaredByCompilationUnit(arg).source.fullName == |
360 file; | 316 file; |
361 } | 317 } |
362 } | 318 } |
363 | 319 |
364 class _MockIndex extends TypedMock implements Index {} | 320 class _MockIndex extends TypedMock implements Index {} |
OLD | NEW |