| 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 analysis.server; | 5 library analysis.server; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 | 9 |
| 10 import 'package:analyzer/file_system/file_system.dart'; | 10 import 'package:analyzer/file_system/file_system.dart'; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 | 30 |
| 31 | 31 |
| 32 class ServerContextManager extends ContextManager { | 32 class ServerContextManager extends ContextManager { |
| 33 final AnalysisServer analysisServer; | 33 final AnalysisServer analysisServer; |
| 34 | 34 |
| 35 /** | 35 /** |
| 36 * The default options used to create new analysis contexts. | 36 * The default options used to create new analysis contexts. |
| 37 */ | 37 */ |
| 38 AnalysisOptionsImpl defaultOptions = new AnalysisOptionsImpl(); | 38 AnalysisOptionsImpl defaultOptions = new AnalysisOptionsImpl(); |
| 39 | 39 |
| 40 ServerContextManager( | 40 ServerContextManager(this.analysisServer, ResourceProvider resourceProvider, |
| 41 this.analysisServer, ResourceProvider resourceProvider, | |
| 42 PackageMapProvider packageMapProvider) | 41 PackageMapProvider packageMapProvider) |
| 43 : super(resourceProvider, packageMapProvider); | 42 : super(resourceProvider, packageMapProvider); |
| 44 | 43 |
| 45 @override | 44 @override |
| 46 void addContext(Folder folder, Map<String, List<Folder>> packageMap) { | 45 void addContext(Folder folder, Map<String, List<Folder>> packageMap) { |
| 47 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext(); | 46 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext(); |
| 48 analysisServer.folderMap[folder] = context; | 47 analysisServer.folderMap[folder] = context; |
| 49 context.sourceFactory = _createSourceFactory(packageMap); | 48 context.sourceFactory = _createSourceFactory(packageMap); |
| 50 context.analysisOptions = new AnalysisOptionsImpl.con1(defaultOptions); | 49 context.analysisOptions = new AnalysisOptionsImpl.con1(defaultOptions); |
| 51 analysisServer.schedulePerformAnalysisOperation(context); | 50 analysisServer.schedulePerformAnalysisOperation(context); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 65 AnalysisContext context = analysisServer.folderMap.remove(folder); | 64 AnalysisContext context = analysisServer.folderMap.remove(folder); |
| 66 if (analysisServer.index != null) { | 65 if (analysisServer.index != null) { |
| 67 analysisServer.index.removeContext(context); | 66 analysisServer.index.removeContext(context); |
| 68 } | 67 } |
| 69 analysisServer.sendContextAnalysisDoneNotifications( | 68 analysisServer.sendContextAnalysisDoneNotifications( |
| 70 context, | 69 context, |
| 71 AnalysisDoneReason.CONTEXT_REMOVED); | 70 AnalysisDoneReason.CONTEXT_REMOVED); |
| 72 } | 71 } |
| 73 | 72 |
| 74 @override | 73 @override |
| 75 void updateContextPackageMap(Folder contextFolder, | 74 void updateContextPackageMap(Folder contextFolder, Map<String, |
| 76 Map<String, List<Folder>> packageMap) { | 75 List<Folder>> packageMap) { |
| 77 AnalysisContext context = analysisServer.folderMap[contextFolder]; | 76 AnalysisContext context = analysisServer.folderMap[contextFolder]; |
| 78 context.sourceFactory = _createSourceFactory(packageMap); | 77 context.sourceFactory = _createSourceFactory(packageMap); |
| 79 analysisServer.schedulePerformAnalysisOperation(context); | 78 analysisServer.schedulePerformAnalysisOperation(context); |
| 80 } | 79 } |
| 81 | 80 |
| 82 /** | 81 /** |
| 83 * Set up a [SourceFactory] that resolves packages using the given | 82 * Set up a [SourceFactory] that resolves packages using the given |
| 84 * [packageMap]. | 83 * [packageMap]. |
| 85 */ | 84 */ |
| 86 SourceFactory _createSourceFactory(Map<String, List<Folder>> packageMap) { | 85 SourceFactory _createSourceFactory(Map<String, List<Folder>> packageMap) { |
| 87 List<UriResolver> resolvers = <UriResolver>[ | 86 List<UriResolver> resolvers = <UriResolver>[ |
| 88 new DartUriResolver(analysisServer.defaultSdk), | 87 new DartUriResolver(analysisServer.defaultSdk), |
| 89 new ResourceUriResolver(resourceProvider), | 88 new ResourceUriResolver(resourceProvider), |
| 90 new PackageMapUriResolver(resourceProvider, packageMap) | 89 new PackageMapUriResolver(resourceProvider, packageMap)]; |
| 91 ]; | |
| 92 return new SourceFactory(resolvers); | 90 return new SourceFactory(resolvers); |
| 93 } | 91 } |
| 94 } | 92 } |
| 95 | 93 |
| 96 | 94 |
| 97 /** | 95 /** |
| 98 * Enum representing reasons why analysis might be done for a given file. | 96 * Enum representing reasons why analysis might be done for a given file. |
| 99 */ | 97 */ |
| 100 class AnalysisDoneReason { | 98 class AnalysisDoneReason { |
| 101 /** | 99 /** |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 * If [rethrowExceptions] is true, then any exceptions thrown by analysis are | 225 * If [rethrowExceptions] is true, then any exceptions thrown by analysis are |
| 228 * propagated up the call stack. The default is true to allow analysis | 226 * propagated up the call stack. The default is true to allow analysis |
| 229 * exceptions to show up in unit tests, but it should be set to false when | 227 * exceptions to show up in unit tests, but it should be set to false when |
| 230 * running a full analysis server. | 228 * running a full analysis server. |
| 231 */ | 229 */ |
| 232 AnalysisServer(this.channel, this.resourceProvider, | 230 AnalysisServer(this.channel, this.resourceProvider, |
| 233 PackageMapProvider packageMapProvider, this.index, this.defaultSdk, | 231 PackageMapProvider packageMapProvider, this.index, this.defaultSdk, |
| 234 {this.rethrowExceptions: true}) { | 232 {this.rethrowExceptions: true}) { |
| 235 searchEngine = createSearchEngine(index); | 233 searchEngine = createSearchEngine(index); |
| 236 operationQueue = new ServerOperationQueue(this); | 234 operationQueue = new ServerOperationQueue(this); |
| 237 contextDirectoryManager = new ServerContextManager( | 235 contextDirectoryManager = |
| 238 this, resourceProvider, packageMapProvider); | 236 new ServerContextManager(this, resourceProvider, packageMapProvider); |
| 239 AnalysisEngine.instance.logger = new AnalysisLogger(); | 237 AnalysisEngine.instance.logger = new AnalysisLogger(); |
| 240 running = true; | 238 running = true; |
| 241 Notification notification = new ServerConnectedParams().toNotification(); | 239 Notification notification = new ServerConnectedParams().toNotification(); |
| 242 channel.sendNotification(notification); | 240 channel.sendNotification(notification); |
| 243 channel.listen(handleRequest, onDone: done, onError: error); | 241 channel.listen(handleRequest, onDone: done, onError: error); |
| 244 } | 242 } |
| 245 | 243 |
| 246 /** | 244 /** |
| 247 * Schedules execution of the given [ServerOperation]. | 245 * Schedules execution of the given [ServerOperation]. |
| 248 */ | 246 */ |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 if (sourceList == null) { | 289 if (sourceList == null) { |
| 292 sourceList = <Source>[]; | 290 sourceList = <Source>[]; |
| 293 sourceMap[analysisContext] = sourceList; | 291 sourceMap[analysisContext] = sourceList; |
| 294 } | 292 } |
| 295 sourceList.add(getSource(file)); | 293 sourceList.add(getSource(file)); |
| 296 } | 294 } |
| 297 }); | 295 }); |
| 298 if (unanalyzed.isNotEmpty) { | 296 if (unanalyzed.isNotEmpty) { |
| 299 StringBuffer buffer = new StringBuffer(); | 297 StringBuffer buffer = new StringBuffer(); |
| 300 buffer.writeAll(unanalyzed, ', '); | 298 buffer.writeAll(unanalyzed, ', '); |
| 301 throw new RequestFailure(new Response.unanalyzedPriorityFiles(request, | 299 throw new RequestFailure( |
| 302 buffer.toString())); | 300 new Response.unanalyzedPriorityFiles(request, buffer.toString())); |
| 303 } | 301 } |
| 304 folderMap.forEach((Folder folder, AnalysisContext context) { | 302 folderMap.forEach((Folder folder, AnalysisContext context) { |
| 305 List<Source> sourceList = sourceMap[context]; | 303 List<Source> sourceList = sourceMap[context]; |
| 306 if (sourceList == null) { | 304 if (sourceList == null) { |
| 307 sourceList = Source.EMPTY_ARRAY; | 305 sourceList = Source.EMPTY_ARRAY; |
| 308 } | 306 } |
| 309 context.analysisPriorityOrder = sourceList; | 307 context.analysisPriorityOrder = sourceList; |
| 310 }); | 308 }); |
| 311 } | 309 } |
| 312 | 310 |
| 313 /** | 311 /** |
| 314 * Use the given updaters to update the values of the options in every | 312 * Use the given updaters to update the values of the options in every |
| 315 * existing analysis context. | 313 * existing analysis context. |
| 316 */ | 314 */ |
| 317 void updateOptions(List<OptionUpdater> optionUpdaters) { | 315 void updateOptions(List<OptionUpdater> optionUpdaters) { |
| 318 // | 316 // |
| 319 // Update existing contexts. | 317 // Update existing contexts. |
| 320 // | 318 // |
| 321 folderMap.forEach((Folder folder, AnalysisContext context) { | 319 folderMap.forEach((Folder folder, AnalysisContext context) { |
| 322 AnalysisOptionsImpl options = new AnalysisOptionsImpl.con1(context.analysi
sOptions); | 320 AnalysisOptionsImpl options = |
| 321 new AnalysisOptionsImpl.con1(context.analysisOptions); |
| 323 optionUpdaters.forEach((OptionUpdater optionUpdater) { | 322 optionUpdaters.forEach((OptionUpdater optionUpdater) { |
| 324 optionUpdater(options); | 323 optionUpdater(options); |
| 325 }); | 324 }); |
| 326 context.analysisOptions = options; | 325 context.analysisOptions = options; |
| 327 }); | 326 }); |
| 328 // | 327 // |
| 329 // Update the defaults used to create new contexts. | 328 // Update the defaults used to create new contexts. |
| 330 // | 329 // |
| 331 AnalysisOptionsImpl options = contextDirectoryManager.defaultOptions; | 330 AnalysisOptionsImpl options = contextDirectoryManager.defaultOptions; |
| 332 optionUpdaters.forEach((OptionUpdater optionUpdater) { | 331 optionUpdaters.forEach((OptionUpdater optionUpdater) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 return; | 397 return; |
| 399 } | 398 } |
| 400 if (response != null) { | 399 if (response != null) { |
| 401 channel.sendResponse(response); | 400 channel.sendResponse(response); |
| 402 return; | 401 return; |
| 403 } | 402 } |
| 404 } on RequestFailure catch (exception) { | 403 } on RequestFailure catch (exception) { |
| 405 channel.sendResponse(exception.response); | 404 channel.sendResponse(exception.response); |
| 406 return; | 405 return; |
| 407 } catch (exception, stackTrace) { | 406 } catch (exception, stackTrace) { |
| 408 _sendServerErrorNotification(exception, stackTrace); | 407 RequestError error = new RequestError( |
| 409 RequestError error = | 408 RequestErrorCode.SERVER_ERROR, |
| 410 new RequestError(RequestErrorCode.SERVER_ERROR, 'Server Error'); | 409 exception); |
| 410 if (stackTrace != null) { |
| 411 error.stackTrace = stackTrace.toString(); |
| 412 } |
| 411 Response response = new Response(request.id, error: error); | 413 Response response = new Response(request.id, error: error); |
| 412 channel.sendResponse(response); | 414 channel.sendResponse(response); |
| 413 return; | 415 return; |
| 414 } | 416 } |
| 415 } | 417 } |
| 416 channel.sendResponse(new Response.unknownRequest(request)); | 418 channel.sendResponse(new Response.unknownRequest(request)); |
| 417 }, onError: _sendServerErrorNotification); | 419 }, onError: _sendServerErrorNotification); |
| 418 } | 420 } |
| 419 | 421 |
| 420 /** | 422 /** |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 if (!serverServices.contains(ServerService.STATUS)) { | 515 if (!serverServices.contains(ServerService.STATUS)) { |
| 514 return; | 516 return; |
| 515 } | 517 } |
| 516 // Only send status when it changes | 518 // Only send status when it changes |
| 517 bool isAnalyzing = operation != null; | 519 bool isAnalyzing = operation != null; |
| 518 if (statusAnalyzing == isAnalyzing) { | 520 if (statusAnalyzing == isAnalyzing) { |
| 519 return; | 521 return; |
| 520 } | 522 } |
| 521 statusAnalyzing = isAnalyzing; | 523 statusAnalyzing = isAnalyzing; |
| 522 AnalysisStatus analysis = new AnalysisStatus(isAnalyzing); | 524 AnalysisStatus analysis = new AnalysisStatus(isAnalyzing); |
| 523 channel.sendNotification(new ServerStatusParams( | 525 channel.sendNotification( |
| 524 analysis: analysis).toNotification()); | 526 new ServerStatusParams(analysis: analysis).toNotification()); |
| 525 } | 527 } |
| 526 | 528 |
| 527 /** | 529 /** |
| 528 * Implementation for `analysis.setAnalysisRoots`. | 530 * Implementation for `analysis.setAnalysisRoots`. |
| 529 * | 531 * |
| 530 * TODO(scheglov) implement complete projects/contexts semantics. | 532 * TODO(scheglov) implement complete projects/contexts semantics. |
| 531 * | 533 * |
| 532 * The current implementation is intentionally simplified and expected | 534 * The current implementation is intentionally simplified and expected |
| 533 * that only folders are given each given folder corresponds to the exactly | 535 * that only folders are given each given folder corresponds to the exactly |
| 534 * one context. | 536 * one context. |
| 535 * | 537 * |
| 536 * So, we can start working in parallel on adding services and improving | 538 * So, we can start working in parallel on adding services and improving |
| 537 * projects/contexts support. | 539 * projects/contexts support. |
| 538 */ | 540 */ |
| 539 void setAnalysisRoots(String requestId, | 541 void setAnalysisRoots(String requestId, List<String> includedPaths, |
| 540 List<String> includedPaths, | 542 List<String> excludedPaths) { |
| 541 List<String> excludedPaths) { | |
| 542 try { | 543 try { |
| 543 contextDirectoryManager.setRoots(includedPaths, excludedPaths); | 544 contextDirectoryManager.setRoots(includedPaths, excludedPaths); |
| 544 } on UnimplementedError catch (e) { | 545 } on UnimplementedError catch (e) { |
| 545 throw new RequestFailure( | 546 throw new RequestFailure( |
| 546 new Response.unsupportedFeature( | 547 new Response.unsupportedFeature(requestId, e.message)); |
| 547 requestId, e.message)); | |
| 548 } | 548 } |
| 549 } | 549 } |
| 550 | 550 |
| 551 /** | 551 /** |
| 552 * Implementation for `analysis.updateContent`. | 552 * Implementation for `analysis.updateContent`. |
| 553 */ | 553 */ |
| 554 void updateContent(String id, Map<String, dynamic> changes) { | 554 void updateContent(String id, Map<String, dynamic> changes) { |
| 555 changes.forEach((file, change) { | 555 changes.forEach((file, change) { |
| 556 AnalysisContext analysisContext = getAnalysisContext(file); | 556 AnalysisContext analysisContext = getAnalysisContext(file); |
| 557 // TODO(paulberry): handle the case where a file is referred to by more | 557 // TODO(paulberry): handle the case where a file is referred to by more |
| 558 // than one context (e.g package A depends on package B using a local | 558 // than one context (e.g package A depends on package B using a local |
| 559 // path, user has both packages open for editing in separate contexts, | 559 // path, user has both packages open for editing in separate contexts, |
| 560 // and user modifies a file in package B). | 560 // and user modifies a file in package B). |
| 561 if (analysisContext != null) { | 561 if (analysisContext != null) { |
| 562 Source source = getSource(file); | 562 Source source = getSource(file); |
| 563 if (change is AddContentOverlay) { | 563 if (change is AddContentOverlay) { |
| 564 analysisContext.setContents(source, change.content); | 564 analysisContext.setContents(source, change.content); |
| 565 } else if (change is ChangeContentOverlay) { | 565 } else if (change is ChangeContentOverlay) { |
| 566 // TODO(paulberry): an error should be generated if source is not | 566 // TODO(paulberry): an error should be generated if source is not |
| 567 // currently in the content cache. | 567 // currently in the content cache. |
| 568 TimestampedData<String> oldContents = analysisContext.getContents( | 568 TimestampedData<String> oldContents = |
| 569 source); | 569 analysisContext.getContents(source); |
| 570 String newContents; | 570 String newContents; |
| 571 try { | 571 try { |
| 572 newContents = SourceEdit.applySequence(oldContents.data, | 572 newContents = |
| 573 change.edits); | 573 SourceEdit.applySequence(oldContents.data, change.edits); |
| 574 } on RangeError { | 574 } on RangeError { |
| 575 throw new RequestFailure(new Response(id, error: new RequestError( | 575 throw new RequestFailure( |
| 576 RequestErrorCode.INVALID_OVERLAY_CHANGE, | 576 new Response( |
| 577 'Invalid overlay change'))); | 577 id, |
| 578 error: new RequestError( |
| 579 RequestErrorCode.INVALID_OVERLAY_CHANGE, |
| 580 'Invalid overlay change'))); |
| 578 } | 581 } |
| 579 // TODO(paulberry): to aid in incremental processing it would be | 582 // TODO(paulberry): to aid in incremental processing it would be |
| 580 // better to use setChangedContents. | 583 // better to use setChangedContents. |
| 581 analysisContext.setContents(source, newContents); | 584 analysisContext.setContents(source, newContents); |
| 582 } else if (change is RemoveContentOverlay) { | 585 } else if (change is RemoveContentOverlay) { |
| 583 analysisContext.setContents(source, null); | 586 analysisContext.setContents(source, null); |
| 584 } else { | 587 } else { |
| 585 // Protocol parsing should have ensured that we never get here. | 588 // Protocol parsing should have ensured that we never get here. |
| 586 throw new AnalysisException('Illegal change type'); | 589 throw new AnalysisException('Illegal change type'); |
| 587 } | 590 } |
| 588 schedulePerformAnalysisOperation(analysisContext); | 591 schedulePerformAnalysisOperation(analysisContext); |
| 589 } | 592 } |
| 590 }); | 593 }); |
| 591 } | 594 } |
| 592 | 595 |
| 593 /** | 596 /** |
| 594 * Implementation for `analysis.setSubscriptions`. | 597 * Implementation for `analysis.setSubscriptions`. |
| 595 */ | 598 */ |
| 596 void setAnalysisSubscriptions(Map<AnalysisService, Set<String>> subscriptions)
{ | 599 void setAnalysisSubscriptions(Map<AnalysisService, |
| 600 Set<String>> subscriptions) { |
| 597 // send notifications for already analyzed sources | 601 // send notifications for already analyzed sources |
| 598 subscriptions.forEach((service, Set<String> newFiles) { | 602 subscriptions.forEach((service, Set<String> newFiles) { |
| 599 Set<String> oldFiles = analysisServices[service]; | 603 Set<String> oldFiles = analysisServices[service]; |
| 600 Set<String> todoFiles = oldFiles != null ? newFiles.difference(oldFiles) :
newFiles; | 604 Set<String> todoFiles = |
| 605 oldFiles != null ? newFiles.difference(oldFiles) : newFiles; |
| 601 for (String file in todoFiles) { | 606 for (String file in todoFiles) { |
| 602 Source source = getSource(file); | 607 Source source = getSource(file); |
| 603 // prepare context | 608 // prepare context |
| 604 AnalysisContext context = getAnalysisContext(file); | 609 AnalysisContext context = getAnalysisContext(file); |
| 605 if (context == null) { | 610 if (context == null) { |
| 606 continue; | 611 continue; |
| 607 } | 612 } |
| 608 // Dart unit notifications. | 613 // Dart unit notifications. |
| 609 if (AnalysisEngine.isDartFileName(file)) { | 614 if (AnalysisEngine.isDartFileName(file)) { |
| 610 CompilationUnit dartUnit = getResolvedCompilationUnitToResendNotificat
ion(file); | 615 CompilationUnit dartUnit = |
| 616 getResolvedCompilationUnitToResendNotification(file); |
| 611 if (dartUnit != null) { | 617 if (dartUnit != null) { |
| 612 switch (service) { | 618 switch (service) { |
| 613 case AnalysisService.HIGHLIGHTS: | 619 case AnalysisService.HIGHLIGHTS: |
| 614 sendAnalysisNotificationHighlights(this, file, dartUnit); | 620 sendAnalysisNotificationHighlights(this, file, dartUnit); |
| 615 break; | 621 break; |
| 616 case AnalysisService.NAVIGATION: | 622 case AnalysisService.NAVIGATION: |
| 617 // TODO(scheglov) consider support for one unit in 2+ libraries | 623 // TODO(scheglov) consider support for one unit in 2+ libraries |
| 618 sendAnalysisNotificationNavigation(this, file, dartUnit); | 624 sendAnalysisNotificationNavigation(this, file, dartUnit); |
| 619 break; | 625 break; |
| 620 case AnalysisService.OCCURRENCES: | 626 case AnalysisService.OCCURRENCES: |
| 621 sendAnalysisNotificationOccurrences(this, file, dartUnit); | 627 sendAnalysisNotificationOccurrences(this, file, dartUnit); |
| 622 break; | 628 break; |
| 623 case AnalysisService.OUTLINE: | 629 case AnalysisService.OUTLINE: |
| 624 sendAnalysisNotificationOutline(this, context, source, dartUnit)
; | 630 sendAnalysisNotificationOutline( |
| 631 this, |
| 632 context, |
| 633 source, |
| 634 dartUnit); |
| 625 break; | 635 break; |
| 626 case AnalysisService.OVERRIDES: | 636 case AnalysisService.OVERRIDES: |
| 627 sendAnalysisNotificationOverrides(this, file, dartUnit); | 637 sendAnalysisNotificationOverrides(this, file, dartUnit); |
| 628 break; | 638 break; |
| 629 } | 639 } |
| 630 } | 640 } |
| 631 } | 641 } |
| 632 } | 642 } |
| 633 }); | 643 }); |
| 634 // remember new subscriptions | 644 // remember new subscriptions |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 746 List<CompilationUnit> units = <CompilationUnit>[]; | 756 List<CompilationUnit> units = <CompilationUnit>[]; |
| 747 // prepare AnalysisContext | 757 // prepare AnalysisContext |
| 748 AnalysisContext context = getAnalysisContext(path); | 758 AnalysisContext context = getAnalysisContext(path); |
| 749 if (context == null) { | 759 if (context == null) { |
| 750 return units; | 760 return units; |
| 751 } | 761 } |
| 752 // add a unit for each unit/library combination | 762 // add a unit for each unit/library combination |
| 753 Source unitSource = getSource(path); | 763 Source unitSource = getSource(path); |
| 754 List<Source> librarySources = context.getLibrariesContaining(unitSource); | 764 List<Source> librarySources = context.getLibrariesContaining(unitSource); |
| 755 for (Source librarySource in librarySources) { | 765 for (Source librarySource in librarySources) { |
| 756 CompilationUnit unit = context.getResolvedCompilationUnit2(unitSource, lib
rarySource); | 766 CompilationUnit unit = |
| 767 context.getResolvedCompilationUnit2(unitSource, librarySource); |
| 757 if (unit != null) { | 768 if (unit != null) { |
| 758 units.add(unit); | 769 units.add(unit); |
| 759 } | 770 } |
| 760 } | 771 } |
| 761 // done | 772 // done |
| 762 return units; | 773 return units; |
| 763 } | 774 } |
| 764 | 775 |
| 765 /** | 776 /** |
| 766 * Returns [AstNode]s at the given [offset] of the given [file]. | 777 * Returns [AstNode]s at the given [offset] of the given [file]. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 839 contextAnalysisDoneCompleters[context] = completer; | 850 contextAnalysisDoneCompleters[context] = completer; |
| 840 } | 851 } |
| 841 return completer.future; | 852 return completer.future; |
| 842 } | 853 } |
| 843 | 854 |
| 844 /** | 855 /** |
| 845 * This method is called when analysis of the given [AnalysisContext] is | 856 * This method is called when analysis of the given [AnalysisContext] is |
| 846 * done. | 857 * done. |
| 847 */ | 858 */ |
| 848 void sendContextAnalysisDoneNotifications(AnalysisContext context, | 859 void sendContextAnalysisDoneNotifications(AnalysisContext context, |
| 849 AnalysisDoneReason reason) { | 860 AnalysisDoneReason reason) { |
| 850 Completer<AnalysisDoneReason> completer = | 861 Completer<AnalysisDoneReason> completer = |
| 851 contextAnalysisDoneCompleters.remove(context); | 862 contextAnalysisDoneCompleters.remove(context); |
| 852 if (completer != null) { | 863 if (completer != null) { |
| 853 completer.complete(reason); | 864 completer.complete(reason); |
| 854 } | 865 } |
| 855 } | 866 } |
| 856 | 867 |
| 857 void shutdown() { | 868 void shutdown() { |
| 858 running = false; | 869 running = false; |
| 859 if (index != null) { | 870 if (index != null) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 919 exceptionString = 'null exception'; | 930 exceptionString = 'null exception'; |
| 920 } | 931 } |
| 921 // prepare stackTrace.toString() | 932 // prepare stackTrace.toString() |
| 922 String stackTraceString; | 933 String stackTraceString; |
| 923 if (stackTrace != null) { | 934 if (stackTrace != null) { |
| 924 stackTraceString = stackTrace.toString(); | 935 stackTraceString = stackTrace.toString(); |
| 925 } else { | 936 } else { |
| 926 stackTraceString = 'null stackTrace'; | 937 stackTraceString = 'null stackTrace'; |
| 927 } | 938 } |
| 928 // send the notification | 939 // send the notification |
| 929 channel.sendNotification(new ServerErrorParams(true, exceptionString, | 940 channel.sendNotification( |
| 930 stackTraceString).toNotification()); | 941 new ServerErrorParams( |
| 942 true, |
| 943 exceptionString, |
| 944 stackTraceString).toNotification()); |
| 931 } | 945 } |
| 932 } | 946 } |
| 933 | 947 |
| 934 /** | 948 /** |
| 935 * An object that is listening for lifecycle events from an analysis server. | 949 * An object that is listening for lifecycle events from an analysis server. |
| 936 */ | 950 */ |
| 937 abstract class AnalysisServerListener { | 951 abstract class AnalysisServerListener { |
| 938 /** | 952 /** |
| 939 * Analysis is complete. | 953 * Analysis is complete. |
| 940 */ | 954 */ |
| 941 void analysisComplete(); | 955 void analysisComplete(); |
| 942 } | 956 } |
| 943 | 957 |
| 944 typedef void OptionUpdater(AnalysisOptionsImpl options); | 958 typedef void OptionUpdater(AnalysisOptionsImpl options); |
| OLD | NEW |