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

Unified Diff: pkg/analysis_server/lib/src/context_manager.dart

Issue 1243063003: Get rid of ContextManager._contexts. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Fix typo. 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 side-by-side diff with in-line comments
Download patch
Index: pkg/analysis_server/lib/src/context_manager.dart
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index ed2e3a01193b239245bdbcd6b2b364186ddd0b83..68f85ca6154c444d1f117ce31476df823ddda3d2 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -110,6 +110,16 @@ class ContextInfo {
pathFilter = null;
/**
+ * Iterate through all [children] and their children, recursively.
+ */
+ Iterable<ContextInfo> get descendants sync* {
+ for (ContextInfo child in children) {
+ yield child;
+ yield* child.descendants;
+ }
+ }
+
+ /**
* Returns `true` if this is a "top level" context, meaning that the folder
* associated with it is not contained within any other folders that have an
* associated context.
@@ -130,6 +140,19 @@ class ContextInfo {
*/
bool excludesResource(Resource resource) => excludes(resource.path);
+ /**
+ * Return the first [ContextInfo] in [children] whose associated folder is or
+ * contains [path]. If there is no such [ContextInfo], return `null`.
+ */
+ ContextInfo findChildInfoFor(String path) {
+ for (ContextInfo info in children) {
+ if (info.folder.isOrContains(path)) {
+ return info;
+ }
+ }
+ return null;
+ }
+
/// Returns `true` if [path] should be ignored.
bool ignored(String path) => pathFilter.ignored(path);
@@ -181,8 +204,9 @@ abstract class ContextManager {
List<String> get includedPaths;
/**
- * Return a list containing all of the contexts contained in the given
- * [analysisRoot].
+ * Return a list of all of the contexts reachable from the given
+ * [analysisRoot] (the context associated with [analysisRoot] and all of its
+ * descendants).
*/
List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot);
@@ -297,12 +321,6 @@ class ContextManagerImpl implements ContextManager {
static const String PACKAGE_SPEC_NAME = '.packages';
/**
- * [ContextInfo] object for each included directory in the most
- * recent successful call to [setRoots].
- */
- Map<Folder, ContextInfo> _contexts = new HashMap<Folder, ContextInfo>();
-
- /**
* The [ResourceProvider] using which paths are converted into [Resource]s.
*/
final ResourceProvider resourceProvider;
@@ -374,18 +392,36 @@ class ContextManagerImpl implements ContextManager {
@override
List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot) {
List<AnalysisContext> contexts = <AnalysisContext>[];
- _contexts.forEach((Folder contextFolder, ContextInfo info) {
- if (analysisRoot.isOrContains(contextFolder.path)) {
- contexts.add(info.context);
+ ContextInfo innermostContainingInfo =
+ _getInnermostContextInfoFor(analysisRoot.path);
+ void addContextAndDescendants(ContextInfo info) {
+ contexts.add(info.context);
+ info.children.forEach(addContextAndDescendants);
+ }
+ if (innermostContainingInfo != null) {
+ if (analysisRoot == innermostContainingInfo.folder) {
+ addContextAndDescendants(innermostContainingInfo);
+ } else {
+ for (ContextInfo info in innermostContainingInfo.children) {
+ if (analysisRoot.isOrContains(info.folder.path)) {
+ addContextAndDescendants(info);
+ }
+ }
}
- });
+ }
return contexts;
}
/**
* For testing: get the [ContextInfo] object for the given [folder], if any.
*/
- ContextInfo getContextInfoFor(Folder folder) => _contexts[folder];
+ ContextInfo getContextInfoFor(Folder folder) {
+ ContextInfo info = _getInnermostContextInfoFor(folder.path);
+ if (folder == info.folder) {
+ return info;
+ }
+ return null;
+ }
@override
bool isInAnalysisRoot(String path) {
@@ -393,9 +429,9 @@ class ContextManagerImpl implements ContextManager {
if (_isExcluded(path)) {
return false;
}
- // check if in of the roots
- for (Folder root in _contexts.keys) {
- if (root.contains(path)) {
+ // check if in one of the roots
+ for (ContextInfo info in _rootInfo.children) {
+ if (info.folder.contains(path)) {
return true;
}
}
@@ -424,14 +460,15 @@ class ContextManagerImpl implements ContextManager {
@override
void refresh(List<Resource> roots) {
// Destroy old contexts
- List<Folder> contextFolders = _contexts.keys.toList();
+ List<ContextInfo> contextInfos = _rootInfo.descendants.toList();
if (roots == null) {
- contextFolders.forEach(_destroyContext);
+ contextInfos.forEach(_destroyContext);
} else {
roots.forEach((Resource resource) {
- contextFolders.forEach((Folder contextFolder) {
- if (resource is Folder && resource.isOrContains(contextFolder.path)) {
- _destroyContext(contextFolder);
+ contextInfos.forEach((ContextInfo contextInfo) {
+ if (resource is Folder &&
+ resource.isOrContains(contextInfo.folder.path)) {
+ _destroyContext(contextInfo);
}
});
});
@@ -464,7 +501,7 @@ class ContextManagerImpl implements ContextManager {
}
});
- List<Folder> contextFolders = _contexts.keys.toList();
+ List<ContextInfo> contextInfos = _rootInfo.descendants.toList();
// included
Set<Folder> includedFolders = new HashSet<Folder>();
for (int i = 0; i < includedPaths.length; i++) {
@@ -483,33 +520,33 @@ class ContextManagerImpl implements ContextManager {
List<String> oldExcludedPaths = this.excludedPaths;
this.excludedPaths = excludedPaths;
// destroy old contexts
- for (Folder contextFolder in contextFolders) {
+ for (ContextInfo contextInfo in contextInfos) {
bool isIncluded = includedFolders.any((folder) {
- return folder.isOrContains(contextFolder.path);
+ return folder.isOrContains(contextInfo.folder.path);
});
if (!isIncluded) {
- _destroyContext(contextFolder);
+ _destroyContext(contextInfo);
}
}
// Update package roots for existing contexts
- _contexts.forEach((Folder folder, ContextInfo info) {
- String newPackageRoot = normalizedPackageRoots[folder.path];
+ for (ContextInfo info in _rootInfo.descendants) {
+ String newPackageRoot = normalizedPackageRoots[info.folder.path];
if (info.packageRoot != newPackageRoot) {
info.packageRoot = newPackageRoot;
_recomputePackageUriResolver(info);
}
- });
+ }
// create new contexts
for (Folder includedFolder in includedFolders) {
- bool wasIncluded = contextFolders.any((folder) {
- return folder.isOrContains(includedFolder.path);
+ bool wasIncluded = contextInfos.any((info) {
+ return info.folder.isOrContains(includedFolder.path);
});
if (!wasIncluded) {
_createContexts(_rootInfo, includedFolder, false);
}
}
// remove newly excluded sources
- _contexts.forEach((folder, info) {
+ for (ContextInfo info in _rootInfo.descendants) {
// prepare excluded sources
Map<String, Source> excludedSources = new HashMap<String, Source>();
info.sources.forEach((String path, Source source) {
@@ -524,14 +561,15 @@ class ContextManagerImpl implements ContextManager {
info.sources.remove(path);
changeSet.removedSource(source);
});
- callbacks.applyChangesToContext(folder, changeSet);
- });
+ callbacks.applyChangesToContext(info.folder, changeSet);
+ }
// add previously excluded sources
- _contexts.forEach((folder, info) {
+ for (ContextInfo info in _rootInfo.descendants) {
ChangeSet changeSet = new ChangeSet();
- _addPreviouslyExcludedSources(info, changeSet, folder, oldExcludedPaths);
- callbacks.applyChangesToContext(folder, changeSet);
- });
+ _addPreviouslyExcludedSources(
+ info, changeSet, info.folder, oldExcludedPaths);
+ callbacks.applyChangesToContext(info.folder, changeSet);
+ }
}
/**
@@ -651,13 +689,13 @@ class ContextManagerImpl implements ContextManager {
* orphaned by this context being removed (no other context includes this
* file.)
*/
- List<String> _computeFlushedFiles(Folder folder) {
- AnalysisContext context = _contexts[folder].context;
+ List<String> _computeFlushedFiles(ContextInfo info) {
+ AnalysisContext context = info.context;
HashSet<String> flushedFiles = new HashSet<String>();
for (Source source in context.sources) {
flushedFiles.add(source.fullName);
}
- for (ContextInfo contextInfo in _contexts.values) {
+ for (ContextInfo contextInfo in _rootInfo.descendants) {
AnalysisContext contextN = contextInfo.context;
if (context != contextN) {
for (Source source in contextN.sources) {
@@ -752,7 +790,6 @@ class ContextManagerImpl implements ContextManager {
ContextInfo parent, Folder folder, File packagespecFile) {
ContextInfo info = new ContextInfo(
parent, folder, packagespecFile, normalizedPackageRoots[folder.path]);
- _contexts[folder] = info;
Map<String, YamlNode> options = analysisOptionsProvider.getOptions(folder);
processOptionsForContext(info, options);
info.changeSubscription = folder.changes.listen((WatchEvent event) {
@@ -841,14 +878,12 @@ class ContextManagerImpl implements ContextManager {
/**
* Clean up and destroy the context associated with the given folder.
*/
- void _destroyContext(Folder folder) {
- ContextInfo info = _contexts[folder];
+ void _destroyContext(ContextInfo info) {
info.changeSubscription.cancel();
_cancelDependencySubscriptions(info);
- callbacks.removeContext(folder, _computeFlushedFiles(folder));
+ callbacks.removeContext(info.folder, _computeFlushedFiles(info));
bool wasRemoved = info.parent.children.remove(info);
assert(wasRemoved);
- _contexts.remove(folder);
}
/**
@@ -887,6 +922,29 @@ class ContextManagerImpl implements ContextManager {
// adopted by newInfo now.
}
+ /**
+ * Return the [ContextInfo] for the "innermost" context whose associated
+ * folder is or contains the given path. ("innermost" refers to the nesting
+ * of contexts, so if there is a context for path /foo and a context for
+ * path /foo/bar, then the innermost context containing /foo/bar/baz.dart is
+ * the context for /foo/bar.)
+ *
+ * If no context contains the given path, `null` is returned.
+ */
+ ContextInfo _getInnermostContextInfoFor(String path) {
+ ContextInfo info = _rootInfo.findChildInfoFor(path);
+ if (info == null) {
+ return null;
+ }
+ while (true) {
+ ContextInfo childInfo = info.findChildInfoFor(path);
+ if (childInfo == null) {
+ return info;
+ }
+ info = childInfo;
+ }
+ }
+
void _handleWatchEvent(Folder folder, ContextInfo info, WatchEvent event) {
// TODO(brianwilkerson) If a file is explicitly included in one context
// but implicitly referenced in another context, we will only send a
@@ -1070,7 +1128,7 @@ class ContextManagerImpl implements ContextManager {
*/
void _mergeContext(ContextInfo info) {
// destroy the context
- _destroyContext(info.folder);
+ _destroyContext(info);
// add files to the parent context
ContextInfo parentInfo = info.parent;
if (parentInfo != null) {
« no previous file with comments | « pkg/analysis_server/lib/src/analysis_server.dart ('k') | pkg/analysis_server/test/context_manager_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698