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 import 'dart:async'; | 5 import 'dart:async'; |
6 | 6 |
7 import 'package:analysis_server/protocol/protocol.dart'; | 7 import 'package:analysis_server/protocol/protocol.dart'; |
8 import 'package:analysis_server/protocol/protocol_generated.dart'; | 8 import 'package:analysis_server/protocol/protocol_generated.dart'; |
9 import 'package:analysis_server/src/analysis_server.dart'; | 9 import 'package:analysis_server/src/analysis_server.dart'; |
10 import 'package:analysis_server/src/constants.dart'; | 10 import 'package:analysis_server/src/constants.dart'; |
11 import 'package:analysis_server/src/context_manager.dart'; | |
12 import 'package:analysis_server/src/domain_server.dart'; | 11 import 'package:analysis_server/src/domain_server.dart'; |
13 import 'package:analysis_server/src/operation/operation.dart'; | 12 import 'package:analysis_server/src/operation/operation.dart'; |
14 import 'package:analysis_server/src/plugin/server_plugin.dart'; | 13 import 'package:analysis_server/src/plugin/server_plugin.dart'; |
15 import 'package:analyzer/exception/exception.dart'; | 14 import 'package:analyzer/exception/exception.dart'; |
16 import 'package:analyzer/file_system/file_system.dart'; | 15 import 'package:analyzer/file_system/file_system.dart'; |
17 import 'package:analyzer/file_system/memory_file_system.dart'; | 16 import 'package:analyzer/file_system/memory_file_system.dart'; |
18 import 'package:analyzer/instrumentation/instrumentation.dart'; | 17 import 'package:analyzer/instrumentation/instrumentation.dart'; |
19 import 'package:analyzer/source/package_map_resolver.dart'; | |
20 import 'package:analyzer/src/generated/engine.dart'; | 18 import 'package:analyzer/src/generated/engine.dart'; |
21 import 'package:analyzer/src/generated/sdk.dart'; | 19 import 'package:analyzer/src/generated/sdk.dart'; |
22 import 'package:analyzer/src/generated/source.dart'; | 20 import 'package:analyzer/src/generated/source.dart'; |
23 import 'package:analyzer_plugin/protocol/protocol_common.dart'; | 21 import 'package:analyzer_plugin/protocol/protocol_common.dart'; |
24 import 'package:plugin/manager.dart'; | 22 import 'package:plugin/manager.dart'; |
25 import 'package:plugin/plugin.dart'; | 23 import 'package:plugin/plugin.dart'; |
26 import 'package:test/test.dart'; | 24 import 'package:test/test.dart'; |
27 import 'package:test_reflective_loader/test_reflective_loader.dart'; | 25 import 'package:test_reflective_loader/test_reflective_loader.dart'; |
28 import 'package:typed_mock/typed_mock.dart'; | 26 import 'package:typed_mock/typed_mock.dart'; |
29 | 27 |
30 import 'mock_sdk.dart'; | 28 import 'mock_sdk.dart'; |
31 import 'mocks.dart'; | 29 import 'mocks.dart'; |
32 | 30 |
33 main() { | 31 main() { |
34 defineReflectiveSuite(() { | 32 defineReflectiveSuite(() { |
35 defineReflectiveTests(AnalysisServerTest); | 33 defineReflectiveTests(AnalysisServerTest); |
36 }); | 34 }); |
37 } | 35 } |
38 | 36 |
39 @reflectiveTest | 37 @reflectiveTest |
40 class AnalysisServerTest { | 38 class AnalysisServerTest { |
41 MockServerChannel channel; | 39 MockServerChannel channel; |
42 AnalysisServer server; | 40 AnalysisServer server; |
43 MemoryResourceProvider resourceProvider; | 41 MemoryResourceProvider resourceProvider; |
44 MockPackageMapProvider packageMapProvider; | 42 MockPackageMapProvider packageMapProvider; |
45 | 43 |
46 /** | |
47 * Verify that getAnalysisContextForSource returns the correct contexts even | |
48 * for sources that are included by multiple contexts. | |
49 * | |
50 * See dartbug.com/21898 | |
51 */ | |
52 Future fail_getAnalysisContextForSource_crossImports() { | |
53 // Subscribe to STATUS so we'll know when analysis is done. | |
54 server.serverServices = [ServerService.STATUS].toSet(); | |
55 // Analyze project foo containing foo.dart and project bar containing | |
56 // bar.dart. | |
57 resourceProvider.newFolder('/foo'); | |
58 resourceProvider.newFolder('/bar'); | |
59 File foo = resourceProvider.newFile( | |
60 '/foo/foo.dart', | |
61 ''' | |
62 libary foo; | |
63 import "../bar/bar.dart"; | |
64 '''); | |
65 Source fooSource = foo.createSource(); | |
66 File bar = resourceProvider.newFile( | |
67 '/bar/bar.dart', | |
68 ''' | |
69 library bar; | |
70 import "../foo/foo.dart"; | |
71 '''); | |
72 Source barSource = bar.createSource(); | |
73 server.setAnalysisRoots('0', ['/foo', '/bar'], [], {}); | |
74 return server.onAnalysisComplete.then((_) { | |
75 expect(server.statusAnalyzing, isFalse); | |
76 // Make sure getAnalysisContext returns the proper context for each. | |
77 AnalysisContext fooContext = | |
78 server.getAnalysisContextForSource(fooSource); | |
79 expect(fooContext, isNotNull); | |
80 AnalysisContext barContext = | |
81 server.getAnalysisContextForSource(barSource); | |
82 expect(barContext, isNotNull); | |
83 expect(fooContext, isNot(same(barContext))); | |
84 expect(fooContext.getKindOf(fooSource), SourceKind.LIBRARY); | |
85 expect(fooContext.getKindOf(barSource), SourceKind.UNKNOWN); | |
86 expect(barContext.getKindOf(fooSource), SourceKind.UNKNOWN); | |
87 expect(barContext.getKindOf(barSource), SourceKind.LIBRARY); | |
88 }); | |
89 } | |
90 | |
91 /** | |
92 * Verify that getAnalysisContextForSource returns the correct contexts even | |
93 * for sources that haven't been analyzed yet. | |
94 * | |
95 * See dartbug.com/21898 | |
96 */ | |
97 Future fail_getAnalysisContextForSource_unanalyzed() { | |
98 // Subscribe to STATUS so we'll know when analysis is done. | |
99 server.serverServices = [ServerService.STATUS].toSet(); | |
100 // Analyze project foo containing foo.dart and project bar containing | |
101 // bar.dart. | |
102 resourceProvider.newFolder('/foo'); | |
103 resourceProvider.newFolder('/bar'); | |
104 File foo = resourceProvider.newFile('/foo/foo.dart', 'library lib;'); | |
105 Source fooSource = foo.createSource(); | |
106 File bar = resourceProvider.newFile('/bar/bar.dart', 'library lib;'); | |
107 Source barSource = bar.createSource(); | |
108 server.setAnalysisRoots('0', ['/foo', '/bar'], [], {}); | |
109 AnalysisContext fooContext = server.getAnalysisContextForSource(fooSource); | |
110 expect(fooContext, isNotNull); | |
111 AnalysisContext barContext = server.getAnalysisContextForSource(barSource); | |
112 expect(barContext, isNotNull); | |
113 expect(fooContext, isNot(same(barContext))); | |
114 return server.onAnalysisComplete.then((_) { | |
115 expect(server.statusAnalyzing, isFalse); | |
116 // Make sure getAnalysisContext returned the proper context for each. | |
117 expect(fooContext.getKindOf(fooSource), SourceKind.LIBRARY); | |
118 expect(fooContext.getKindOf(barSource), SourceKind.UNKNOWN); | |
119 expect(barContext.getKindOf(fooSource), SourceKind.UNKNOWN); | |
120 expect(barContext.getKindOf(barSource), SourceKind.LIBRARY); | |
121 }); | |
122 } | |
123 | |
124 void processRequiredPlugins(ServerPlugin serverPlugin) { | 44 void processRequiredPlugins(ServerPlugin serverPlugin) { |
125 List<Plugin> plugins = <Plugin>[]; | 45 List<Plugin> plugins = <Plugin>[]; |
126 plugins.addAll(AnalysisEngine.instance.requiredPlugins); | 46 plugins.addAll(AnalysisEngine.instance.requiredPlugins); |
127 plugins.add(serverPlugin); | 47 plugins.add(serverPlugin); |
128 | 48 |
129 ExtensionManager manager = new ExtensionManager(); | 49 ExtensionManager manager = new ExtensionManager(); |
130 manager.processPlugins(plugins); | 50 manager.processPlugins(plugins); |
131 } | 51 } |
132 | 52 |
133 void setUp() { | 53 void setUp() { |
134 ServerPlugin serverPlugin = new ServerPlugin(); | 54 ServerPlugin serverPlugin = new ServerPlugin(); |
135 processRequiredPlugins(serverPlugin); | 55 processRequiredPlugins(serverPlugin); |
136 channel = new MockServerChannel(); | 56 channel = new MockServerChannel(); |
137 resourceProvider = new MemoryResourceProvider(); | 57 resourceProvider = new MemoryResourceProvider(); |
138 // Create an SDK in the mock file system. | 58 // Create an SDK in the mock file system. |
139 new MockSdk(resourceProvider: resourceProvider); | 59 new MockSdk(resourceProvider: resourceProvider); |
140 packageMapProvider = new MockPackageMapProvider(); | 60 packageMapProvider = new MockPackageMapProvider(); |
141 server = new AnalysisServer( | 61 server = new AnalysisServer( |
142 channel, | 62 channel, |
143 resourceProvider, | 63 resourceProvider, |
144 packageMapProvider, | 64 packageMapProvider, |
145 null, | 65 null, |
146 serverPlugin, | 66 serverPlugin, |
147 new AnalysisServerOptions(), | 67 new AnalysisServerOptions(), |
148 new DartSdkManager('/', false), | 68 new DartSdkManager('/', false), |
149 InstrumentationService.NULL_SERVICE, | 69 InstrumentationService.NULL_SERVICE, |
150 rethrowExceptions: true); | 70 rethrowExceptions: true); |
151 } | 71 } |
152 | 72 |
153 Future test_contextDisposed() { | |
154 resourceProvider.newFolder('/foo'); | |
155 resourceProvider.newFile('/foo/bar.dart', 'library lib;'); | |
156 server.setAnalysisRoots('0', ['/foo'], [], {}); | |
157 AnalysisContext context; | |
158 return pumpEventQueue() | |
159 .then((_) { | |
160 context = server.getAnalysisContext('/foo/bar.dart'); | |
161 server.setAnalysisRoots('1', [], [], {}); | |
162 }) | |
163 .then((_) => pumpEventQueue()) | |
164 .then((_) { | |
165 expect(context.isDisposed, isTrue); | |
166 }); | |
167 } | |
168 | |
169 Future test_contextsChangedEvent() { | |
170 resourceProvider.newFolder('/foo'); | |
171 | |
172 bool wasAdded = false; | |
173 bool wasChanged = false; | |
174 bool wasRemoved = false; | |
175 server.onContextsChanged.listen((ContextsChangedEvent event) { | |
176 wasAdded = event.added.length == 1; | |
177 if (wasAdded) { | |
178 expect(event.added[0], isNotNull); | |
179 } | |
180 wasChanged = event.changed.length == 1; | |
181 if (wasChanged) { | |
182 expect(event.changed[0], isNotNull); | |
183 } | |
184 wasRemoved = event.removed.length == 1; | |
185 if (wasRemoved) { | |
186 expect(event.removed[0], isNotNull); | |
187 } | |
188 }); | |
189 | |
190 server.setAnalysisRoots('0', ['/foo'], [], {}); | |
191 return pumpEventQueue().then((_) { | |
192 expect(wasAdded, isTrue); | |
193 expect(wasChanged, isFalse); | |
194 expect(wasRemoved, isFalse); | |
195 | |
196 wasAdded = false; | |
197 wasChanged = false; | |
198 wasRemoved = false; | |
199 server.setAnalysisRoots('0', ['/foo'], [], {'/foo': '/bar'}); | |
200 return pumpEventQueue(); | |
201 }).then((_) { | |
202 expect(wasAdded, isFalse); | |
203 expect(wasChanged, isTrue); | |
204 expect(wasRemoved, isFalse); | |
205 | |
206 wasAdded = false; | |
207 wasChanged = false; | |
208 wasRemoved = false; | |
209 server.setAnalysisRoots('0', [], [], {}); | |
210 return pumpEventQueue(); | |
211 }).then((_) { | |
212 expect(wasAdded, isFalse); | |
213 expect(wasChanged, isFalse); | |
214 expect(wasRemoved, isTrue); | |
215 }); | |
216 } | |
217 | |
218 Future test_echo() { | 73 Future test_echo() { |
219 server.handlers = [new EchoHandler()]; | 74 server.handlers = [new EchoHandler()]; |
220 var request = new Request('my22', 'echo'); | 75 var request = new Request('my22', 'echo'); |
221 return channel.sendRequest(request).then((Response response) { | 76 return channel.sendRequest(request).then((Response response) { |
222 expect(response.id, equals('my22')); | 77 expect(response.id, equals('my22')); |
223 expect(response.error, isNull); | 78 expect(response.error, isNull); |
224 }); | 79 }); |
225 } | 80 } |
226 | 81 |
227 Future test_getAnalysisContextForSource() { | |
228 // Subscribe to STATUS so we'll know when analysis is done. | |
229 server.serverServices = [ServerService.STATUS].toSet(); | |
230 // Analyze project foo containing foo.dart and project bar containing | |
231 // bar.dart. | |
232 resourceProvider.newFolder('/foo'); | |
233 resourceProvider.newFolder('/bar'); | |
234 File foo = resourceProvider.newFile('/foo/foo.dart', 'library lib;'); | |
235 Source fooSource = foo.createSource(); | |
236 File bar = resourceProvider.newFile('/bar/bar.dart', 'library lib;'); | |
237 Source barSource = bar.createSource(); | |
238 server.setAnalysisRoots('0', ['/foo', '/bar'], [], {}); | |
239 return server.onAnalysisComplete.then((_) { | |
240 expect(server.statusAnalyzing, isFalse); | |
241 // Make sure getAnalysisContext returns the proper context for each. | |
242 AnalysisContext fooContext = | |
243 server.getAnalysisContextForSource(fooSource); | |
244 expect(fooContext, isNotNull); | |
245 AnalysisContext barContext = | |
246 server.getAnalysisContextForSource(barSource); | |
247 expect(barContext, isNotNull); | |
248 expect(fooContext, isNot(same(barContext))); | |
249 expect(fooContext.getKindOf(fooSource), SourceKind.LIBRARY); | |
250 expect(fooContext.getKindOf(barSource), SourceKind.UNKNOWN); | |
251 expect(barContext.getKindOf(fooSource), SourceKind.UNKNOWN); | |
252 expect(barContext.getKindOf(barSource), SourceKind.LIBRARY); | |
253 }); | |
254 } | |
255 | |
256 test_getContextSourcePair_nested() { | |
257 String dir1Path = '/dir1'; | |
258 String dir2Path = dir1Path + '/dir2'; | |
259 String filePath = dir2Path + '/file.dart'; | |
260 resourceProvider.newFile('$dir1Path/.packages', ''); | |
261 resourceProvider.newFile('$dir2Path/.packages', ''); | |
262 resourceProvider.newFile(filePath, 'library lib;'); | |
263 // create contexts | |
264 server.setAnalysisRoots('0', [dir1Path], [], {}); | |
265 // get pair | |
266 ContextSourcePair pair = server.getContextSourcePair(filePath); | |
267 _assertContextOfFolder(pair.context, dir2Path); | |
268 Source source = pair.source; | |
269 expect(source, isNotNull); | |
270 expect(source.uri.scheme, 'file'); | |
271 expect(source.fullName, filePath); | |
272 } | |
273 | |
274 test_getContextSourcePair_nonFile() { | |
275 String dirPath = '/dir'; | |
276 Folder dir = resourceProvider.newFolder(dirPath); | |
277 | |
278 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext(); | |
279 _configureSourceFactory(context); | |
280 server.folderMap[dir] = context; | |
281 | |
282 ContextSourcePair pair = server.getContextSourcePair(dirPath); | |
283 expect(pair, isNotNull); | |
284 expect(pair.context, isNull); | |
285 expect(pair.source, isNull); | |
286 } | |
287 | |
288 test_getContextSourcePair_simple() { | |
289 String dirPath = '/dir'; | |
290 String filePath = dirPath + '/file.dart'; | |
291 resourceProvider.newFile(filePath, 'library lib;'); | |
292 // create contexts | |
293 server.setAnalysisRoots('0', [dirPath], [], {}); | |
294 // get pair | |
295 ContextSourcePair pair = server.getContextSourcePair(filePath); | |
296 _assertContextOfFolder(pair.context, dirPath); | |
297 Source source = pair.source; | |
298 expect(source, isNotNull); | |
299 expect(source.uri.scheme, 'file'); | |
300 expect(source.fullName, filePath); | |
301 } | |
302 | |
303 test_getContextSourcePair_withPackagesFile() { | |
304 String dirPath = '/dir'; | |
305 String packagesFilePath = dirPath + '/.packages'; | |
306 resourceProvider.newFile(packagesFilePath, 'dir:lib/'); | |
307 String filePath = dirPath + '/lib/file.dart'; | |
308 resourceProvider.newFile(filePath, 'library lib;'); | |
309 // create contexts | |
310 server.setAnalysisRoots('0', [dirPath], [], {}); | |
311 // get pair | |
312 ContextSourcePair pair = server.getContextSourcePair(filePath); | |
313 _assertContextOfFolder(pair.context, dirPath); | |
314 Source source = pair.source; | |
315 expect(source, isNotNull); | |
316 expect(source.uri.scheme, 'package'); | |
317 expect(source.fullName, filePath); | |
318 } | |
319 | |
320 /** | 82 /** |
321 * Test that having multiple analysis contexts analyze the same file doesn't | 83 * Test that having multiple analysis contexts analyze the same file doesn't |
322 * cause that file to receive duplicate notifications when it's modified. | 84 * cause that file to receive duplicate notifications when it's modified. |
323 */ | 85 */ |
324 Future test_no_duplicate_notifications() async { | 86 Future test_no_duplicate_notifications() async { |
325 // Subscribe to STATUS so we'll know when analysis is done. | 87 // Subscribe to STATUS so we'll know when analysis is done. |
326 server.serverServices = [ServerService.STATUS].toSet(); | 88 server.serverServices = [ServerService.STATUS].toSet(); |
327 resourceProvider.newFolder('/foo'); | 89 resourceProvider.newFolder('/foo'); |
328 resourceProvider.newFolder('/bar'); | 90 resourceProvider.newFolder('/bar'); |
329 resourceProvider.newFile('/foo/foo.dart', 'import "../bar/bar.dart";'); | 91 resourceProvider.newFile('/foo/foo.dart', 'import "../bar/bar.dart";'); |
(...skipping 27 matching lines...) Expand all Loading... |
357 break; | 119 break; |
358 default: | 120 default: |
359 if (!notificationTypesReceived.add(notificationType)) { | 121 if (!notificationTypesReceived.add(notificationType)) { |
360 fail('Notification type $notificationType received more than once'); | 122 fail('Notification type $notificationType received more than once'); |
361 } | 123 } |
362 break; | 124 break; |
363 } | 125 } |
364 } | 126 } |
365 } | 127 } |
366 | 128 |
367 test_operationsRemovedOnContextDisposal() async { | |
368 resourceProvider.newFolder('/foo'); | |
369 resourceProvider.newFile('/foo/baz.dart', 'library lib;'); | |
370 resourceProvider.newFolder('/bar'); | |
371 resourceProvider.newFile('/bar/baz.dart', 'library lib;'); | |
372 server.setAnalysisRoots('0', ['/foo', '/bar'], [], {}); | |
373 await pumpEventQueue(); | |
374 AnalysisContext contextFoo = server.getAnalysisContext('/foo/baz.dart'); | |
375 AnalysisContext contextBar = server.getAnalysisContext('/bar/baz.dart'); | |
376 _MockServerOperation operationFoo = new _MockServerOperation(contextFoo); | |
377 _MockServerOperation operationBar = new _MockServerOperation(contextBar); | |
378 server.scheduleOperation(operationFoo); | |
379 server.scheduleOperation(operationBar); | |
380 server.setAnalysisRoots('1', ['/foo'], [], {}); | |
381 await pumpEventQueue(); | |
382 expect(operationFoo.isComplete, isTrue); | |
383 expect(operationBar.isComplete, isFalse); | |
384 } | |
385 | |
386 Future test_prioritySourcesChangedEvent() { | |
387 resourceProvider.newFolder('/foo'); | |
388 | |
389 int eventCount = 0; | |
390 Source firstSource = null; | |
391 server.onPriorityChange.listen((PriorityChangeEvent event) { | |
392 ++eventCount; | |
393 firstSource = event.firstSource; | |
394 }); | |
395 | |
396 server.setAnalysisRoots('0', ['/foo'], [], {}); | |
397 return pumpEventQueue().then((_) { | |
398 expect(eventCount, 0); | |
399 | |
400 server.setPriorityFiles('1', ['/foo/bar.dart']); | |
401 return pumpEventQueue(); | |
402 }).then((_) { | |
403 expect(eventCount, 1); | |
404 expect(firstSource.fullName, '/foo/bar.dart'); | |
405 | |
406 server.setPriorityFiles('2', ['/foo/b1.dart', '/foo/b2.dart']); | |
407 return pumpEventQueue(); | |
408 }).then((_) { | |
409 expect(eventCount, 2); | |
410 expect(firstSource.fullName, '/foo/b1.dart'); | |
411 | |
412 server.setPriorityFiles('17', []); | |
413 return pumpEventQueue(); | |
414 }).then((_) { | |
415 expect(eventCount, 3); | |
416 expect(firstSource, isNull); | |
417 }); | |
418 } | |
419 | |
420 void test_rethrowExceptions() { | 129 void test_rethrowExceptions() { |
421 Exception exceptionToThrow = new Exception('test exception'); | 130 Exception exceptionToThrow = new Exception('test exception'); |
422 MockServerOperation operation = | 131 MockServerOperation operation = |
423 new MockServerOperation(ServerOperationPriority.ANALYSIS, (_) { | 132 new MockServerOperation(ServerOperationPriority.ANALYSIS, (_) { |
424 throw exceptionToThrow; | 133 throw exceptionToThrow; |
425 }); | 134 }); |
426 server.operationQueue.add(operation); | 135 server.operationQueue.add(operation); |
427 server.performOperationPending = true; | 136 server.performOperationPending = true; |
428 try { | 137 try { |
429 server.performOperation(); | 138 server.performOperation(); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 } | 228 } |
520 | 229 |
521 Future test_unknownRequest() { | 230 Future test_unknownRequest() { |
522 server.handlers = [new EchoHandler()]; | 231 server.handlers = [new EchoHandler()]; |
523 var request = new Request('my22', 'randomRequest'); | 232 var request = new Request('my22', 'randomRequest'); |
524 return channel.sendRequest(request).then((Response response) { | 233 return channel.sendRequest(request).then((Response response) { |
525 expect(response.id, equals('my22')); | 234 expect(response.id, equals('my22')); |
526 expect(response.error, isNotNull); | 235 expect(response.error, isNotNull); |
527 }); | 236 }); |
528 } | 237 } |
529 | |
530 void _assertContextOfFolder( | |
531 AnalysisContext context, String expectedFolderPath) { | |
532 Folder expectedFolder = resourceProvider.newFolder(expectedFolderPath); | |
533 ContextInfo expectedContextInfo = | |
534 (server.contextManager as ContextManagerImpl) | |
535 .getContextInfoFor(expectedFolder); | |
536 expect(expectedContextInfo, isNotNull); | |
537 expect(context, same(expectedContextInfo.context)); | |
538 } | |
539 | |
540 void _configureSourceFactory(AnalysisContext context) { | |
541 var resourceUriResolver = new ResourceUriResolver(resourceProvider); | |
542 var packageUriResolver = new PackageMapUriResolver( | |
543 resourceProvider, packageMapProvider.packageMap); | |
544 context.sourceFactory = | |
545 new SourceFactory([packageUriResolver, resourceUriResolver]); | |
546 } | |
547 } | 238 } |
548 | 239 |
549 class EchoHandler implements RequestHandler { | 240 class EchoHandler implements RequestHandler { |
550 @override | 241 @override |
551 Response handleRequest(Request request) { | 242 Response handleRequest(Request request) { |
552 if (request.method == 'echo') { | 243 if (request.method == 'echo') { |
553 return new Response(request.id, result: {'echo': true}); | 244 return new Response(request.id, result: {'echo': true}); |
554 } | 245 } |
555 return null; | 246 return null; |
556 } | 247 } |
557 } | 248 } |
558 | |
559 /** | |
560 * A [ServerOperation] that does nothing but keep track of whether or not it | |
561 * has been performed. | |
562 */ | |
563 class _MockServerOperation implements ServerOperation { | |
564 final AnalysisContext context; | |
565 bool isComplete = false; | |
566 | |
567 _MockServerOperation(this.context); | |
568 | |
569 @override | |
570 ServerOperationPriority get priority => ServerOperationPriority.ANALYSIS; | |
571 | |
572 @override | |
573 void perform(AnalysisServer server) { | |
574 isComplete = true; | |
575 } | |
576 } | |
OLD | NEW |