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

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

Issue 456893002: Support for excluded files/folders. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/analysis_server/test/context_manager_test.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 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 9
10 import 'package:analysis_server/src/package_map_provider.dart'; 10 import 'package:analysis_server/src/package_map_provider.dart';
(...skipping 25 matching lines...) Expand all
36 * The [ResourceProvider] using which paths are converted into [Resource]s. 36 * The [ResourceProvider] using which paths are converted into [Resource]s.
37 */ 37 */
38 final ResourceProvider resourceProvider; 38 final ResourceProvider resourceProvider;
39 39
40 /** 40 /**
41 * The context used to work with file system paths. 41 * The context used to work with file system paths.
42 */ 42 */
43 pathos.Context pathContext; 43 pathos.Context pathContext;
44 44
45 /** 45 /**
46 * A list of excluded paths - folders and files.
47 */
48 List<String> excludedPaths = <String>[];
49
50 /**
46 * Provider which is used to determine the mapping from package name to 51 * Provider which is used to determine the mapping from package name to
47 * package folder. 52 * package folder.
48 */ 53 */
49 final PackageMapProvider packageMapProvider; 54 final PackageMapProvider packageMapProvider;
50 55
51 ContextManager(this.resourceProvider, this.packageMapProvider) { 56 ContextManager(this.resourceProvider, this.packageMapProvider) {
52 pathContext = resourceProvider.pathContext; 57 pathContext = resourceProvider.pathContext;
53 } 58 }
54 59
55 /** 60 /**
56 * Called when a new context needs to be created. 61 * Called when a new context needs to be created.
57 */ 62 */
58 void addContext(Folder folder, Map<String, List<Folder>> packageMap); 63 void addContext(Folder folder, Map<String, List<Folder>> packageMap);
59 64
60 /** 65 /**
61 * Called when the set of files associated with a context have changed (or 66 * Called when the set of files associated with a context have changed (or
62 * some of those files have been modified). [changeSet] is the set of 67 * some of those files have been modified). [changeSet] is the set of
63 * changes that need to be applied to the context. 68 * changes that need to be applied to the context.
64 */ 69 */
65 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet); 70 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet);
66 71
67 /** 72 /**
68 * Returns `true` if the given absolute [path] is in one of the current 73 * Returns `true` if the given absolute [path] is in one of the current
69 * root folders and is not excluded. 74 * root folders and is not excluded.
70 */ 75 */
71 bool isInAnalysisRoot(String path) { 76 bool isInAnalysisRoot(String path) {
72 // TODO(scheglov) check for excluded paths 77 // check if excluded
78 if (_isExcluded(path)) {
79 return false;
80 }
81 // check if in of the roots
73 for (Folder root in _contexts.keys) { 82 for (Folder root in _contexts.keys) {
74 if (root.contains(path)) { 83 if (root.contains(path)) {
75 return true; 84 return true;
76 } 85 }
77 } 86 }
87 // no
78 return false; 88 return false;
79 } 89 }
80 90
81 /** 91 /**
82 * Remove the context associated with the given [folder]. 92 * Remove the context associated with the given [folder].
83 */ 93 */
84 void removeContext(Folder folder); 94 void removeContext(Folder folder);
85 95
86 /** 96 /**
87 * Change the set of paths which should be used as starting points to 97 * Change the set of paths which should be used as starting points to
88 * determine the context directories. 98 * determine the context directories.
89 */ 99 */
90 void setRoots(List<String> includedPaths, List<String> excludedPaths) { 100 void setRoots(List<String> includedPaths, List<String> excludedPaths) {
91 List<Folder> contextFolders = _contexts.keys.toList(); 101 List<Folder> contextFolders = _contexts.keys.toList();
92 // included 102 // included
93 Set<Folder> includedFolders = new HashSet<Folder>(); 103 Set<Folder> includedFolders = new HashSet<Folder>();
94 for (int i = 0; i < includedPaths.length; i++) { 104 for (int i = 0; i < includedPaths.length; i++) {
95 String path = includedPaths[i]; 105 String path = includedPaths[i];
96 Resource resource = resourceProvider.getResource(path); 106 Resource resource = resourceProvider.getResource(path);
97 if (resource is Folder) { 107 if (resource is Folder) {
98 includedFolders.add(resource); 108 includedFolders.add(resource);
99 } else { 109 } else {
100 // TODO(scheglov) implemented separate files analysis 110 // TODO(scheglov) implemented separate files analysis
101 throw new UnimplementedError( 111 throw new UnimplementedError(
102 '$path is not a folder. ' 112 '$path is not a folder. '
103 'Only support for folder analysis is implemented currently.'); 113 'Only support for folder analysis is implemented currently.');
104 } 114 }
105 } 115 }
106 // excluded 116 // excluded
107 // TODO(scheglov) remove when implemented 117 List<String> oldExcludedPaths = this.excludedPaths;
108 if (excludedPaths.isNotEmpty) { 118 this.excludedPaths = excludedPaths;
109 throw new UnimplementedError('Excluded paths are not supported yet');
110 }
111 Set<Folder> excludedFolders = new HashSet<Folder>();
112 // destroy old contexts 119 // destroy old contexts
113 for (Folder contextFolder in contextFolders) { 120 for (Folder contextFolder in contextFolders) {
114 bool isIncluded = includedFolders.any((folder) { 121 bool isIncluded = includedFolders.any((folder) {
115 return folder.contains(contextFolder.path); 122 return folder.isOrContains(contextFolder.path);
116 }); 123 });
117 if (!isIncluded) { 124 if (!isIncluded) {
118 _destroyContext(contextFolder); 125 _destroyContext(contextFolder);
119 } 126 }
120 } 127 }
121 // create new contexts 128 // create new contexts
122 for (Folder includedFolder in includedFolders) { 129 for (Folder includedFolder in includedFolders) {
123 bool wasIncluded = contextFolders.any((folder) { 130 bool wasIncluded = contextFolders.any((folder) {
124 return folder.contains(includedFolder.path); 131 return folder.isOrContains(includedFolder.path);
125 }); 132 });
126 if (!wasIncluded) { 133 if (!wasIncluded) {
127 _createContexts(includedFolder, false); 134 _createContexts(includedFolder, false);
128 } 135 }
129 } 136 }
137 // remove newly excluded sources
138 _contexts.forEach((folder, info) {
139 // prepare excluded sources
140 Map<String, Source> excludedSources = new HashMap<String, Source>();
141 info.sources.forEach((String path, Source source) {
142 if (_isExcludedBy(excludedPaths, path) &&
143 !_isExcludedBy(oldExcludedPaths, path)) {
144 excludedSources[path] = source;
145 }
146 });
147 // apply exclusion
148 ChangeSet changeSet = new ChangeSet();
149 excludedSources.forEach((String path, Source source) {
150 info.sources.remove(path);
151 changeSet.removedSource(source);
152 });
153 applyChangesToContext(folder, changeSet);
154 });
155 // add previously excluded sources
156 _contexts.forEach((folder, info) {
157 ChangeSet changeSet = new ChangeSet();
Brian Wilkerson 2014/08/08 19:19:35 Can we merge this into the loop above so that each
158 _addPreviouslyExcludedSources(info, changeSet, folder, oldExcludedPaths);
159 applyChangesToContext(folder, changeSet);
160 });
130 } 161 }
131 162
132 /** 163 /**
133 * Called when the package map for a context has changed. 164 * Called when the package map for a context has changed.
134 */ 165 */
135 void updateContextPackageMap(Folder contextFolder, Map<String, 166 void updateContextPackageMap(Folder contextFolder, Map<String,
136 List<Folder>> packageMap); 167 List<Folder>> packageMap);
137 168
138 /** 169 /**
170 * Resursively adds all Dart and HTML files to the [changeSet].
171 */
172 void _addPreviouslyExcludedSources(_ContextInfo info, ChangeSet changeSet,
173 Folder folder, List<String> oldExcludedPaths) {
174 if (info.excludesResource(folder)) {
175 return;
176 }
177 List<Resource> children = folder.getChildren();
178 for (Resource child in children) {
179 String path = child.path;
180 // ignore if wasn't previously excluded
181 bool wasExcluded =
182 _isExcludedBy(oldExcludedPaths, path) &&
183 !_isExcludedBy(excludedPaths, path);
184 if (!wasExcluded) {
185 continue;
186 }
187 // add files, recurse into folders
188 if (child is File) {
189 if (_shouldFileBeAnalyzed(child)) {
190 Source source = child.createSource();
191 changeSet.addedSource(source);
192 info.sources[path] = source;
193 }
194 } else if (child is Folder) {
195 if (child.shortName == 'packages') {
Brian Wilkerson 2014/08/08 19:19:35 The string 'packages' should be a constant. This
196 // TODO(paulberry): perhaps we should only skip packages dirs if
197 // there is a pubspec.yaml?
198 continue;
199 }
200 _addPreviouslyExcludedSources(info, changeSet, child, oldExcludedPaths);
201 }
202 }
203 }
204
205 /**
206 * Resursively adds all Dart and HTML files to the [changeSet].
207 */
208 void _addSourceFiles(ChangeSet changeSet, Folder folder, _ContextInfo info) {
209 if (info.excludesResource(folder)) {
210 return;
211 }
212 List<Resource> children = folder.getChildren();
213 for (Resource child in children) {
214 String path = child.path;
215 // ignore excluded files or folders
216 if (_isExcluded(path)) {
217 continue;
218 }
219 // add files, recurse into folders
220 if (child is File) {
221 if (_shouldFileBeAnalyzed(child)) {
222 Source source = child.createSource();
223 changeSet.addedSource(source);
224 info.sources[path] = source;
225 }
226 } else if (child is Folder) {
227 if (child.shortName == 'packages') {
228 // TODO(paulberry): perhaps we should only skip packages dirs if
229 // there is a pubspec.yaml?
230 continue;
231 }
232 _addSourceFiles(changeSet, child, info);
233 }
234 }
235 }
236
237 /**
139 * Create a new empty context associated with [folder]. 238 * Create a new empty context associated with [folder].
140 */ 239 */
141 _ContextInfo _createContext(Folder folder, List<_ContextInfo> children) { 240 _ContextInfo _createContext(Folder folder, List<_ContextInfo> children) {
142 _ContextInfo info = new _ContextInfo(folder, children); 241 _ContextInfo info = new _ContextInfo(folder, children);
143 _contexts[folder] = info; 242 _contexts[folder] = info;
144 info.changeSubscription = folder.changes.listen((WatchEvent event) { 243 info.changeSubscription = folder.changes.listen((WatchEvent event) {
145 _handleWatchEvent(folder, info, event); 244 _handleWatchEvent(folder, info, event);
146 }); 245 });
147 PackageMapInfo packageMapInfo = 246 PackageMapInfo packageMapInfo =
148 packageMapProvider.computePackageMap(folder); 247 packageMapProvider.computePackageMap(folder);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 extractedSources.forEach((path, source) { 342 extractedSources.forEach((path, source) {
244 oldInfo.sources.remove(path); 343 oldInfo.sources.remove(path);
245 changeSet.removedSource(source); 344 changeSet.removedSource(source);
246 }); 345 });
247 applyChangesToContext(oldInfo.folder, changeSet); 346 applyChangesToContext(oldInfo.folder, changeSet);
248 } 347 }
249 } 348 }
250 349
251 void _handleWatchEvent(Folder folder, _ContextInfo info, WatchEvent event) { 350 void _handleWatchEvent(Folder folder, _ContextInfo info, WatchEvent event) {
252 String path = event.path; 351 String path = event.path;
253 // maybe excluded, so other context will handle it 352 // maybe excluded globally
353 if (_isExcluded(path)) {
354 return;
355 }
356 // maybe excluded from the context, so other context will handle it
254 if (info.excludes(path)) { 357 if (info.excludes(path)) {
255 return; 358 return;
256 } 359 }
257 // handle the change 360 // handle the change
258 switch (event.type) { 361 switch (event.type) {
259 case ChangeType.ADD: 362 case ChangeType.ADD:
260 if (_isInPackagesDir(path, folder)) { 363 if (_isInPackagesDir(path, folder)) {
261 // TODO(paulberry): perhaps we should only skip packages dirs if 364 // TODO(paulberry): perhaps we should only skip packages dirs if
262 // there is a pubspec.yaml? 365 // there is a pubspec.yaml?
263 break; 366 break;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 // while we're rerunning "pub list", since any analysis we complete while 415 // while we're rerunning "pub list", since any analysis we complete while
313 // "pub list" is in progress is just going to get thrown away anyhow. 416 // "pub list" is in progress is just going to get thrown away anyhow.
314 PackageMapInfo packageMapInfo = 417 PackageMapInfo packageMapInfo =
315 packageMapProvider.computePackageMap(folder); 418 packageMapProvider.computePackageMap(folder);
316 info.packageMapDependencies = packageMapInfo.dependencies; 419 info.packageMapDependencies = packageMapInfo.dependencies;
317 updateContextPackageMap(folder, packageMapInfo.packageMap); 420 updateContextPackageMap(folder, packageMapInfo.packageMap);
318 } 421 }
319 } 422 }
320 423
321 /** 424 /**
425 * Returns `true` if the given [path] is excluded by [excludedPaths].
426 */
427 bool _isExcluded(String path) {
428 return _isExcludedBy(excludedPaths, path);
429 }
430
431 /**
432 * Returns `true` if the given [path] is excluded by [excludedPaths].
433 */
434 bool _isExcludedBy(List<String> excludedPaths, String path) {
435 return excludedPaths.any((excludedPath) {
436 if (pathContext.isWithin(excludedPath, path)) {
437 return true;
438 }
439 return path == excludedPath;
440 });
441 }
442
443 /**
322 * Determine if the path from [folder] to [path] contains a 'packages' 444 * Determine if the path from [folder] to [path] contains a 'packages'
323 * directory. 445 * directory.
324 */ 446 */
325 bool _isInPackagesDir(String path, Folder folder) { 447 bool _isInPackagesDir(String path, Folder folder) {
326 String relativePath = pathContext.relative(path, from: folder.path); 448 String relativePath = pathContext.relative(path, from: folder.path);
327 List<String> pathParts = pathContext.split(relativePath); 449 List<String> pathParts = pathContext.split(relativePath);
328 for (int i = 0; i < pathParts.length - 1; i++) { 450 for (int i = 0; i < pathParts.length - 1; i++) {
329 if (pathParts[i] == 'packages') { 451 if (pathParts[i] == 'packages') {
330 return true; 452 return true;
331 } 453 }
(...skipping 20 matching lines...) Expand all
352 parentInfo.children.remove(info); 474 parentInfo.children.remove(info);
353 ChangeSet changeSet = new ChangeSet(); 475 ChangeSet changeSet = new ChangeSet();
354 info.sources.forEach((path, source) { 476 info.sources.forEach((path, source) {
355 parentInfo.sources[path] = source; 477 parentInfo.sources[path] = source;
356 changeSet.addedSource(source); 478 changeSet.addedSource(source);
357 }); 479 });
358 applyChangesToContext(parentInfo.folder, changeSet); 480 applyChangesToContext(parentInfo.folder, changeSet);
359 } 481 }
360 } 482 }
361 483
362 /**
363 * Resursively adds all Dart and HTML files to the [changeSet].
364 */
365 static void _addSourceFiles(ChangeSet changeSet, Folder folder,
366 _ContextInfo info) {
367 if (info.excludesResource(folder)) {
368 return;
369 }
370 List<Resource> children = folder.getChildren();
371 for (Resource child in children) {
372 if (child is File) {
373 if (_shouldFileBeAnalyzed(child)) {
374 Source source = child.createSource();
375 changeSet.addedSource(source);
376 info.sources[child.path] = source;
377 }
378 } else if (child is Folder) {
379 if (child.shortName == 'packages') {
380 // TODO(paulberry): perhaps we should only skip packages dirs if
381 // there is a pubspec.yaml?
382 continue;
383 }
384 _addSourceFiles(changeSet, child, info);
385 }
386 }
387 }
388
389 static bool _shouldFileBeAnalyzed(File file) { 484 static bool _shouldFileBeAnalyzed(File file) {
390 if (!(AnalysisEngine.isDartFileName(file.path) || 485 if (!(AnalysisEngine.isDartFileName(file.path) ||
391 AnalysisEngine.isHtmlFileName(file.path))) { 486 AnalysisEngine.isHtmlFileName(file.path))) {
392 return false; 487 return false;
393 } 488 }
394 // Emacs creates dummy links to track the fact that a file is open for 489 // Emacs creates dummy links to track the fact that a file is open for
395 // editing and has unsaved changes (e.g. having unsaved changes to 490 // editing and has unsaved changes (e.g. having unsaved changes to
396 // 'foo.dart' causes a link '.#foo.dart' to be created, which points to the 491 // 'foo.dart' causes a link '.#foo.dart' to be created, which points to the
397 // non-existent file 'username@hostname.pid'. To avoid these dummy links 492 // non-existent file 'username@hostname.pid'. To avoid these dummy links
398 // causing the analyzer to thrash, just ignore links to non-existent files. 493 // causing the analyzer to thrash, just ignore links to non-existent files.
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 return excludes(resource.path); 565 return excludes(resource.path);
471 } 566 }
472 567
473 /** 568 /**
474 * Returns `true` if [path] is the pubspec file of this context. 569 * Returns `true` if [path] is the pubspec file of this context.
475 */ 570 */
476 bool isPubspec(String path) { 571 bool isPubspec(String path) {
477 return path == pubspecPath; 572 return path == pubspecPath;
478 } 573 }
479 } 574 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_server/test/context_manager_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698