| 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 import 'dart:collection'; | 6 import 'dart:collection'; |
| 7 import 'dart:core'; | 7 import 'dart:core'; |
| 8 import 'dart:io' as io; | 8 import 'dart:io' as io; |
| 9 import 'dart:math' show max; | 9 import 'dart:math' show max; |
| 10 | 10 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 import 'package:analysis_server/src/operation/operation_queue.dart'; | 28 import 'package:analysis_server/src/operation/operation_queue.dart'; |
| 29 import 'package:analysis_server/src/plugin/notification_manager.dart'; | 29 import 'package:analysis_server/src/plugin/notification_manager.dart'; |
| 30 import 'package:analysis_server/src/plugin/plugin_manager.dart'; | 30 import 'package:analysis_server/src/plugin/plugin_manager.dart'; |
| 31 import 'package:analysis_server/src/plugin/plugin_watcher.dart'; | 31 import 'package:analysis_server/src/plugin/plugin_watcher.dart'; |
| 32 import 'package:analysis_server/src/plugin/server_plugin.dart'; | 32 import 'package:analysis_server/src/plugin/server_plugin.dart'; |
| 33 import 'package:analysis_server/src/protocol_server.dart' as server; | 33 import 'package:analysis_server/src/protocol_server.dart' as server; |
| 34 import 'package:analysis_server/src/server/diagnostic_server.dart'; | 34 import 'package:analysis_server/src/server/diagnostic_server.dart'; |
| 35 import 'package:analysis_server/src/services/correction/namespace.dart'; | 35 import 'package:analysis_server/src/services/correction/namespace.dart'; |
| 36 import 'package:analysis_server/src/services/index/index.dart'; | 36 import 'package:analysis_server/src/services/index/index.dart'; |
| 37 import 'package:analysis_server/src/services/search/search_engine.dart'; | 37 import 'package:analysis_server/src/services/search/search_engine.dart'; |
| 38 import 'package:analysis_server/src/services/search/search_engine_internal.dart'
; | |
| 39 import 'package:analysis_server/src/services/search/search_engine_internal2.dart
'; | 38 import 'package:analysis_server/src/services/search/search_engine_internal2.dart
'; |
| 40 import 'package:analysis_server/src/single_context_manager.dart'; | 39 import 'package:analysis_server/src/single_context_manager.dart'; |
| 41 import 'package:analysis_server/src/utilities/null_string_sink.dart'; | 40 import 'package:analysis_server/src/utilities/null_string_sink.dart'; |
| 42 import 'package:analyzer/context/context_root.dart'; | 41 import 'package:analyzer/context/context_root.dart'; |
| 43 import 'package:analyzer/dart/ast/ast.dart'; | 42 import 'package:analyzer/dart/ast/ast.dart'; |
| 44 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; | |
| 45 import 'package:analyzer/dart/element/element.dart'; | 43 import 'package:analyzer/dart/element/element.dart'; |
| 46 import 'package:analyzer/exception/exception.dart'; | 44 import 'package:analyzer/exception/exception.dart'; |
| 47 import 'package:analyzer/file_system/file_system.dart'; | 45 import 'package:analyzer/file_system/file_system.dart'; |
| 48 import 'package:analyzer/file_system/physical_file_system.dart'; | 46 import 'package:analyzer/file_system/physical_file_system.dart'; |
| 49 import 'package:analyzer/instrumentation/instrumentation.dart'; | 47 import 'package:analyzer/instrumentation/instrumentation.dart'; |
| 50 import 'package:analyzer/plugin/resolver_provider.dart'; | 48 import 'package:analyzer/plugin/resolver_provider.dart'; |
| 51 import 'package:analyzer/source/pub_package_map_provider.dart'; | 49 import 'package:analyzer/source/pub_package_map_provider.dart'; |
| 52 import 'package:analyzer/src/context/builder.dart'; | 50 import 'package:analyzer/src/context/builder.dart'; |
| 53 import 'package:analyzer/src/dart/analysis/ast_provider_context.dart'; | |
| 54 import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart'; | 51 import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart'; |
| 55 import 'package:analyzer/src/dart/analysis/driver.dart' as nd; | 52 import 'package:analyzer/src/dart/analysis/driver.dart' as nd; |
| 56 import 'package:analyzer/src/dart/analysis/file_state.dart' as nd; | 53 import 'package:analyzer/src/dart/analysis/file_state.dart' as nd; |
| 57 import 'package:analyzer/src/dart/analysis/status.dart' as nd; | 54 import 'package:analyzer/src/dart/analysis/status.dart' as nd; |
| 58 import 'package:analyzer/src/dart/ast/utilities.dart'; | 55 import 'package:analyzer/src/dart/ast/utilities.dart'; |
| 59 import 'package:analyzer/src/dart/element/ast_provider.dart'; | 56 import 'package:analyzer/src/dart/element/ast_provider.dart'; |
| 60 import 'package:analyzer/src/generated/engine.dart'; | 57 import 'package:analyzer/src/generated/engine.dart'; |
| 61 import 'package:analyzer/src/generated/sdk.dart'; | 58 import 'package:analyzer/src/generated/sdk.dart'; |
| 62 import 'package:analyzer/src/generated/source.dart'; | 59 import 'package:analyzer/src/generated/source.dart'; |
| 63 import 'package:analyzer/src/generated/source_io.dart'; | 60 import 'package:analyzer/src/generated/source_io.dart'; |
| 64 import 'package:analyzer/src/generated/utilities_general.dart'; | 61 import 'package:analyzer/src/generated/utilities_general.dart'; |
| 65 import 'package:analyzer/src/task/dart.dart'; | |
| 66 import 'package:analyzer/src/util/glob.dart'; | 62 import 'package:analyzer/src/util/glob.dart'; |
| 67 import 'package:analyzer/task/dart.dart'; | |
| 68 import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element; | 63 import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element; |
| 69 import 'package:front_end/src/base/performace_logger.dart'; | 64 import 'package:front_end/src/base/performace_logger.dart'; |
| 70 import 'package:front_end/src/incremental/byte_store.dart'; | 65 import 'package:front_end/src/incremental/byte_store.dart'; |
| 71 import 'package:front_end/src/incremental/file_byte_store.dart'; | 66 import 'package:front_end/src/incremental/file_byte_store.dart'; |
| 72 import 'package:plugin/plugin.dart'; | 67 import 'package:plugin/plugin.dart'; |
| 73 import 'package:watcher/watcher.dart'; | 68 import 'package:watcher/watcher.dart'; |
| 74 | 69 |
| 75 typedef void OptionUpdater(AnalysisOptionsImpl options); | 70 typedef void OptionUpdater(AnalysisOptionsImpl options); |
| 76 | 71 |
| 77 /** | 72 /** |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 * The controller that is notified when analysis is started. | 269 * The controller that is notified when analysis is started. |
| 275 */ | 270 */ |
| 276 StreamController<bool> _onAnalysisStartedController; | 271 StreamController<bool> _onAnalysisStartedController; |
| 277 | 272 |
| 278 /** | 273 /** |
| 279 * The controller that is notified when a single file has been analyzed. | 274 * The controller that is notified when a single file has been analyzed. |
| 280 */ | 275 */ |
| 281 StreamController<ChangeNotice> _onFileAnalyzedController; | 276 StreamController<ChangeNotice> _onFileAnalyzedController; |
| 282 | 277 |
| 283 /** | 278 /** |
| 284 * The controller used to notify others when priority sources change. | |
| 285 */ | |
| 286 StreamController<PriorityChangeEvent> _onPriorityChangeController; | |
| 287 | |
| 288 /** | |
| 289 * True if any exceptions thrown by analysis should be propagated up the call | 279 * True if any exceptions thrown by analysis should be propagated up the call |
| 290 * stack. | 280 * stack. |
| 291 */ | 281 */ |
| 292 bool rethrowExceptions; | 282 bool rethrowExceptions; |
| 293 | 283 |
| 294 /** | 284 /** |
| 295 * The next time (milliseconds since epoch) after which the analysis server | 285 * The next time (milliseconds since epoch) after which the analysis server |
| 296 * should pause so that pending requests can be fetched by the system. | 286 * should pause so that pending requests can be fetched by the system. |
| 297 */ | 287 */ |
| 298 // Add 1 sec to prevent delay from impacting short running tests | 288 // Add 1 sec to prevent delay from impacting short running tests |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 462 contextManager = new SingleContextManager(resourceProvider, sdkManager, | 452 contextManager = new SingleContextManager(resourceProvider, sdkManager, |
| 463 packageResolverProvider, analyzedFilesGlobs, defaultContextOptions); | 453 packageResolverProvider, analyzedFilesGlobs, defaultContextOptions); |
| 464 } else { | 454 } else { |
| 465 contextManager = new ContextManagerImpl( | 455 contextManager = new ContextManagerImpl( |
| 466 resourceProvider, | 456 resourceProvider, |
| 467 sdkManager, | 457 sdkManager, |
| 468 packageResolverProvider, | 458 packageResolverProvider, |
| 469 packageMapProvider, | 459 packageMapProvider, |
| 470 analyzedFilesGlobs, | 460 analyzedFilesGlobs, |
| 471 instrumentationService, | 461 instrumentationService, |
| 472 defaultContextOptions, | 462 defaultContextOptions); |
| 473 options.enableNewAnalysisDriver); | |
| 474 } | 463 } |
| 475 this.fileResolverProvider = fileResolverProvider; | 464 this.fileResolverProvider = fileResolverProvider; |
| 476 this.packageResolverProvider = packageResolverProvider; | 465 this.packageResolverProvider = packageResolverProvider; |
| 477 ServerContextManagerCallbacks contextManagerCallbacks = | 466 ServerContextManagerCallbacks contextManagerCallbacks = |
| 478 new ServerContextManagerCallbacks(this, resourceProvider); | 467 new ServerContextManagerCallbacks(this, resourceProvider); |
| 479 contextManager.callbacks = contextManagerCallbacks; | 468 contextManager.callbacks = contextManagerCallbacks; |
| 480 AnalysisEngine.instance.logger = new AnalysisLogger(this); | 469 AnalysisEngine.instance.logger = new AnalysisLogger(this); |
| 481 _onAnalysisStartedController = new StreamController.broadcast(); | 470 _onAnalysisStartedController = new StreamController.broadcast(); |
| 482 _onFileAnalyzedController = new StreamController.broadcast(); | 471 _onFileAnalyzedController = new StreamController.broadcast(); |
| 483 // temporary plugin support: | 472 // temporary plugin support: |
| 484 _onFileAddedController = new StreamController.broadcast(); | 473 _onFileAddedController = new StreamController.broadcast(); |
| 485 // temporary plugin support: | 474 // temporary plugin support: |
| 486 _onFileChangedController = new StreamController.broadcast(); | 475 _onFileChangedController = new StreamController.broadcast(); |
| 487 _onPriorityChangeController = | |
| 488 new StreamController<PriorityChangeEvent>.broadcast(); | |
| 489 running = true; | 476 running = true; |
| 490 onAnalysisStarted.first.then((_) { | 477 onAnalysisStarted.first.then((_) { |
| 491 onAnalysisComplete.then((_) { | 478 onAnalysisComplete.then((_) { |
| 492 performanceAfterStartup = new ServerPerformance(); | 479 performanceAfterStartup = new ServerPerformance(); |
| 493 _performance = performanceAfterStartup; | 480 _performance = performanceAfterStartup; |
| 494 }); | 481 }); |
| 495 }); | 482 }); |
| 496 _setupIndexInvalidation(); | 483 _setupIndexInvalidation(); |
| 497 if (options.enableNewAnalysisDriver) { | 484 searchEngine = new SearchEngineImpl2(driverMap.values); |
| 498 searchEngine = new SearchEngineImpl2(driverMap.values); | |
| 499 } else if (index != null) { | |
| 500 searchEngine = new SearchEngineImpl(index, getAstProvider); | |
| 501 } | |
| 502 Notification notification = new ServerConnectedParams(VERSION, io.pid, | 485 Notification notification = new ServerConnectedParams(VERSION, io.pid, |
| 503 sessionId: instrumentationService.sessionId) | 486 sessionId: instrumentationService.sessionId) |
| 504 .toNotification(); | 487 .toNotification(); |
| 505 channel.sendNotification(notification); | 488 channel.sendNotification(notification); |
| 506 channel.listen(handleRequest, onDone: done, onError: error); | 489 channel.listen(handleRequest, onDone: done, onError: error); |
| 507 handlers = serverPlugin.createDomains(this); | 490 handlers = serverPlugin.createDomains(this); |
| 508 } | 491 } |
| 509 | 492 |
| 510 /** | 493 /** |
| 511 * Return the [AnalysisContext]s that are being used to analyze the analysis | 494 * Return the [AnalysisContext]s that are being used to analyze the analysis |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 Stream get onFileAnalyzed => _onFileAnalyzedController.stream; | 568 Stream get onFileAnalyzed => _onFileAnalyzedController.stream; |
| 586 | 569 |
| 587 /** | 570 /** |
| 588 * The stream that is notified when a single file has been changed. This | 571 * The stream that is notified when a single file has been changed. This |
| 589 * exists as a temporary stopgap for plugins, until the official plugin API is | 572 * exists as a temporary stopgap for plugins, until the official plugin API is |
| 590 * complete. | 573 * complete. |
| 591 */ | 574 */ |
| 592 Stream get onFileChanged => _onFileChangedController.stream; | 575 Stream get onFileChanged => _onFileChangedController.stream; |
| 593 | 576 |
| 594 /** | 577 /** |
| 595 * The stream that is notified when priority sources change. | |
| 596 */ | |
| 597 Stream<PriorityChangeEvent> get onPriorityChange => | |
| 598 _onPriorityChangeController.stream; | |
| 599 | |
| 600 /** | |
| 601 * The [Future] that completes when the next operation is performed. | 578 * The [Future] that completes when the next operation is performed. |
| 602 */ | 579 */ |
| 603 Future get test_onOperationPerformed { | 580 Future get test_onOperationPerformed { |
| 604 if (_test_onOperationPerformedCompleter == null) { | 581 if (_test_onOperationPerformedCompleter == null) { |
| 605 _test_onOperationPerformedCompleter = new Completer(); | 582 _test_onOperationPerformedCompleter = new Completer(); |
| 606 } | 583 } |
| 607 return _test_onOperationPerformedCompleter.future; | 584 return _test_onOperationPerformedCompleter.future; |
| 608 } | 585 } |
| 609 | 586 |
| 610 /** | 587 /** |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 DartSdk findSdk() { | 635 DartSdk findSdk() { |
| 659 DartSdk sdk = sdkManager.anySdk; | 636 DartSdk sdk = sdkManager.anySdk; |
| 660 if (sdk != null) { | 637 if (sdk != null) { |
| 661 return sdk; | 638 return sdk; |
| 662 } | 639 } |
| 663 // TODO(brianwilkerson) Should we create an SDK using the default options? | 640 // TODO(brianwilkerson) Should we create an SDK using the default options? |
| 664 return null; | 641 return null; |
| 665 } | 642 } |
| 666 | 643 |
| 667 /** | 644 /** |
| 668 * Return the preferred [AnalysisContext] for analyzing the given [path]. | |
| 669 * This will be the context that explicitly contains the path, if any such | |
| 670 * context exists, otherwise it will be the first analysis context that | |
| 671 * implicitly analyzes it. Return `null` if no context is analyzing the | |
| 672 * path. | |
| 673 */ | |
| 674 AnalysisContext getAnalysisContext(String path) { | |
| 675 return getContextSourcePair(path).context; | |
| 676 } | |
| 677 | |
| 678 /** | |
| 679 * Return any [AnalysisContext] that is analyzing the given [source], either | |
| 680 * explicitly or implicitly. Return `null` if there is no such context. | |
| 681 */ | |
| 682 AnalysisContext getAnalysisContextForSource(Source source) { | |
| 683 for (AnalysisContext context in analysisContexts) { | |
| 684 SourceKind kind = context.getKindOf(source); | |
| 685 if (kind != SourceKind.UNKNOWN) { | |
| 686 return context; | |
| 687 } | |
| 688 } | |
| 689 return null; | |
| 690 } | |
| 691 | |
| 692 /** | |
| 693 * Return an analysis driver to which the file with the given [path] is | 645 * Return an analysis driver to which the file with the given [path] is |
| 694 * added if one exists, otherwise a driver in which the file was analyzed if | 646 * added if one exists, otherwise a driver in which the file was analyzed if |
| 695 * one exists, otherwise the first driver, otherwise `null`. | 647 * one exists, otherwise the first driver, otherwise `null`. |
| 696 */ | 648 */ |
| 697 nd.AnalysisDriver getAnalysisDriver(String path) { | 649 nd.AnalysisDriver getAnalysisDriver(String path) { |
| 698 List<nd.AnalysisDriver> drivers = driverMap.values.toList(); | 650 List<nd.AnalysisDriver> drivers = driverMap.values.toList(); |
| 699 if (drivers.isNotEmpty) { | 651 if (drivers.isNotEmpty) { |
| 700 // Sort the drivers so that more deeply nested contexts will be checked | 652 // Sort the drivers so that more deeply nested contexts will be checked |
| 701 // before enclosing contexts. | 653 // before enclosing contexts. |
| 702 drivers.sort((first, second) => | 654 drivers.sort((first, second) => |
| (...skipping 27 matching lines...) Expand all Loading... |
| 730 // Ignore the exception. | 682 // Ignore the exception. |
| 731 // We don't want to log the same exception again and again. | 683 // We don't want to log the same exception again and again. |
| 732 return null; | 684 return null; |
| 733 } | 685 } |
| 734 } | 686 } |
| 735 | 687 |
| 736 /** | 688 /** |
| 737 * Return the [AstProvider] for the given [path]. | 689 * Return the [AstProvider] for the given [path]. |
| 738 */ | 690 */ |
| 739 AstProvider getAstProvider(String path) { | 691 AstProvider getAstProvider(String path) { |
| 740 if (options.enableNewAnalysisDriver) { | 692 nd.AnalysisDriver analysisDriver = getAnalysisDriver(path); |
| 741 var analysisDriver = getAnalysisDriver(path); | 693 return new AstProviderForDriver(analysisDriver); |
| 742 return new AstProviderForDriver(analysisDriver); | |
| 743 } else { | |
| 744 var analysisContext = getAnalysisContext(path); | |
| 745 return new AstProviderForContext(analysisContext); | |
| 746 } | |
| 747 } | |
| 748 | |
| 749 CompilationUnitElement getCompilationUnitElement(String file) { | |
| 750 ContextSourcePair pair = getContextSourcePair(file); | |
| 751 if (pair == null) { | |
| 752 return null; | |
| 753 } | |
| 754 // prepare AnalysisContext and Source | |
| 755 AnalysisContext context = pair.context; | |
| 756 Source unitSource = pair.source; | |
| 757 if (context == null || unitSource == null) { | |
| 758 return null; | |
| 759 } | |
| 760 // get element in the first library | |
| 761 List<Source> librarySources = context.getLibrariesContaining(unitSource); | |
| 762 if (!librarySources.isNotEmpty) { | |
| 763 return null; | |
| 764 } | |
| 765 Source librarySource = librarySources.first; | |
| 766 return context.getCompilationUnitElement(unitSource, librarySource); | |
| 767 } | 694 } |
| 768 | 695 |
| 769 /** | 696 /** |
| 770 * Return the [AnalysisContext] for the "innermost" context whose associated | 697 * Return the [AnalysisContext] for the "innermost" context whose associated |
| 771 * folder is or contains the given path. ("innermost" refers to the nesting | 698 * folder is or contains the given path. ("innermost" refers to the nesting |
| 772 * of contexts, so if there is a context for path /foo and a context for | 699 * of contexts, so if there is a context for path /foo and a context for |
| 773 * path /foo/bar, then the innermost context containing /foo/bar/baz.dart is | 700 * path /foo/bar, then the innermost context containing /foo/bar/baz.dart is |
| 774 * the context for /foo/bar.) | 701 * the context for /foo/bar.) |
| 775 * | 702 * |
| 776 * If no context contains the given path, `null` is returned. | 703 * If no context contains the given path, `null` is returned. |
| 777 */ | 704 */ |
| 778 AnalysisContext getContainingContext(String path) { | 705 AnalysisContext getContainingContext(String path) { |
| 779 return contextManager.getContextFor(path); | 706 return contextManager.getContextFor(path); |
| 780 } | 707 } |
| 781 | 708 |
| 782 /** | 709 /** |
| 783 * Return the [nd.AnalysisDriver] for the "innermost" context whose associated | 710 * Return the [nd.AnalysisDriver] for the "innermost" context whose associated |
| 784 * folder is or contains the given path. ("innermost" refers to the nesting | 711 * folder is or contains the given path. ("innermost" refers to the nesting |
| 785 * of contexts, so if there is a context for path /foo and a context for | 712 * of contexts, so if there is a context for path /foo and a context for |
| 786 * path /foo/bar, then the innermost context containing /foo/bar/baz.dart is | 713 * path /foo/bar, then the innermost context containing /foo/bar/baz.dart is |
| 787 * the context for /foo/bar.) | 714 * the context for /foo/bar.) |
| 788 * | 715 * |
| 789 * If no context contains the given path, `null` is returned. | 716 * If no context contains the given path, `null` is returned. |
| 790 */ | 717 */ |
| 791 nd.AnalysisDriver getContainingDriver(String path) { | 718 nd.AnalysisDriver getContainingDriver(String path) { |
| 792 return contextManager.getDriverFor(path); | 719 return contextManager.getDriverFor(path); |
| 793 } | 720 } |
| 794 | 721 |
| 795 /** | 722 /** |
| 796 * Return the primary [ContextSourcePair] representing the given [path]. | |
| 797 * | |
| 798 * The [AnalysisContext] of this pair will be the context that explicitly | |
| 799 * contains the path, if any such context exists, otherwise it will be the | |
| 800 * first context that implicitly analyzes it. | |
| 801 * | |
| 802 * If the [path] is not analyzed by any context, a [ContextSourcePair] with | |
| 803 * a `null` context and a `file` [Source] is returned. | |
| 804 * | |
| 805 * If the [path] doesn't represent a file, a [ContextSourcePair] with a `null` | |
| 806 * context and `null` [Source] is returned. | |
| 807 * | |
| 808 * Does not return `null`. | |
| 809 */ | |
| 810 ContextSourcePair getContextSourcePair(String path) { | |
| 811 // try SDK | |
| 812 { | |
| 813 DartSdk sdk = findSdk(); | |
| 814 if (sdk != null) { | |
| 815 Uri uri = resourceProvider.pathContext.toUri(path); | |
| 816 Source sdkSource = sdk.fromFileUri(uri); | |
| 817 if (sdkSource != null) { | |
| 818 return new ContextSourcePair(sdk.context, sdkSource); | |
| 819 } | |
| 820 } | |
| 821 } | |
| 822 // try to find the deep-most containing context | |
| 823 Resource resource = resourceProvider.getResource(path); | |
| 824 if (resource is! File) { | |
| 825 return new ContextSourcePair(null, null); | |
| 826 } | |
| 827 File file = resource; | |
| 828 { | |
| 829 AnalysisContext containingContext = getContainingContext(path); | |
| 830 if (containingContext != null) { | |
| 831 Source source = | |
| 832 ContextManagerImpl.createSourceInContext(containingContext, file); | |
| 833 return new ContextSourcePair(containingContext, source); | |
| 834 } | |
| 835 } | |
| 836 // try to find a context that analysed the file | |
| 837 for (AnalysisContext context in analysisContexts) { | |
| 838 Source source = ContextManagerImpl.createSourceInContext(context, file); | |
| 839 SourceKind kind = context.getKindOf(source); | |
| 840 if (kind != SourceKind.UNKNOWN) { | |
| 841 return new ContextSourcePair(context, source); | |
| 842 } | |
| 843 } | |
| 844 // try to find a context for which the file is a priority source | |
| 845 for (InternalAnalysisContext context in analysisContexts) { | |
| 846 List<Source> sources = context.getSourcesWithFullName(path); | |
| 847 if (sources.isNotEmpty) { | |
| 848 Source source = sources.first; | |
| 849 return new ContextSourcePair(context, source); | |
| 850 } | |
| 851 } | |
| 852 // file-based source | |
| 853 Source fileSource = file.createSource(); | |
| 854 return new ContextSourcePair(null, fileSource); | |
| 855 } | |
| 856 | |
| 857 /** | |
| 858 * Return a [Future] that completes with the [Element] at the given | 723 * Return a [Future] that completes with the [Element] at the given |
| 859 * [offset] of the given [file], or with `null` if there is no node at the | 724 * [offset] of the given [file], or with `null` if there is no node at the |
| 860 * [offset] or the node does not have an element. | 725 * [offset] or the node does not have an element. |
| 861 */ | 726 */ |
| 862 Future<Element> getElementAtOffset(String file, int offset) async { | 727 Future<Element> getElementAtOffset(String file, int offset) async { |
| 863 AstNode node = await getNodeAtOffset(file, offset); | 728 AstNode node = await getNodeAtOffset(file, offset); |
| 864 return getElementOfNode(node); | 729 return getElementOfNode(node); |
| 865 } | 730 } |
| 866 | 731 |
| 867 /** | 732 /** |
| (...skipping 14 matching lines...) Expand all Loading... |
| 882 return null; | 747 return null; |
| 883 } | 748 } |
| 884 Element element = ElementLocator.locate(node); | 749 Element element = ElementLocator.locate(node); |
| 885 if (node is SimpleIdentifier && element is PrefixElement) { | 750 if (node is SimpleIdentifier && element is PrefixElement) { |
| 886 element = getImportElement(node); | 751 element = getImportElement(node); |
| 887 } | 752 } |
| 888 return element; | 753 return element; |
| 889 } | 754 } |
| 890 | 755 |
| 891 /** | 756 /** |
| 892 * Return an analysis error info containing the array of all of the errors and | |
| 893 * the line info associated with [file]. | |
| 894 * | |
| 895 * Returns `null` if [file] does not belong to any [AnalysisContext], or the | |
| 896 * file does not exist. | |
| 897 * | |
| 898 * The array of errors will be empty if there are no errors in [file]. The | |
| 899 * errors contained in the array can be incomplete. | |
| 900 * | |
| 901 * This method does not wait for all errors to be computed, and returns just | |
| 902 * the current state. | |
| 903 */ | |
| 904 AnalysisErrorInfo getErrors(String file) { | |
| 905 ContextSourcePair contextSource = getContextSourcePair(file); | |
| 906 AnalysisContext context = contextSource.context; | |
| 907 Source source = contextSource.source; | |
| 908 if (context == null) { | |
| 909 return null; | |
| 910 } | |
| 911 if (!context.exists(source)) { | |
| 912 return null; | |
| 913 } | |
| 914 return context.getErrors(source); | |
| 915 } | |
| 916 | |
| 917 /** | |
| 918 * Return a [Future] that completes with the resolved [AstNode] at the | 757 * Return a [Future] that completes with the resolved [AstNode] at the |
| 919 * given [offset] of the given [file], or with `null` if there is no node as | 758 * given [offset] of the given [file], or with `null` if there is no node as |
| 920 * the [offset]. | 759 * the [offset]. |
| 921 */ | 760 */ |
| 922 Future<AstNode> getNodeAtOffset(String file, int offset) async { | 761 Future<AstNode> getNodeAtOffset(String file, int offset) async { |
| 923 CompilationUnit unit; | 762 nd.AnalysisResult result = await getAnalysisResult(file); |
| 924 if (options.enableNewAnalysisDriver) { | 763 CompilationUnit unit = result?.unit; |
| 925 nd.AnalysisResult result = await getAnalysisResult(file); | |
| 926 unit = result?.unit; | |
| 927 } else { | |
| 928 unit = await getResolvedCompilationUnit(file); | |
| 929 } | |
| 930 if (unit != null) { | 764 if (unit != null) { |
| 931 return new NodeLocator(offset).searchWithin(unit); | 765 return new NodeLocator(offset).searchWithin(unit); |
| 932 } | 766 } |
| 933 return null; | 767 return null; |
| 934 } | 768 } |
| 935 | 769 |
| 936 /** | 770 /** |
| 937 * Return a [Future] that completes with the resolved [CompilationUnit] for | 771 * Return a [Future] that completes with the resolved [CompilationUnit] for |
| 938 * the Dart file with the given [path], or with `null` if the file is not a | 772 * the Dart file with the given [path], or with `null` if the file is not a |
| 939 * Dart file or cannot be resolved. | 773 * Dart file or cannot be resolved. |
| 940 */ | 774 */ |
| 941 Future<CompilationUnit> getResolvedCompilationUnit(String path) async { | 775 Future<CompilationUnit> getResolvedCompilationUnit(String path) async { |
| 942 if (options.enableNewAnalysisDriver) { | 776 nd.AnalysisResult result = await getAnalysisResult(path); |
| 943 nd.AnalysisResult result = await getAnalysisResult(path); | 777 return result?.unit; |
| 944 return result?.unit; | |
| 945 } | |
| 946 ContextSourcePair contextSource = getContextSourcePair(path); | |
| 947 AnalysisContext context = contextSource.context; | |
| 948 if (context == null) { | |
| 949 return null; | |
| 950 } | |
| 951 return runWithActiveContext(context, () { | |
| 952 Source unitSource = contextSource.source; | |
| 953 List<Source> librarySources = context.getLibrariesContaining(unitSource); | |
| 954 for (Source librarySource in librarySources) { | |
| 955 return context.resolveCompilationUnit2(unitSource, librarySource); | |
| 956 } | |
| 957 return null; | |
| 958 }); | |
| 959 } | 778 } |
| 960 | 779 |
| 961 // TODO(brianwilkerson) Add the following method after 'prioritySources' has | 780 // TODO(brianwilkerson) Add the following method after 'prioritySources' has |
| 962 // been added to InternalAnalysisContext. | 781 // been added to InternalAnalysisContext. |
| 963 // /** | 782 // /** |
| 964 // * Return a list containing the full names of all of the sources that are | 783 // * Return a list containing the full names of all of the sources that are |
| 965 // * priority sources. | 784 // * priority sources. |
| 966 // */ | 785 // */ |
| 967 // List<String> getPriorityFiles() { | 786 // List<String> getPriorityFiles() { |
| 968 // List<String> priorityFiles = new List<String>(); | 787 // List<String> priorityFiles = new List<String>(); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1037 /** | 856 /** |
| 1038 * Return `true` if the given path is a valid `FilePath`. | 857 * Return `true` if the given path is a valid `FilePath`. |
| 1039 * | 858 * |
| 1040 * This means that it is absolute and normalized. | 859 * This means that it is absolute and normalized. |
| 1041 */ | 860 */ |
| 1042 bool isValidFilePath(String path) { | 861 bool isValidFilePath(String path) { |
| 1043 return resourceProvider.absolutePathContext.isValid(path); | 862 return resourceProvider.absolutePathContext.isValid(path); |
| 1044 } | 863 } |
| 1045 | 864 |
| 1046 /** | 865 /** |
| 1047 * Returns a [Future] completing when [file] has been completely analyzed, in | |
| 1048 * particular, all its errors have been computed. The future is completed | |
| 1049 * with an [AnalysisDoneReason] indicating what caused the file's analysis to | |
| 1050 * be considered complete. | |
| 1051 * | |
| 1052 * If the given file doesn't belong to any context, null is returned. | |
| 1053 * | |
| 1054 * TODO(scheglov) this method should be improved. | |
| 1055 * | |
| 1056 * 1. The analysis context should be told to analyze this particular file ASAP
. | |
| 1057 * | |
| 1058 * 2. We should complete the future as soon as the file is analyzed (not wait | |
| 1059 * until the context is completely finished) | |
| 1060 */ | |
| 1061 Future<AnalysisDoneReason> onFileAnalysisComplete(String file) { | |
| 1062 // prepare AnalysisContext | |
| 1063 AnalysisContext context = getAnalysisContext(file); | |
| 1064 if (context == null) { | |
| 1065 return null; | |
| 1066 } | |
| 1067 // done if everything is already analyzed | |
| 1068 if (isAnalysisComplete()) { | |
| 1069 return new Future.value(AnalysisDoneReason.COMPLETE); | |
| 1070 } | |
| 1071 // schedule context analysis | |
| 1072 schedulePerformAnalysisOperation(context); | |
| 1073 // associate with the context completer | |
| 1074 Completer<AnalysisDoneReason> completer = | |
| 1075 contextAnalysisDoneCompleters[context]; | |
| 1076 if (completer == null) { | |
| 1077 completer = new Completer<AnalysisDoneReason>(); | |
| 1078 contextAnalysisDoneCompleters[context] = completer; | |
| 1079 } | |
| 1080 return completer.future; | |
| 1081 } | |
| 1082 | |
| 1083 /** | |
| 1084 * Perform the next available [ServerOperation]. | 866 * Perform the next available [ServerOperation]. |
| 1085 */ | 867 */ |
| 1086 void performOperation() { | 868 void performOperation() { |
| 1087 assert(performOperationPending); | 869 assert(performOperationPending); |
| 1088 PerformanceTag.unknown.makeCurrent(); | 870 PerformanceTag.unknown.makeCurrent(); |
| 1089 performOperationPending = false; | 871 performOperationPending = false; |
| 1090 if (!running) { | 872 if (!running) { |
| 1091 // An error has occurred, or the connection to the client has been | 873 // An error has occurred, or the connection to the client has been |
| 1092 // closed, since this method was scheduled on the event queue. So | 874 // closed, since this method was scheduled on the event queue. So |
| 1093 // don't do anything. Instead clear the operation queue. | 875 // don't do anything. Instead clear the operation queue. |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1334 } | 1116 } |
| 1335 | 1117 |
| 1336 /** | 1118 /** |
| 1337 * Implementation for `analysis.setSubscriptions`. | 1119 * Implementation for `analysis.setSubscriptions`. |
| 1338 */ | 1120 */ |
| 1339 void setAnalysisSubscriptions( | 1121 void setAnalysisSubscriptions( |
| 1340 Map<AnalysisService, Set<String>> subscriptions) { | 1122 Map<AnalysisService, Set<String>> subscriptions) { |
| 1341 if (notificationManager != null) { | 1123 if (notificationManager != null) { |
| 1342 notificationManager.setSubscriptions(subscriptions); | 1124 notificationManager.setSubscriptions(subscriptions); |
| 1343 } | 1125 } |
| 1344 if (options.enableNewAnalysisDriver) { | 1126 this.analysisServices = subscriptions; |
| 1345 this.analysisServices = subscriptions; | 1127 Set<String> allNewFiles = |
| 1346 Set<String> allNewFiles = | 1128 subscriptions.values.expand((files) => files).toSet(); |
| 1347 subscriptions.values.expand((files) => files).toSet(); | 1129 for (String file in allNewFiles) { |
| 1348 for (String file in allNewFiles) { | 1130 // The result will be produced by the "results" stream with |
| 1349 // The result will be produced by the "results" stream with | 1131 // the fully resolved unit, and processed with sending analysis |
| 1350 // the fully resolved unit, and processed with sending analysis | 1132 // notifications as it happens after content changes. |
| 1351 // notifications as it happens after content changes. | 1133 if (AnalysisEngine.isDartFileName(file)) { |
| 1352 if (AnalysisEngine.isDartFileName(file)) { | 1134 getAnalysisResult(file); |
| 1353 getAnalysisResult(file); | |
| 1354 } | |
| 1355 } | 1135 } |
| 1356 return; | |
| 1357 } | |
| 1358 // send notifications for already analyzed sources | |
| 1359 subscriptions.forEach((service, Set<String> newFiles) { | |
| 1360 Set<String> oldFiles = analysisServices[service]; | |
| 1361 Set<String> todoFiles = | |
| 1362 oldFiles != null ? newFiles.difference(oldFiles) : newFiles; | |
| 1363 for (String file in todoFiles) { | |
| 1364 if (contextManager.isIgnored(file)) { | |
| 1365 continue; | |
| 1366 } | |
| 1367 // prepare context | |
| 1368 ContextSourcePair contextSource = getContextSourcePair(file); | |
| 1369 AnalysisContext context = contextSource.context; | |
| 1370 if (context == null) { | |
| 1371 continue; | |
| 1372 } | |
| 1373 Source source = contextSource.source; | |
| 1374 // Ensure that if the AST is flushed / not ready, it will be | |
| 1375 // computed eventually. | |
| 1376 if (AnalysisEngine.isDartFileName(file)) { | |
| 1377 (context as InternalAnalysisContext).ensureResolvedDartUnits(source); | |
| 1378 } | |
| 1379 // Send notifications that don't directly take an AST. | |
| 1380 switch (service) { | |
| 1381 case AnalysisService.NAVIGATION: | |
| 1382 sendAnalysisNotificationNavigation(this, context, source); | |
| 1383 continue; | |
| 1384 case AnalysisService.OCCURRENCES: | |
| 1385 sendAnalysisNotificationOccurrences(this, context, source); | |
| 1386 continue; | |
| 1387 } | |
| 1388 // Dart unit notifications. | |
| 1389 if (AnalysisEngine.isDartFileName(file)) { | |
| 1390 // TODO(scheglov) This way to get resolved information is very Dart | |
| 1391 // specific. OTOH as it is planned now Angular results are not | |
| 1392 // flushable. | |
| 1393 CompilationUnit dartUnit = | |
| 1394 _getResolvedCompilationUnitToResendNotification(context, source); | |
| 1395 if (dartUnit != null) { | |
| 1396 switch (service) { | |
| 1397 case AnalysisService.HIGHLIGHTS: | |
| 1398 sendAnalysisNotificationHighlights(this, file, dartUnit); | |
| 1399 break; | |
| 1400 case AnalysisService.OUTLINE: | |
| 1401 AnalysisContext context = resolutionMap | |
| 1402 .elementDeclaredByCompilationUnit(dartUnit) | |
| 1403 .context; | |
| 1404 LineInfo lineInfo = context.getLineInfo(source); | |
| 1405 SourceKind kind = context.getKindOf(source); | |
| 1406 sendAnalysisNotificationOutline( | |
| 1407 this, file, lineInfo, kind, dartUnit); | |
| 1408 break; | |
| 1409 case AnalysisService.OVERRIDES: | |
| 1410 sendAnalysisNotificationOverrides(this, file, dartUnit); | |
| 1411 break; | |
| 1412 } | |
| 1413 } | |
| 1414 } | |
| 1415 } | |
| 1416 }); | |
| 1417 // remember new subscriptions | |
| 1418 this.analysisServices = subscriptions; | |
| 1419 // special case for implemented elements | |
| 1420 if (analysisServices.containsKey(AnalysisService.IMPLEMENTED) && | |
| 1421 isAnalysisComplete()) { | |
| 1422 _scheduleAnalysisImplementedNotification(); | |
| 1423 } | 1136 } |
| 1424 } | 1137 } |
| 1425 | 1138 |
| 1426 /** | 1139 /** |
| 1427 * Implementation for `analysis.setGeneralSubscriptions`. | 1140 * Implementation for `analysis.setGeneralSubscriptions`. |
| 1428 */ | 1141 */ |
| 1429 void setGeneralAnalysisSubscriptions( | 1142 void setGeneralAnalysisSubscriptions( |
| 1430 List<GeneralAnalysisService> subscriptions) { | 1143 List<GeneralAnalysisService> subscriptions) { |
| 1431 Set<GeneralAnalysisService> newServices = subscriptions.toSet(); | 1144 Set<GeneralAnalysisService> newServices = subscriptions.toSet(); |
| 1432 if (newServices.contains(GeneralAnalysisService.ANALYZED_FILES) && | 1145 if (newServices.contains(GeneralAnalysisService.ANALYZED_FILES) && |
| 1433 !generalAnalysisServices | 1146 !generalAnalysisServices |
| 1434 .contains(GeneralAnalysisService.ANALYZED_FILES) && | 1147 .contains(GeneralAnalysisService.ANALYZED_FILES) && |
| 1435 isAnalysisComplete()) { | 1148 isAnalysisComplete()) { |
| 1436 sendAnalysisNotificationAnalyzedFiles(this); | 1149 sendAnalysisNotificationAnalyzedFiles(this); |
| 1437 } else if (!newServices.contains(GeneralAnalysisService.ANALYZED_FILES) && | 1150 } else if (!newServices.contains(GeneralAnalysisService.ANALYZED_FILES) && |
| 1438 generalAnalysisServices | 1151 generalAnalysisServices |
| 1439 .contains(GeneralAnalysisService.ANALYZED_FILES)) { | 1152 .contains(GeneralAnalysisService.ANALYZED_FILES)) { |
| 1440 prevAnalyzedFiles = null; | 1153 prevAnalyzedFiles = null; |
| 1441 } | 1154 } |
| 1442 generalAnalysisServices = newServices; | 1155 generalAnalysisServices = newServices; |
| 1443 } | 1156 } |
| 1444 | 1157 |
| 1445 /** | 1158 /** |
| 1446 * Set the priority files to the given [files]. | 1159 * Set the priority files to the given [files]. |
| 1447 */ | 1160 */ |
| 1448 void setPriorityFiles(String requestId, List<String> files) { | 1161 void setPriorityFiles(String requestId, List<String> files) { |
| 1449 if (options.enableNewAnalysisDriver) { | 1162 priorityFiles.clear(); |
| 1450 priorityFiles.clear(); | 1163 priorityFiles.addAll(files); |
| 1451 priorityFiles.addAll(files); | 1164 // Set priority files in drivers. |
| 1452 // Set priority files in drivers. | 1165 driverMap.values.forEach((driver) { |
| 1453 driverMap.values.forEach((driver) { | 1166 driver.priorityFiles = files; |
| 1454 driver.priorityFiles = files; | |
| 1455 }); | |
| 1456 return; | |
| 1457 } | |
| 1458 // Note: when a file is a priority file, that information needs to be | |
| 1459 // propagated to all contexts that analyze the file, so that all contexts | |
| 1460 // will be able to do incremental resolution of the file. See | |
| 1461 // dartbug.com/22209. | |
| 1462 Map<AnalysisContext, List<Source>> sourceMap = | |
| 1463 new HashMap<AnalysisContext, List<Source>>(); | |
| 1464 List<String> unanalyzed = new List<String>(); | |
| 1465 Source firstSource = null; | |
| 1466 files.forEach((String file) { | |
| 1467 if (contextManager.isIgnored(file)) { | |
| 1468 unanalyzed.add(file); | |
| 1469 return; | |
| 1470 } | |
| 1471 // Prepare the context/source pair. | |
| 1472 ContextSourcePair contextSource = getContextSourcePair(file); | |
| 1473 AnalysisContext preferredContext = contextSource.context; | |
| 1474 Source source = contextSource.source; | |
| 1475 // Try to make the file analyzable. | |
| 1476 // If it is not in any context yet, add it to the first one which | |
| 1477 // could use it, e.g. imports its package, even if not the library. | |
| 1478 if (preferredContext == null) { | |
| 1479 Resource resource = resourceProvider.getResource(file); | |
| 1480 if (resource is File && resource.exists) { | |
| 1481 for (AnalysisContext context in analysisContexts) { | |
| 1482 Uri uri = context.sourceFactory.restoreUri(source); | |
| 1483 if (uri.scheme != 'file') { | |
| 1484 preferredContext = context; | |
| 1485 source = | |
| 1486 ContextManagerImpl.createSourceInContext(context, resource); | |
| 1487 break; | |
| 1488 } | |
| 1489 } | |
| 1490 } | |
| 1491 } | |
| 1492 // Fill the source map. | |
| 1493 bool contextFound = false; | |
| 1494 if (preferredContext != null) { | |
| 1495 sourceMap.putIfAbsent(preferredContext, () => <Source>[]).add(source); | |
| 1496 contextFound = true; | |
| 1497 } | |
| 1498 for (AnalysisContext context in analysisContexts) { | |
| 1499 if (context != preferredContext && | |
| 1500 context.getKindOf(source) != SourceKind.UNKNOWN) { | |
| 1501 sourceMap.putIfAbsent(context, () => <Source>[]).add(source); | |
| 1502 contextFound = true; | |
| 1503 } | |
| 1504 } | |
| 1505 if (firstSource == null) { | |
| 1506 firstSource = source; | |
| 1507 } | |
| 1508 if (!contextFound) { | |
| 1509 unanalyzed.add(file); | |
| 1510 } | |
| 1511 }); | 1167 }); |
| 1512 if (unanalyzed.isNotEmpty) { | |
| 1513 StringBuffer buffer = new StringBuffer(); | |
| 1514 buffer.writeAll(unanalyzed, ', '); | |
| 1515 throw new RequestFailure( | |
| 1516 new Response.unanalyzedPriorityFiles(requestId, buffer.toString())); | |
| 1517 } | |
| 1518 sourceMap.forEach((context, List<Source> sourceList) { | |
| 1519 context.analysisPriorityOrder = sourceList; | |
| 1520 // Schedule the context for analysis so that it has the opportunity to | |
| 1521 // cache the AST's for the priority sources as soon as possible. | |
| 1522 schedulePerformAnalysisOperation(context); | |
| 1523 }); | |
| 1524 operationQueue.reschedule(); | |
| 1525 _onPriorityChangeController.add(new PriorityChangeEvent(firstSource)); | |
| 1526 } | 1168 } |
| 1527 | 1169 |
| 1528 /** | 1170 /** |
| 1529 * Returns `true` if errors should be reported for [file] with the given | 1171 * Returns `true` if errors should be reported for [file] with the given |
| 1530 * absolute path. | 1172 * absolute path. |
| 1531 */ | 1173 */ |
| 1532 bool shouldSendErrorsNotificationFor(String file) { | 1174 bool shouldSendErrorsNotificationFor(String file) { |
| 1533 return contextManager.isInAnalysisRoot(file); | 1175 return contextManager.isInAnalysisRoot(file); |
| 1534 } | 1176 } |
| 1535 | 1177 |
| 1536 void shutdown() { | 1178 void shutdown() { |
| 1537 running = false; | 1179 running = false; |
| 1538 if (index != null) { | 1180 if (index != null) { |
| 1539 index.stop(); | 1181 index.stop(); |
| 1540 } | 1182 } |
| 1541 // Defer closing the channel and shutting down the instrumentation server so | 1183 // Defer closing the channel and shutting down the instrumentation server so |
| 1542 // that the shutdown response can be sent and logged. | 1184 // that the shutdown response can be sent and logged. |
| 1543 new Future(() { | 1185 new Future(() { |
| 1544 instrumentationService.shutdown(); | 1186 instrumentationService.shutdown(); |
| 1545 channel.close(); | 1187 channel.close(); |
| 1546 }); | 1188 }); |
| 1547 } | 1189 } |
| 1548 | 1190 |
| 1549 void test_flushAstStructures(String file) { | |
| 1550 if (AnalysisEngine.isDartFileName(file)) { | |
| 1551 ContextSourcePair contextSource = getContextSourcePair(file); | |
| 1552 InternalAnalysisContext context = contextSource.context; | |
| 1553 Source source = contextSource.source; | |
| 1554 context.test_flushAstStructures(source); | |
| 1555 } | |
| 1556 } | |
| 1557 | |
| 1558 /** | 1191 /** |
| 1559 * Performs all scheduled analysis operations. | 1192 * Performs all scheduled analysis operations. |
| 1560 */ | 1193 */ |
| 1561 void test_performAllAnalysisOperations() { | 1194 void test_performAllAnalysisOperations() { |
| 1562 while (true) { | 1195 while (true) { |
| 1563 ServerOperation operation = operationQueue.takeIf((operation) { | 1196 ServerOperation operation = operationQueue.takeIf((operation) { |
| 1564 return operation is PerformAnalysisOperation; | 1197 return operation is PerformAnalysisOperation; |
| 1565 }); | 1198 }); |
| 1566 if (operation == null) { | 1199 if (operation == null) { |
| 1567 break; | 1200 break; |
| 1568 } | 1201 } |
| 1569 operation.perform(this); | 1202 operation.perform(this); |
| 1570 } | 1203 } |
| 1571 } | 1204 } |
| 1572 | 1205 |
| 1573 /** | 1206 /** |
| 1574 * Implementation for `analysis.updateContent`. | 1207 * Implementation for `analysis.updateContent`. |
| 1575 */ | 1208 */ |
| 1576 void updateContent(String id, Map<String, dynamic> changes) { | 1209 void updateContent(String id, Map<String, dynamic> changes) { |
| 1577 if (options.enableNewAnalysisDriver) { | |
| 1578 changes.forEach((file, change) { | |
| 1579 // Prepare the new contents. | |
| 1580 String oldContents = fileContentOverlay[file]; | |
| 1581 String newContents; | |
| 1582 if (change is AddContentOverlay) { | |
| 1583 newContents = change.content; | |
| 1584 } else if (change is ChangeContentOverlay) { | |
| 1585 if (oldContents == null) { | |
| 1586 // The client may only send a ChangeContentOverlay if there is | |
| 1587 // already an existing overlay for the source. | |
| 1588 throw new RequestFailure(new Response(id, | |
| 1589 error: new RequestError(RequestErrorCode.INVALID_OVERLAY_CHANGE, | |
| 1590 'Invalid overlay change'))); | |
| 1591 } | |
| 1592 try { | |
| 1593 newContents = SourceEdit.applySequence(oldContents, change.edits); | |
| 1594 } on RangeError { | |
| 1595 throw new RequestFailure(new Response(id, | |
| 1596 error: new RequestError(RequestErrorCode.INVALID_OVERLAY_CHANGE, | |
| 1597 'Invalid overlay change'))); | |
| 1598 } | |
| 1599 } else if (change is RemoveContentOverlay) { | |
| 1600 newContents = null; | |
| 1601 } else { | |
| 1602 // Protocol parsing should have ensured that we never get here. | |
| 1603 throw new AnalysisException('Illegal change type'); | |
| 1604 } | |
| 1605 | |
| 1606 fileContentOverlay[file] = newContents; | |
| 1607 | |
| 1608 driverMap.values.forEach((driver) { | |
| 1609 driver.changeFile(file); | |
| 1610 }); | |
| 1611 | |
| 1612 // temporary plugin support: | |
| 1613 _onFileChangedController.add(file); | |
| 1614 | |
| 1615 // If the file did not exist, and is "overlay only", it still should be | |
| 1616 // analyzed. Add it to driver to which it should have been added. | |
| 1617 contextManager.getDriverFor(file)?.addFile(file); | |
| 1618 | |
| 1619 // TODO(scheglov) implement other cases | |
| 1620 }); | |
| 1621 return; | |
| 1622 } | |
| 1623 changes.forEach((file, change) { | 1210 changes.forEach((file, change) { |
| 1624 ContextSourcePair contextSource = getContextSourcePair(file); | |
| 1625 Source source = contextSource.source; | |
| 1626 operationQueue.sourceAboutToChange(source); | |
| 1627 // Prepare the new contents. | 1211 // Prepare the new contents. |
| 1628 String oldContents = overlayState.getContents(source); | 1212 String oldContents = fileContentOverlay[file]; |
| 1629 String newContents; | 1213 String newContents; |
| 1630 if (change is AddContentOverlay) { | 1214 if (change is AddContentOverlay) { |
| 1631 newContents = change.content; | 1215 newContents = change.content; |
| 1632 } else if (change is ChangeContentOverlay) { | 1216 } else if (change is ChangeContentOverlay) { |
| 1633 if (oldContents == null) { | 1217 if (oldContents == null) { |
| 1634 // The client may only send a ChangeContentOverlay if there is | 1218 // The client may only send a ChangeContentOverlay if there is |
| 1635 // already an existing overlay for the source. | 1219 // already an existing overlay for the source. |
| 1636 throw new RequestFailure(new Response(id, | 1220 throw new RequestFailure(new Response(id, |
| 1637 error: new RequestError(RequestErrorCode.INVALID_OVERLAY_CHANGE, | 1221 error: new RequestError(RequestErrorCode.INVALID_OVERLAY_CHANGE, |
| 1638 'Invalid overlay change'))); | 1222 'Invalid overlay change'))); |
| 1639 } | 1223 } |
| 1640 try { | 1224 try { |
| 1641 newContents = SourceEdit.applySequence(oldContents, change.edits); | 1225 newContents = SourceEdit.applySequence(oldContents, change.edits); |
| 1642 } on RangeError { | 1226 } on RangeError { |
| 1643 throw new RequestFailure(new Response(id, | 1227 throw new RequestFailure(new Response(id, |
| 1644 error: new RequestError(RequestErrorCode.INVALID_OVERLAY_CHANGE, | 1228 error: new RequestError(RequestErrorCode.INVALID_OVERLAY_CHANGE, |
| 1645 'Invalid overlay change'))); | 1229 'Invalid overlay change'))); |
| 1646 } | 1230 } |
| 1647 } else if (change is RemoveContentOverlay) { | 1231 } else if (change is RemoveContentOverlay) { |
| 1648 newContents = null; | 1232 newContents = null; |
| 1649 } else { | 1233 } else { |
| 1650 // Protocol parsing should have ensured that we never get here. | 1234 // Protocol parsing should have ensured that we never get here. |
| 1651 throw new AnalysisException('Illegal change type'); | 1235 throw new AnalysisException('Illegal change type'); |
| 1652 } | 1236 } |
| 1653 | 1237 |
| 1654 AnalysisContext containingContext = getContainingContext(file); | 1238 fileContentOverlay[file] = newContents; |
| 1655 | 1239 |
| 1656 // Check for an implicitly added but missing source. | 1240 driverMap.values.forEach((driver) { |
| 1657 // (For example, the target of an import might not exist yet.) | 1241 driver.changeFile(file); |
| 1658 // We need to do this before setContents, which changes the stamp. | 1242 }); |
| 1659 bool wasMissing = containingContext?.getModificationStamp(source) == -1; | |
| 1660 | 1243 |
| 1661 overlayState.setContents(source, newContents); | 1244 // temporary plugin support: |
| 1662 // If the source does not exist, then it was an overlay-only one. | 1245 _onFileChangedController.add(file); |
| 1663 // Remove it from contexts. | 1246 |
| 1664 if (newContents == null && !source.exists()) { | 1247 // If the file did not exist, and is "overlay only", it still should be |
| 1665 for (InternalAnalysisContext context in analysisContexts) { | 1248 // analyzed. Add it to driver to which it should have been added. |
| 1666 List<Source> sources = context.getSourcesWithFullName(file); | 1249 contextManager.getDriverFor(file)?.addFile(file); |
| 1667 ChangeSet changeSet = new ChangeSet(); | 1250 |
| 1668 sources.forEach(changeSet.removedSource); | 1251 // TODO(scheglov) implement other cases |
| 1669 context.applyChanges(changeSet); | |
| 1670 schedulePerformAnalysisOperation(context); | |
| 1671 } | |
| 1672 return; | |
| 1673 } | |
| 1674 // Update all contexts. | |
| 1675 bool anyContextUpdated = false; | |
| 1676 for (InternalAnalysisContext context in analysisContexts) { | |
| 1677 List<Source> sources = context.getSourcesWithFullName(file); | |
| 1678 sources.forEach((Source source) { | |
| 1679 anyContextUpdated = true; | |
| 1680 if (context == containingContext && wasMissing) { | |
| 1681 // Promote missing source to an explicitly added Source. | |
| 1682 context.applyChanges(new ChangeSet()..addedSource(source)); | |
| 1683 schedulePerformAnalysisOperation(context); | |
| 1684 } | |
| 1685 if (context.handleContentsChanged( | |
| 1686 source, oldContents, newContents, true)) { | |
| 1687 schedulePerformAnalysisOperation(context); | |
| 1688 } else { | |
| 1689 // When the client sends any change for a source, we should resend | |
| 1690 // subscribed notifications, even if there were no changes in the | |
| 1691 // source contents. | |
| 1692 // TODO(scheglov) consider checking if there are subscriptions. | |
| 1693 if (AnalysisEngine.isDartFileName(file)) { | |
| 1694 List<CompilationUnit> dartUnits = | |
| 1695 context.ensureResolvedDartUnits(source); | |
| 1696 if (dartUnits != null) { | |
| 1697 AnalysisErrorInfo errorInfo = context.getErrors(source); | |
| 1698 for (var dartUnit in dartUnits) { | |
| 1699 scheduleNotificationOperations( | |
| 1700 this, | |
| 1701 source, | |
| 1702 file, | |
| 1703 errorInfo.lineInfo, | |
| 1704 context, | |
| 1705 null, | |
| 1706 dartUnit, | |
| 1707 errorInfo.errors); | |
| 1708 scheduleIndexOperation(this, file, dartUnit); | |
| 1709 } | |
| 1710 } else { | |
| 1711 schedulePerformAnalysisOperation(context); | |
| 1712 } | |
| 1713 } | |
| 1714 } | |
| 1715 }); | |
| 1716 } | |
| 1717 // The source is not analyzed by any context, add to the containing one. | |
| 1718 if (!anyContextUpdated) { | |
| 1719 AnalysisContext context = contextSource.context; | |
| 1720 if (context != null && source != null) { | |
| 1721 ChangeSet changeSet = new ChangeSet(); | |
| 1722 changeSet.addedSource(source); | |
| 1723 context.applyChanges(changeSet); | |
| 1724 schedulePerformAnalysisOperation(context); | |
| 1725 } | |
| 1726 } | |
| 1727 }); | 1252 }); |
| 1728 } | 1253 } |
| 1729 | 1254 |
| 1730 /** | 1255 /** |
| 1731 * Use the given updaters to update the values of the options in every | 1256 * Use the given updaters to update the values of the options in every |
| 1732 * existing analysis context. | 1257 * existing analysis context. |
| 1733 */ | 1258 */ |
| 1734 void updateOptions(List<OptionUpdater> optionUpdaters) { | 1259 void updateOptions(List<OptionUpdater> optionUpdaters) { |
| 1735 if (options.enableNewAnalysisDriver) { | 1260 // TODO(scheglov) implement for the new analysis driver |
| 1736 // TODO(scheglov) implement for the new analysis driver | 1261 // // |
| 1737 return; | 1262 // // Update existing contexts. |
| 1738 } | 1263 // // |
| 1739 // | 1264 // for (AnalysisContext context in analysisContexts) { |
| 1740 // Update existing contexts. | 1265 // AnalysisOptionsImpl options = |
| 1741 // | 1266 // new AnalysisOptionsImpl.from(context.analysisOptions); |
| 1742 for (AnalysisContext context in analysisContexts) { | 1267 // optionUpdaters.forEach((OptionUpdater optionUpdater) { |
| 1743 AnalysisOptionsImpl options = | 1268 // optionUpdater(options); |
| 1744 new AnalysisOptionsImpl.from(context.analysisOptions); | 1269 // }); |
| 1745 optionUpdaters.forEach((OptionUpdater optionUpdater) { | 1270 // context.analysisOptions = options; |
| 1746 optionUpdater(options); | 1271 // // TODO(brianwilkerson) As far as I can tell, this doesn't cause analysi
s |
| 1747 }); | 1272 // // to be scheduled for this context. |
| 1748 context.analysisOptions = options; | 1273 // } |
| 1749 // TODO(brianwilkerson) As far as I can tell, this doesn't cause analysis | 1274 // // |
| 1750 // to be scheduled for this context. | 1275 // // Update the defaults used to create new contexts. |
| 1751 } | 1276 // // |
| 1752 // | 1277 // optionUpdaters.forEach((OptionUpdater optionUpdater) { |
| 1753 // Update the defaults used to create new contexts. | 1278 // optionUpdater(defaultContextOptions); |
| 1754 // | 1279 // }); |
| 1755 optionUpdaters.forEach((OptionUpdater optionUpdater) { | |
| 1756 optionUpdater(defaultContextOptions); | |
| 1757 }); | |
| 1758 } | 1280 } |
| 1759 | 1281 |
| 1760 void _computingPackageMap(bool computing) { | 1282 void _computingPackageMap(bool computing) { |
| 1761 if (serverServices.contains(ServerService.STATUS)) { | 1283 if (serverServices.contains(ServerService.STATUS)) { |
| 1762 PubStatus pubStatus = new PubStatus(computing); | 1284 PubStatus pubStatus = new PubStatus(computing); |
| 1763 ServerStatusParams params = new ServerStatusParams(pub: pubStatus); | 1285 ServerStatusParams params = new ServerStatusParams(pub: pubStatus); |
| 1764 sendNotification(params.toNotification()); | 1286 sendNotification(params.toNotification()); |
| 1765 } | 1287 } |
| 1766 } | 1288 } |
| 1767 | 1289 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1805 Set<AnalysisContext> _getContexts(List<Resource> resources) { | 1327 Set<AnalysisContext> _getContexts(List<Resource> resources) { |
| 1806 Set<AnalysisContext> contexts = new HashSet<AnalysisContext>(); | 1328 Set<AnalysisContext> contexts = new HashSet<AnalysisContext>(); |
| 1807 resources.forEach((Resource resource) { | 1329 resources.forEach((Resource resource) { |
| 1808 if (resource is Folder) { | 1330 if (resource is Folder) { |
| 1809 contexts.addAll(contextManager.contextsInAnalysisRoot(resource)); | 1331 contexts.addAll(contextManager.contextsInAnalysisRoot(resource)); |
| 1810 } | 1332 } |
| 1811 }); | 1333 }); |
| 1812 return contexts; | 1334 return contexts; |
| 1813 } | 1335 } |
| 1814 | 1336 |
| 1815 /** | |
| 1816 * Returns the [CompilationUnit] of the Dart file with the given [source] that | |
| 1817 * should be used to resend notifications for already resolved unit. | |
| 1818 * Returns `null` if the file is not a part of any context, library has not | |
| 1819 * been yet resolved, or any problem happened. | |
| 1820 */ | |
| 1821 CompilationUnit _getResolvedCompilationUnitToResendNotification( | |
| 1822 AnalysisContext context, Source source) { | |
| 1823 List<Source> librarySources = context.getLibrariesContaining(source); | |
| 1824 if (librarySources.isEmpty) { | |
| 1825 return null; | |
| 1826 } | |
| 1827 // if library has not been resolved yet, the unit will be resolved later | |
| 1828 Source librarySource = librarySources[0]; | |
| 1829 if (context.getResult(librarySource, LIBRARY_ELEMENT6) == null) { | |
| 1830 return null; | |
| 1831 } | |
| 1832 // if library has been already resolved, resolve unit | |
| 1833 return runWithActiveContext(context, () { | |
| 1834 return context.resolveCompilationUnit2(source, librarySource); | |
| 1835 }); | |
| 1836 } | |
| 1837 | |
| 1838 bool _hasAnalysisServiceSubscription(AnalysisService service, String file) { | 1337 bool _hasAnalysisServiceSubscription(AnalysisService service, String file) { |
| 1839 return analysisServices[service]?.contains(file) ?? false; | 1338 return analysisServices[service]?.contains(file) ?? false; |
| 1840 } | 1339 } |
| 1841 | 1340 |
| 1842 _scheduleAnalysisImplementedNotification() async { | 1341 _scheduleAnalysisImplementedNotification() async { |
| 1843 Set<String> files = analysisServices[AnalysisService.IMPLEMENTED]; | 1342 Set<String> files = analysisServices[AnalysisService.IMPLEMENTED]; |
| 1844 if (files != null) { | 1343 if (files != null) { |
| 1845 scheduleImplementedNotification(this, files); | 1344 scheduleImplementedNotification(this, files); |
| 1846 } | 1345 } |
| 1847 } | 1346 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1879 * | 1378 * |
| 1880 * It is possible that this method will do more in the future, e.g. listening | 1379 * It is possible that this method will do more in the future, e.g. listening |
| 1881 * for summary information and linking pre-indexed packages into the index, | 1380 * for summary information and linking pre-indexed packages into the index, |
| 1882 * but for now we only invalidate project specific index information. | 1381 * but for now we only invalidate project specific index information. |
| 1883 */ | 1382 */ |
| 1884 void _setupIndexInvalidation() { | 1383 void _setupIndexInvalidation() { |
| 1885 if (index == null) { | 1384 if (index == null) { |
| 1886 return; | 1385 return; |
| 1887 } | 1386 } |
| 1888 onContextsChanged.listen((ContextsChangedEvent event) { | 1387 onContextsChanged.listen((ContextsChangedEvent event) { |
| 1889 for (AnalysisContext context in event.added) { | 1388 // TODO(brianwilkerson) `onContextsChanged` should never have anything |
| 1890 context | 1389 // written to it. Figure out whether we need something like this under the |
| 1891 .onResultChanged(RESOLVED_UNIT3) | 1390 // new analysis driver, and remove this method if not. |
| 1892 .listen((ResultChangedEvent event) { | 1391 // for (AnalysisContext context in event.added) { |
| 1893 if (event.wasComputed) { | 1392 // context |
| 1894 Object value = event.value; | 1393 // .onResultChanged(RESOLVED_UNIT3) |
| 1895 if (value is CompilationUnit) { | 1394 // .listen((ResultChangedEvent event) { |
| 1896 index.indexDeclarations(value); | 1395 // if (event.wasComputed) { |
| 1897 } | 1396 // Object value = event.value; |
| 1898 } | 1397 // if (value is CompilationUnit) { |
| 1899 }); | 1398 // index.indexDeclarations(value); |
| 1900 context | 1399 // } |
| 1901 .onResultChanged(RESOLVED_UNIT) | 1400 // } |
| 1902 .listen((ResultChangedEvent event) { | 1401 // }); |
| 1903 if (event.wasInvalidated) { | 1402 // context |
| 1904 LibrarySpecificUnit target = event.target; | 1403 // .onResultChanged(RESOLVED_UNIT) |
| 1905 index.removeUnit(event.context, target.library, target.unit); | 1404 // .listen((ResultChangedEvent event) { |
| 1906 } | 1405 // if (event.wasInvalidated) { |
| 1907 }); | 1406 // LibrarySpecificUnit target = event.target; |
| 1908 } | 1407 // index.removeUnit(event.context, target.library, target.unit); |
| 1909 for (AnalysisContext context in event.removed) { | 1408 // } |
| 1910 index.removeContext(context); | 1409 // }); |
| 1911 } | 1410 // } |
| 1411 // for (AnalysisContext context in event.removed) { |
| 1412 // index.removeContext(context); |
| 1413 // } |
| 1912 }); | 1414 }); |
| 1913 } | 1415 } |
| 1914 } | 1416 } |
| 1915 | 1417 |
| 1916 class AnalysisServerOptions { | 1418 class AnalysisServerOptions { |
| 1917 bool enableIncrementalResolutionApi = false; | 1419 bool enableIncrementalResolutionApi = false; |
| 1918 bool enableIncrementalResolutionValidation = false; | 1420 bool enableIncrementalResolutionValidation = false; |
| 1919 bool enableNewAnalysisDriver = false; | |
| 1920 bool useAnalysisHighlight2 = false; | 1421 bool useAnalysisHighlight2 = false; |
| 1921 String fileReadMode = 'as-is'; | 1422 String fileReadMode = 'as-is'; |
| 1922 String newAnalysisDriverLog; | 1423 String newAnalysisDriverLog; |
| 1923 | 1424 |
| 1924 String clientId; | 1425 String clientId; |
| 1925 String clientVersion; | 1426 String clientVersion; |
| 1926 | 1427 |
| 1927 // IDE options | 1428 // IDE options |
| 1928 bool enableVerboseFlutterCompletions = false; | 1429 bool enableVerboseFlutterCompletions = false; |
| 1929 } | 1430 } |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2088 analysisServer.folderMap[folder] = context; | 1589 analysisServer.folderMap[folder] = context; |
| 2089 analysisServer._onContextsChangedController | 1590 analysisServer._onContextsChangedController |
| 2090 .add(new ContextsChangedEvent(added: [context])); | 1591 .add(new ContextsChangedEvent(added: [context])); |
| 2091 analysisServer.schedulePerformAnalysisOperation(context); | 1592 analysisServer.schedulePerformAnalysisOperation(context); |
| 2092 | 1593 |
| 2093 return context; | 1594 return context; |
| 2094 } | 1595 } |
| 2095 | 1596 |
| 2096 @override | 1597 @override |
| 2097 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) { | 1598 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) { |
| 2098 if (analysisServer.options.enableNewAnalysisDriver) { | 1599 nd.AnalysisDriver analysisDriver = analysisServer.driverMap[contextFolder]; |
| 2099 nd.AnalysisDriver analysisDriver = | 1600 if (analysisDriver != null) { |
| 2100 analysisServer.driverMap[contextFolder]; | 1601 changeSet.addedSources.forEach((source) { |
| 2101 if (analysisDriver != null) { | 1602 analysisDriver.addFile(source.fullName); |
| 2102 changeSet.addedSources.forEach((source) { | 1603 // temporary plugin support: |
| 2103 analysisDriver.addFile(source.fullName); | 1604 analysisServer._onFileAddedController.add(source.fullName); |
| 2104 // temporary plugin support: | 1605 }); |
| 2105 analysisServer._onFileAddedController.add(source.fullName); | 1606 changeSet.changedSources.forEach((source) { |
| 2106 }); | 1607 analysisDriver.changeFile(source.fullName); |
| 2107 changeSet.changedSources.forEach((source) { | 1608 // temporary plugin support: |
| 2108 analysisDriver.changeFile(source.fullName); | 1609 analysisServer._onFileChangedController.add(source.fullName); |
| 2109 // temporary plugin support: | 1610 }); |
| 2110 analysisServer._onFileChangedController.add(source.fullName); | 1611 changeSet.removedSources.forEach((source) { |
| 2111 }); | 1612 analysisDriver.removeFile(source.fullName); |
| 2112 changeSet.removedSources.forEach((source) { | 1613 }); |
| 2113 analysisDriver.removeFile(source.fullName); | |
| 2114 }); | |
| 2115 } | |
| 2116 } else { | |
| 2117 AnalysisContext context = analysisServer.folderMap[contextFolder]; | |
| 2118 if (context != null) { | |
| 2119 context.applyChanges(changeSet); | |
| 2120 analysisServer.schedulePerformAnalysisOperation(context); | |
| 2121 List<String> flushedFiles = new List<String>(); | |
| 2122 for (Source source in changeSet.removedSources) { | |
| 2123 flushedFiles.add(source.fullName); | |
| 2124 } | |
| 2125 sendAnalysisNotificationFlushResults(analysisServer, flushedFiles); | |
| 2126 } | |
| 2127 } | 1614 } |
| 2128 } | 1615 } |
| 2129 | 1616 |
| 2130 @override | 1617 @override |
| 2131 void applyFileRemoved(nd.AnalysisDriver driver, String file) { | 1618 void applyFileRemoved(nd.AnalysisDriver driver, String file) { |
| 2132 driver.removeFile(file); | 1619 driver.removeFile(file); |
| 2133 sendAnalysisNotificationFlushResults(analysisServer, [file]); | 1620 sendAnalysisNotificationFlushResults(analysisServer, [file]); |
| 2134 } | 1621 } |
| 2135 | 1622 |
| 2136 @override | 1623 @override |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2177 | 1664 |
| 2178 @override | 1665 @override |
| 2179 void moveContext(Folder from, Folder to) { | 1666 void moveContext(Folder from, Folder to) { |
| 2180 // There is nothing to do. | 1667 // There is nothing to do. |
| 2181 // This method is mostly for tests. | 1668 // This method is mostly for tests. |
| 2182 // Context managers manage folders and contexts themselves. | 1669 // Context managers manage folders and contexts themselves. |
| 2183 } | 1670 } |
| 2184 | 1671 |
| 2185 @override | 1672 @override |
| 2186 void removeContext(Folder folder, List<String> flushedFiles) { | 1673 void removeContext(Folder folder, List<String> flushedFiles) { |
| 2187 if (analysisServer.options.enableNewAnalysisDriver) { | 1674 sendAnalysisNotificationFlushResults(analysisServer, flushedFiles); |
| 2188 sendAnalysisNotificationFlushResults(analysisServer, flushedFiles); | 1675 nd.AnalysisDriver driver = analysisServer.driverMap.remove(folder); |
| 2189 nd.AnalysisDriver driver = analysisServer.driverMap.remove(folder); | 1676 driver.dispose(); |
| 2190 driver.dispose(); | |
| 2191 } else { | |
| 2192 AnalysisContext context = analysisServer.folderMap.remove(folder); | |
| 2193 sendAnalysisNotificationFlushResults(analysisServer, flushedFiles); | |
| 2194 | |
| 2195 analysisServer.operationQueue.contextRemoved(context); | |
| 2196 analysisServer._onContextsChangedController | |
| 2197 .add(new ContextsChangedEvent(removed: [context])); | |
| 2198 analysisServer.sendContextAnalysisDoneNotifications( | |
| 2199 context, AnalysisDoneReason.CONTEXT_REMOVED); | |
| 2200 context.dispose(); | |
| 2201 } | |
| 2202 } | 1677 } |
| 2203 | 1678 |
| 2204 @override | 1679 @override |
| 2205 void updateContextPackageUriResolver(AnalysisContext context) { | 1680 void updateContextPackageUriResolver(AnalysisContext context) { |
| 2206 analysisServer._onContextsChangedController | 1681 analysisServer._onContextsChangedController |
| 2207 .add(new ContextsChangedEvent(changed: [context])); | 1682 .add(new ContextsChangedEvent(changed: [context])); |
| 2208 analysisServer.schedulePerformAnalysisOperation(context); | 1683 analysisServer.schedulePerformAnalysisOperation(context); |
| 2209 } | 1684 } |
| 2210 | 1685 |
| 2211 List<HighlightRegion> _computeHighlightRegions(CompilationUnit unit) { | 1686 List<HighlightRegion> _computeHighlightRegions(CompilationUnit unit) { |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2401 /** | 1876 /** |
| 2402 * The [PerformanceTag] for time spent in server request handlers. | 1877 * The [PerformanceTag] for time spent in server request handlers. |
| 2403 */ | 1878 */ |
| 2404 static PerformanceTag serverRequests = server.createChild('requests'); | 1879 static PerformanceTag serverRequests = server.createChild('requests'); |
| 2405 | 1880 |
| 2406 /** | 1881 /** |
| 2407 * The [PerformanceTag] for time spent in split store microtasks. | 1882 * The [PerformanceTag] for time spent in split store microtasks. |
| 2408 */ | 1883 */ |
| 2409 static PerformanceTag splitStore = new PerformanceTag('splitStore'); | 1884 static PerformanceTag splitStore = new PerformanceTag('splitStore'); |
| 2410 } | 1885 } |
| OLD | NEW |