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

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

Issue 1243233003: Preliminary refactoring work on ContextManager. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Minor additions to comments. Created 5 years, 5 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 | no next file » | 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 library context.directory.manager; 5 library context.directory.manager;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection'; 8 import 'dart:collection';
9 import 'dart:convert'; 9 import 'dart:convert';
10 import 'dart:core' hide Resource; 10 import 'dart:core' hide Resource;
(...skipping 25 matching lines...) Expand all
36 * The [Folder] for which this information object is created. 36 * The [Folder] for which this information object is created.
37 */ 37 */
38 final Folder folder; 38 final Folder folder;
39 39
40 /// The [PathFilter] used to filter sources from being analyzed. 40 /// The [PathFilter] used to filter sources from being analyzed.
41 final PathFilter pathFilter; 41 final PathFilter pathFilter;
42 42
43 /** 43 /**
44 * The enclosed pubspec-based contexts. 44 * The enclosed pubspec-based contexts.
45 */ 45 */
46 final List<ContextInfo> children; 46 final List<ContextInfo> children = <ContextInfo>[];
47 47
48 /** 48 /**
49 * The package root for this context, or null if there is no package root. 49 * The package root for this context, or null if there is no package root.
50 */ 50 */
51 String packageRoot; 51 String packageRoot;
52 52
53 /** 53 /**
54 * The [ContextInfo] that encloses this one. 54 * The [ContextInfo] that encloses this one, or `null` if this is the virtual
55 * [ContextInfo] object that acts as the ancestor of all other [ContextInfo]
56 * objects.
55 */ 57 */
56 ContextInfo parent; 58 ContextInfo parent;
57 59
58 /** 60 /**
59 * The package description file path for this context. 61 * The package description file path for this context.
60 */ 62 */
61 String packageDescriptionPath; 63 String packageDescriptionPath;
62 64
63 /** 65 /**
64 * Stream subscription we are using to watch the context's directory for 66 * Stream subscription we are using to watch the context's directory for
(...skipping 20 matching lines...) Expand all
85 Map<String, Source> sources = new HashMap<String, Source>(); 87 Map<String, Source> sources = new HashMap<String, Source>();
86 88
87 /** 89 /**
88 * Info returned by the last call to 90 * Info returned by the last call to
89 * [OptimizingPubPackageMapProvider.computePackageMap], or `null` if the 91 * [OptimizingPubPackageMapProvider.computePackageMap], or `null` if the
90 * package map hasn't been computed for this context yet. 92 * package map hasn't been computed for this context yet.
91 */ 93 */
92 OptimizingPubPackageMapInfo packageMapInfo; 94 OptimizingPubPackageMapInfo packageMapInfo;
93 95
94 ContextInfo( 96 ContextInfo(
95 Folder folder, File packagespecFile, this.children, this.packageRoot) 97 this.parent, Folder folder, File packagespecFile, this.packageRoot)
96 : folder = folder, 98 : folder = folder,
97 pathFilter = new PathFilter(folder.path, null) { 99 pathFilter = new PathFilter(folder.path, null) {
98 packageDescriptionPath = packagespecFile.path; 100 packageDescriptionPath = packagespecFile.path;
99 for (ContextInfo child in children) { 101 parent.children.add(this);
100 child.parent = this;
101 }
102 } 102 }
103 103
104 /** 104 /**
105 * Returns `true` if this context is root folder based. 105 * Create the virtual [ContextInfo] which acts as an ancestor to all other
106 * [ContextInfo]s.
106 */ 107 */
107 bool get isRoot => parent == null; 108 ContextInfo._ancestor()
Brian Wilkerson 2015/07/22 13:52:24 Perhaps "ContextInfo._root"?
Paul Berry 2015/07/22 17:31:49 Acknowledged. After discussion this morning, I wi
109 : folder = null,
110 pathFilter = null;
111
112 /**
113 * Returns `true` if the folder associated with this context is not contained
114 * within any other folders that have an associated context.
115 */
116 bool get isRoot => parent.parent == null;
108 117
109 /** 118 /**
110 * Returns `true` if [path] is excluded, as it is in one of the children. 119 * Returns `true` if [path] is excluded, as it is in one of the children.
111 */ 120 */
112 bool excludes(String path) { 121 bool excludes(String path) {
113 return children.any((child) { 122 return children.any((child) {
114 return child.folder.contains(path); 123 return child.folder.contains(path);
115 }); 124 });
116 } 125 }
117 126
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 new AnalysisOptionsProvider(); 352 new AnalysisOptionsProvider();
344 353
345 /** 354 /**
346 * The instrumentation service used to report instrumentation data. 355 * The instrumentation service used to report instrumentation data.
347 */ 356 */
348 final InstrumentationService _instrumentationService; 357 final InstrumentationService _instrumentationService;
349 358
350 @override 359 @override
351 ContextManagerCallbacks callbacks; 360 ContextManagerCallbacks callbacks;
352 361
362 /**
363 * Virtual [ContextInfo] which acts as the ancestor of all other
364 * [ContextInfo]s.
365 */
366 ContextInfo _ancestorInfo = new ContextInfo._ancestor();
scheglov 2015/07/22 00:05:51 final?
Brian Wilkerson 2015/07/22 13:52:24 Perhaps "_rootInfo"?
Paul Berry 2015/07/22 17:31:49 Done.
367
353 ContextManagerImpl(this.resourceProvider, this.packageResolverProvider, 368 ContextManagerImpl(this.resourceProvider, this.packageResolverProvider,
354 this._packageMapProvider, this._instrumentationService) { 369 this._packageMapProvider, this._instrumentationService) {
355 pathContext = resourceProvider.pathContext; 370 pathContext = resourceProvider.pathContext;
356 } 371 }
357 372
358 @override 373 @override
359 List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot) { 374 List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot) {
360 List<AnalysisContext> contexts = <AnalysisContext>[]; 375 List<AnalysisContext> contexts = <AnalysisContext>[];
361 _contexts.forEach((Folder contextFolder, ContextInfo info) { 376 _contexts.forEach((Folder contextFolder, ContextInfo info) {
362 if (analysisRoot.isOrContains(contextFolder.path)) { 377 if (analysisRoot.isOrContains(contextFolder.path)) {
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 info.packageRoot = newPackageRoot; 497 info.packageRoot = newPackageRoot;
483 _recomputePackageUriResolver(info); 498 _recomputePackageUriResolver(info);
484 } 499 }
485 }); 500 });
486 // create new contexts 501 // create new contexts
487 for (Folder includedFolder in includedFolders) { 502 for (Folder includedFolder in includedFolders) {
488 bool wasIncluded = contextFolders.any((folder) { 503 bool wasIncluded = contextFolders.any((folder) {
489 return folder.isOrContains(includedFolder.path); 504 return folder.isOrContains(includedFolder.path);
490 }); 505 });
491 if (!wasIncluded) { 506 if (!wasIncluded) {
492 _createContexts(includedFolder, false); 507 _createContexts(_ancestorInfo, includedFolder, false);
493 } 508 }
494 } 509 }
495 // remove newly excluded sources 510 // remove newly excluded sources
496 _contexts.forEach((folder, info) { 511 _contexts.forEach((folder, info) {
497 // prepare excluded sources 512 // prepare excluded sources
498 Map<String, Source> excludedSources = new HashMap<String, Source>(); 513 Map<String, Source> excludedSources = new HashMap<String, Source>();
499 info.sources.forEach((String path, Source source) { 514 info.sources.forEach((String path, Source source) {
500 if (_isExcludedBy(excludedPaths, path) && 515 if (_isExcludedBy(excludedPaths, path) &&
501 !_isExcludedBy(oldExcludedPaths, path)) { 516 !_isExcludedBy(oldExcludedPaths, path)) {
502 excludedSources[path] = source; 517 excludedSources[path] = source;
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 return null; 737 return null;
723 } 738 }
724 return new PackageMapUriResolver( 739 return new PackageMapUriResolver(
725 resourceProvider, packageMapInfo.packageMap); 740 resourceProvider, packageMapInfo.packageMap);
726 // TODO(paulberry): if any of the dependencies is outside of [folder], 741 // TODO(paulberry): if any of the dependencies is outside of [folder],
727 // we'll need to watch their parent folders as well. 742 // we'll need to watch their parent folders as well.
728 } 743 }
729 } 744 }
730 745
731 /** 746 /**
732 * Create a new empty context associated with [folder]. 747 * Create a new empty context associated with [folder], having parent
748 * [parent] and using [packagespecFile] to resolve package URI's.
733 */ 749 */
734 ContextInfo _createContext( 750 ContextInfo _createContext(
735 Folder folder, File packagespecFile, List<ContextInfo> children) { 751 ContextInfo parent, Folder folder, File packagespecFile) {
736 ContextInfo info = new ContextInfo( 752 ContextInfo info = new ContextInfo(
737 folder, packagespecFile, children, normalizedPackageRoots[folder.path]); 753 parent, folder, packagespecFile, normalizedPackageRoots[folder.path]);
738 _contexts[folder] = info; 754 _contexts[folder] = info;
739 Map<String, YamlNode> options = analysisOptionsProvider.getOptions(folder); 755 Map<String, YamlNode> options = analysisOptionsProvider.getOptions(folder);
740 processOptionsForContext(info, options); 756 processOptionsForContext(info, options);
741 info.changeSubscription = folder.changes.listen((WatchEvent event) { 757 info.changeSubscription = folder.changes.listen((WatchEvent event) {
742 _handleWatchEvent(folder, info, event); 758 _handleWatchEvent(folder, info, event);
743 }); 759 });
744 try { 760 try {
745 Packages packages; 761 Packages packages;
746 UriResolver packageUriResolver; 762 UriResolver packageUriResolver;
747 763
(...skipping 21 matching lines...) Expand all
769 /** 785 /**
770 * Potentially create a new context associated with the given [folder]. 786 * Potentially create a new context associated with the given [folder].
771 * 787 *
772 * If there are subfolders with 'pubspec.yaml' files, separate contexts are 788 * If there are subfolders with 'pubspec.yaml' files, separate contexts are
773 * created for them and excluded from the context associated with the 789 * created for them and excluded from the context associated with the
774 * [folder]. 790 * [folder].
775 * 791 *
776 * If [withPackageSpecOnly] is `true`, a context will be created only if there 792 * If [withPackageSpecOnly] is `true`, a context will be created only if there
777 * is a 'pubspec.yaml' or '.packages' file in the [folder]. 793 * is a 'pubspec.yaml' or '.packages' file in the [folder].
778 * 794 *
779 * Returns created contexts. 795 * [parent] should be the parent of any contexts that are created.
780 */ 796 */
781 List<ContextInfo> _createContexts(Folder folder, bool withPackageSpecOnly) { 797 void _createContexts(
782 // Try to find subfolders with pubspecs or .packages files. 798 ContextInfo parent, Folder folder, bool withPackageSpecOnly) {
783 List<ContextInfo> children = <ContextInfo>[]; 799 // Decide whether a context needs to be created for [folder] here, and if
784 try { 800 // so, create it.
785 for (Resource child in folder.getChildren()) {
786 if (child is Folder) {
787 children.addAll(_createContexts(child, true));
788 }
789 }
790 } on FileSystemException {
791 // The directory either doesn't exist or cannot be read. Either way, there
792 // are no subfolders that need to be added.
793 }
794
795 File packageSpec; 801 File packageSpec;
796 802
797 if (ENABLE_PACKAGESPEC_SUPPORT) { 803 if (ENABLE_PACKAGESPEC_SUPPORT) {
798 // Start by looking for .packages. 804 // Start by looking for .packages.
799 packageSpec = folder.getChild(PACKAGE_SPEC_NAME); 805 packageSpec = folder.getChild(PACKAGE_SPEC_NAME);
800 } 806 }
801 807
802 // Fall back to looking for a pubspec. 808 // Fall back to looking for a pubspec.
803 if (packageSpec == null || !packageSpec.exists) { 809 if (packageSpec == null || !packageSpec.exists) {
804 packageSpec = folder.getChild(PUBSPEC_NAME); 810 packageSpec = folder.getChild(PUBSPEC_NAME);
805 } 811 }
806 812
807 if (packageSpec.exists) { 813 bool parentCreated = false;
808 return <ContextInfo>[ 814 if (packageSpec.exists || !withPackageSpecOnly) {
809 _createContextWithSources(folder, packageSpec, children) 815 parentCreated = true;
810 ]; 816 parent = _createContext(parent, folder, packageSpec);
811 } 817 }
812 // No packagespec? Done. 818
813 if (withPackageSpecOnly) { 819 // Try to find subfolders with pubspecs or .packages files.
814 return children; 820 try {
821 for (Resource child in folder.getChildren()) {
822 if (child is Folder) {
823 _createContexts(parent, child, true);
824 }
825 }
826 } on FileSystemException {
827 // The directory either doesn't exist or cannot be read. Either way, there
828 // are no subfolders that need to be added.
815 } 829 }
816 // OK, create a context without a packagespec. 830
817 return <ContextInfo>[ 831 if (parentCreated) {
818 _createContextWithSources(folder, packageSpec, children) 832 // Now that the child contexts have been created, add the sources that
819 ]; 833 // don't belong to the children.
834 ChangeSet changeSet = new ChangeSet();
835 _addSourceFiles(changeSet, folder, parent);
836 callbacks.applyChangesToContext(folder, changeSet);
837 }
820 } 838 }
821 839
822 /** 840 /**
823 * Create a new context associated with the given [folder]. The [pubspecFile]
824 * is the `pubspec.yaml` file contained in the folder. Add any sources that
825 * are not included in one of the [children] to the context.
826 */
827 ContextInfo _createContextWithSources(
828 Folder folder, File pubspecFile, List<ContextInfo> children) {
829 ContextInfo info = _createContext(folder, pubspecFile, children);
830 ChangeSet changeSet = new ChangeSet();
831 _addSourceFiles(changeSet, folder, info);
832 callbacks.applyChangesToContext(folder, changeSet);
833 return info;
834 }
835
836 /**
837 * Clean up and destroy the context associated with the given folder. 841 * Clean up and destroy the context associated with the given folder.
838 */ 842 */
839 void _destroyContext(Folder folder) { 843 void _destroyContext(Folder folder) {
840 ContextInfo info = _contexts[folder]; 844 ContextInfo info = _contexts[folder];
841 info.changeSubscription.cancel(); 845 info.changeSubscription.cancel();
842 _cancelDependencySubscriptions(info); 846 _cancelDependencySubscriptions(info);
843 callbacks.removeContext(folder, _computeFlushedFiles(folder)); 847 callbacks.removeContext(folder, _computeFlushedFiles(folder));
848 bool wasRemoved = info.parent.children.remove(info);
849 assert(wasRemoved);
844 _contexts.remove(folder); 850 _contexts.remove(folder);
845 } 851 }
846 852
847 /** 853 /**
848 * Extract a new [packagespecFile]-based context from [oldInfo]. 854 * Extract a new [packagespecFile]-based context from [oldInfo].
849 */ 855 */
850 void _extractContext(ContextInfo oldInfo, File packagespecFile) { 856 void _extractContext(ContextInfo oldInfo, File packagespecFile) {
851 Folder newFolder = packagespecFile.parent; 857 Folder newFolder = packagespecFile.parent;
852 ContextInfo newInfo = _createContext(newFolder, packagespecFile, []); 858 ContextInfo newInfo = _createContext(oldInfo, newFolder, packagespecFile);
853 newInfo.parent = oldInfo;
854 // prepare sources to extract 859 // prepare sources to extract
855 Map<String, Source> extractedSources = new HashMap<String, Source>(); 860 Map<String, Source> extractedSources = new HashMap<String, Source>();
856 oldInfo.sources.forEach((path, source) { 861 oldInfo.sources.forEach((path, source) {
857 if (newFolder.contains(path)) { 862 if (newFolder.contains(path)) {
858 extractedSources[path] = source; 863 extractedSources[path] = source;
859 } 864 }
860 }); 865 });
861 // update new context 866 // update new context
862 { 867 {
863 ChangeSet changeSet = new ChangeSet(); 868 ChangeSet changeSet = new ChangeSet();
864 extractedSources.forEach((path, source) { 869 extractedSources.forEach((path, source) {
865 newInfo.sources[path] = source; 870 newInfo.sources[path] = source;
866 changeSet.addedSource(source); 871 changeSet.addedSource(source);
867 }); 872 });
868 callbacks.applyChangesToContext(newFolder, changeSet); 873 callbacks.applyChangesToContext(newFolder, changeSet);
869 } 874 }
870 // update old context 875 // update old context
871 { 876 {
872 ChangeSet changeSet = new ChangeSet(); 877 ChangeSet changeSet = new ChangeSet();
873 extractedSources.forEach((path, source) { 878 extractedSources.forEach((path, source) {
874 oldInfo.sources.remove(path); 879 oldInfo.sources.remove(path);
875 changeSet.removedSource(source); 880 changeSet.removedSource(source);
876 }); 881 });
877 callbacks.applyChangesToContext(oldInfo.folder, changeSet); 882 callbacks.applyChangesToContext(oldInfo.folder, changeSet);
878 } 883 }
884 // TODO(paulberry): every context that was previously a child of oldInfo is
885 // is still a child of oldInfo. This is wrong--some of them ought to be
886 // adopted by newInfo now.
879 } 887 }
880 888
881 void _handleWatchEvent(Folder folder, ContextInfo info, WatchEvent event) { 889 void _handleWatchEvent(Folder folder, ContextInfo info, WatchEvent event) {
882 // TODO(brianwilkerson) If a file is explicitly included in one context 890 // TODO(brianwilkerson) If a file is explicitly included in one context
883 // but implicitly referenced in another context, we will only send a 891 // but implicitly referenced in another context, we will only send a
884 // changeSet to the context that explicitly includes the file (because 892 // changeSet to the context that explicitly includes the file (because
885 // that's the only context that's watching the file). 893 // that's the only context that's watching the file).
886 _instrumentationService.logWatchEvent( 894 _instrumentationService.logWatchEvent(
887 folder.path, event.path, event.type.toString()); 895 folder.path, event.path, event.type.toString());
888 String path = event.path; 896 String path = event.path;
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
1142 */ 1150 */
1143 final List<AnalysisContext> removed; 1151 final List<AnalysisContext> removed;
1144 1152
1145 /** 1153 /**
1146 * Initialize a newly created event to indicate which contexts have changed. 1154 * Initialize a newly created event to indicate which contexts have changed.
1147 */ 1155 */
1148 ContextsChangedEvent({this.added: AnalysisContext.EMPTY_LIST, 1156 ContextsChangedEvent({this.added: AnalysisContext.EMPTY_LIST,
1149 this.changed: AnalysisContext.EMPTY_LIST, 1157 this.changed: AnalysisContext.EMPTY_LIST,
1150 this.removed: AnalysisContext.EMPTY_LIST}); 1158 this.removed: AnalysisContext.EMPTY_LIST});
1151 } 1159 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698