Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(413)

Side by Side Diff: pkg/analysis_server/lib/src/analysis_server.dart

Issue 2937323003: Remove ability to disable new analysis driver (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/analysis_server/lib/src/context_manager.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_server/lib/src/context_manager.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698