OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 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 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 | 103 |
104 /** | 104 /** |
105 * Create the virtual [ContextInfo] which acts as an ancestor to all other | 105 * Create the virtual [ContextInfo] which acts as an ancestor to all other |
106 * [ContextInfo]s. | 106 * [ContextInfo]s. |
107 */ | 107 */ |
108 ContextInfo._root() | 108 ContextInfo._root() |
109 : folder = null, | 109 : folder = null, |
110 pathFilter = null; | 110 pathFilter = null; |
111 | 111 |
112 /** | 112 /** |
| 113 * Iterate through all [children] and their children, recursively. |
| 114 */ |
| 115 Iterable<ContextInfo> get descendants sync* { |
| 116 for (ContextInfo child in children) { |
| 117 yield child; |
| 118 yield* child.descendants; |
| 119 } |
| 120 } |
| 121 |
| 122 /** |
113 * Returns `true` if this is a "top level" context, meaning that the folder | 123 * Returns `true` if this is a "top level" context, meaning that the folder |
114 * associated with it is not contained within any other folders that have an | 124 * associated with it is not contained within any other folders that have an |
115 * associated context. | 125 * associated context. |
116 */ | 126 */ |
117 bool get isTopLevel => parent.parent == null; | 127 bool get isTopLevel => parent.parent == null; |
118 | 128 |
119 /** | 129 /** |
120 * Returns `true` if [path] is excluded, as it is in one of the children. | 130 * Returns `true` if [path] is excluded, as it is in one of the children. |
121 */ | 131 */ |
122 bool excludes(String path) { | 132 bool excludes(String path) { |
123 return children.any((child) { | 133 return children.any((child) { |
124 return child.folder.contains(path); | 134 return child.folder.contains(path); |
125 }); | 135 }); |
126 } | 136 } |
127 | 137 |
128 /** | 138 /** |
129 * Returns `true` if [resource] is excluded, as it is in one of the children. | 139 * Returns `true` if [resource] is excluded, as it is in one of the children. |
130 */ | 140 */ |
131 bool excludesResource(Resource resource) => excludes(resource.path); | 141 bool excludesResource(Resource resource) => excludes(resource.path); |
132 | 142 |
| 143 /** |
| 144 * Return the first [ContextInfo] in [children] whose associated folder is or |
| 145 * contains [path]. If there is no such [ContextInfo], return `null`. |
| 146 */ |
| 147 ContextInfo findChildInfoFor(String path) { |
| 148 for (ContextInfo info in children) { |
| 149 if (info.folder.isOrContains(path)) { |
| 150 return info; |
| 151 } |
| 152 } |
| 153 return null; |
| 154 } |
| 155 |
133 /// Returns `true` if [path] should be ignored. | 156 /// Returns `true` if [path] should be ignored. |
134 bool ignored(String path) => pathFilter.ignored(path); | 157 bool ignored(String path) => pathFilter.ignored(path); |
135 | 158 |
136 /** | 159 /** |
137 * Returns `true` if [path] is the package description file for this context | 160 * Returns `true` if [path] is the package description file for this context |
138 * (pubspec.yaml or .packages). | 161 * (pubspec.yaml or .packages). |
139 */ | 162 */ |
140 bool isPathToPackageDescription(String path) => | 163 bool isPathToPackageDescription(String path) => |
141 path == packageDescriptionPath; | 164 path == packageDescriptionPath; |
142 } | 165 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 */ | 197 */ |
175 List<String> get excludedPaths; | 198 List<String> get excludedPaths; |
176 | 199 |
177 /** | 200 /** |
178 * Return the list of included paths (folders and files) most recently passed | 201 * Return the list of included paths (folders and files) most recently passed |
179 * to [setRoots]. | 202 * to [setRoots]. |
180 */ | 203 */ |
181 List<String> get includedPaths; | 204 List<String> get includedPaths; |
182 | 205 |
183 /** | 206 /** |
184 * Return a list containing all of the contexts contained in the given | 207 * Return a list of all of the contexts reachable from the given |
185 * [analysisRoot]. | 208 * [analysisRoot] (the context associated with [analysisRoot] and all of its |
| 209 * descendants). |
186 */ | 210 */ |
187 List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot); | 211 List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot); |
188 | 212 |
189 /** | 213 /** |
190 * Return `true` if the given absolute [path] is in one of the current | 214 * Return `true` if the given absolute [path] is in one of the current |
191 * root folders and is not excluded. | 215 * root folders and is not excluded. |
192 */ | 216 */ |
193 bool isInAnalysisRoot(String path); | 217 bool isInAnalysisRoot(String path); |
194 | 218 |
195 /** | 219 /** |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 * File name of pubspec files. | 314 * File name of pubspec files. |
291 */ | 315 */ |
292 static const String PUBSPEC_NAME = 'pubspec.yaml'; | 316 static const String PUBSPEC_NAME = 'pubspec.yaml'; |
293 | 317 |
294 /** | 318 /** |
295 * File name of package spec files. | 319 * File name of package spec files. |
296 */ | 320 */ |
297 static const String PACKAGE_SPEC_NAME = '.packages'; | 321 static const String PACKAGE_SPEC_NAME = '.packages'; |
298 | 322 |
299 /** | 323 /** |
300 * [ContextInfo] object for each included directory in the most | |
301 * recent successful call to [setRoots]. | |
302 */ | |
303 Map<Folder, ContextInfo> _contexts = new HashMap<Folder, ContextInfo>(); | |
304 | |
305 /** | |
306 * The [ResourceProvider] using which paths are converted into [Resource]s. | 324 * The [ResourceProvider] using which paths are converted into [Resource]s. |
307 */ | 325 */ |
308 final ResourceProvider resourceProvider; | 326 final ResourceProvider resourceProvider; |
309 | 327 |
310 /** | 328 /** |
311 * The context used to work with file system paths. | 329 * The context used to work with file system paths. |
312 */ | 330 */ |
313 pathos.Context pathContext; | 331 pathos.Context pathContext; |
314 | 332 |
315 /** | 333 /** |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 final ContextInfo _rootInfo = new ContextInfo._root(); | 385 final ContextInfo _rootInfo = new ContextInfo._root(); |
368 | 386 |
369 ContextManagerImpl(this.resourceProvider, this.packageResolverProvider, | 387 ContextManagerImpl(this.resourceProvider, this.packageResolverProvider, |
370 this._packageMapProvider, this._instrumentationService) { | 388 this._packageMapProvider, this._instrumentationService) { |
371 pathContext = resourceProvider.pathContext; | 389 pathContext = resourceProvider.pathContext; |
372 } | 390 } |
373 | 391 |
374 @override | 392 @override |
375 List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot) { | 393 List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot) { |
376 List<AnalysisContext> contexts = <AnalysisContext>[]; | 394 List<AnalysisContext> contexts = <AnalysisContext>[]; |
377 _contexts.forEach((Folder contextFolder, ContextInfo info) { | 395 ContextInfo innermostContainingInfo = |
378 if (analysisRoot.isOrContains(contextFolder.path)) { | 396 _getInnermostContextInfoFor(analysisRoot.path); |
379 contexts.add(info.context); | 397 void addContextAndDescendants(ContextInfo info) { |
| 398 contexts.add(info.context); |
| 399 info.children.forEach(addContextAndDescendants); |
| 400 } |
| 401 if (innermostContainingInfo != null) { |
| 402 if (analysisRoot == innermostContainingInfo.folder) { |
| 403 addContextAndDescendants(innermostContainingInfo); |
| 404 } else { |
| 405 for (ContextInfo info in innermostContainingInfo.children) { |
| 406 if (analysisRoot.isOrContains(info.folder.path)) { |
| 407 addContextAndDescendants(info); |
| 408 } |
| 409 } |
380 } | 410 } |
381 }); | 411 } |
382 return contexts; | 412 return contexts; |
383 } | 413 } |
384 | 414 |
385 /** | 415 /** |
386 * For testing: get the [ContextInfo] object for the given [folder], if any. | 416 * For testing: get the [ContextInfo] object for the given [folder], if any. |
387 */ | 417 */ |
388 ContextInfo getContextInfoFor(Folder folder) => _contexts[folder]; | 418 ContextInfo getContextInfoFor(Folder folder) { |
| 419 ContextInfo info = _getInnermostContextInfoFor(folder.path); |
| 420 if (folder == info.folder) { |
| 421 return info; |
| 422 } |
| 423 return null; |
| 424 } |
389 | 425 |
390 @override | 426 @override |
391 bool isInAnalysisRoot(String path) { | 427 bool isInAnalysisRoot(String path) { |
392 // check if excluded | 428 // check if excluded |
393 if (_isExcluded(path)) { | 429 if (_isExcluded(path)) { |
394 return false; | 430 return false; |
395 } | 431 } |
396 // check if in of the roots | 432 // check if in one of the roots |
397 for (Folder root in _contexts.keys) { | 433 for (ContextInfo info in _rootInfo.children) { |
398 if (root.contains(path)) { | 434 if (info.folder.contains(path)) { |
399 return true; | 435 return true; |
400 } | 436 } |
401 } | 437 } |
402 // no | 438 // no |
403 return false; | 439 return false; |
404 } | 440 } |
405 | 441 |
406 /** | 442 /** |
407 * Process [options] for the context having info [info]. | 443 * Process [options] for the context having info [info]. |
408 */ | 444 */ |
409 void processOptionsForContext( | 445 void processOptionsForContext( |
410 ContextInfo info, Map<String, YamlNode> options) { | 446 ContextInfo info, Map<String, YamlNode> options) { |
411 YamlMap analyzer = options['analyzer']; | 447 YamlMap analyzer = options['analyzer']; |
412 if (analyzer == null) { | 448 if (analyzer == null) { |
413 // No options for analyzer. | 449 // No options for analyzer. |
414 return; | 450 return; |
415 } | 451 } |
416 | 452 |
417 // Set ignore patterns. | 453 // Set ignore patterns. |
418 YamlList exclude = analyzer['exclude']; | 454 YamlList exclude = analyzer['exclude']; |
419 if (exclude != null) { | 455 if (exclude != null) { |
420 setIgnorePatternsForContext(info, exclude); | 456 setIgnorePatternsForContext(info, exclude); |
421 } | 457 } |
422 } | 458 } |
423 | 459 |
424 @override | 460 @override |
425 void refresh(List<Resource> roots) { | 461 void refresh(List<Resource> roots) { |
426 // Destroy old contexts | 462 // Destroy old contexts |
427 List<Folder> contextFolders = _contexts.keys.toList(); | 463 List<ContextInfo> contextInfos = _rootInfo.descendants.toList(); |
428 if (roots == null) { | 464 if (roots == null) { |
429 contextFolders.forEach(_destroyContext); | 465 contextInfos.forEach(_destroyContext); |
430 } else { | 466 } else { |
431 roots.forEach((Resource resource) { | 467 roots.forEach((Resource resource) { |
432 contextFolders.forEach((Folder contextFolder) { | 468 contextInfos.forEach((ContextInfo contextInfo) { |
433 if (resource is Folder && resource.isOrContains(contextFolder.path)) { | 469 if (resource is Folder && |
434 _destroyContext(contextFolder); | 470 resource.isOrContains(contextInfo.folder.path)) { |
| 471 _destroyContext(contextInfo); |
435 } | 472 } |
436 }); | 473 }); |
437 }); | 474 }); |
438 } | 475 } |
439 | 476 |
440 // Rebuild contexts based on the data last sent to setRoots(). | 477 // Rebuild contexts based on the data last sent to setRoots(). |
441 setRoots(includedPaths, excludedPaths, packageRoots); | 478 setRoots(includedPaths, excludedPaths, packageRoots); |
442 } | 479 } |
443 | 480 |
444 /** | 481 /** |
(...skipping 12 matching lines...) Expand all Loading... |
457 // Normalize all package root sources by mapping them to folders on the | 494 // Normalize all package root sources by mapping them to folders on the |
458 // filesystem. Ignore any package root sources that aren't folders. | 495 // filesystem. Ignore any package root sources that aren't folders. |
459 normalizedPackageRoots = <String, String>{}; | 496 normalizedPackageRoots = <String, String>{}; |
460 packageRoots.forEach((String sourcePath, String targetPath) { | 497 packageRoots.forEach((String sourcePath, String targetPath) { |
461 Resource resource = resourceProvider.getResource(sourcePath); | 498 Resource resource = resourceProvider.getResource(sourcePath); |
462 if (resource is Folder) { | 499 if (resource is Folder) { |
463 normalizedPackageRoots[resource.path] = targetPath; | 500 normalizedPackageRoots[resource.path] = targetPath; |
464 } | 501 } |
465 }); | 502 }); |
466 | 503 |
467 List<Folder> contextFolders = _contexts.keys.toList(); | 504 List<ContextInfo> contextInfos = _rootInfo.descendants.toList(); |
468 // included | 505 // included |
469 Set<Folder> includedFolders = new HashSet<Folder>(); | 506 Set<Folder> includedFolders = new HashSet<Folder>(); |
470 for (int i = 0; i < includedPaths.length; i++) { | 507 for (int i = 0; i < includedPaths.length; i++) { |
471 String path = includedPaths[i]; | 508 String path = includedPaths[i]; |
472 Resource resource = resourceProvider.getResource(path); | 509 Resource resource = resourceProvider.getResource(path); |
473 if (resource is Folder) { | 510 if (resource is Folder) { |
474 includedFolders.add(resource); | 511 includedFolders.add(resource); |
475 } else { | 512 } else { |
476 // TODO(scheglov) implemented separate files analysis | 513 // TODO(scheglov) implemented separate files analysis |
477 throw new UnimplementedError('$path is not a folder. ' | 514 throw new UnimplementedError('$path is not a folder. ' |
478 'Only support for folder analysis is implemented currently.'); | 515 'Only support for folder analysis is implemented currently.'); |
479 } | 516 } |
480 } | 517 } |
481 this.includedPaths = includedPaths; | 518 this.includedPaths = includedPaths; |
482 // excluded | 519 // excluded |
483 List<String> oldExcludedPaths = this.excludedPaths; | 520 List<String> oldExcludedPaths = this.excludedPaths; |
484 this.excludedPaths = excludedPaths; | 521 this.excludedPaths = excludedPaths; |
485 // destroy old contexts | 522 // destroy old contexts |
486 for (Folder contextFolder in contextFolders) { | 523 for (ContextInfo contextInfo in contextInfos) { |
487 bool isIncluded = includedFolders.any((folder) { | 524 bool isIncluded = includedFolders.any((folder) { |
488 return folder.isOrContains(contextFolder.path); | 525 return folder.isOrContains(contextInfo.folder.path); |
489 }); | 526 }); |
490 if (!isIncluded) { | 527 if (!isIncluded) { |
491 _destroyContext(contextFolder); | 528 _destroyContext(contextInfo); |
492 } | 529 } |
493 } | 530 } |
494 // Update package roots for existing contexts | 531 // Update package roots for existing contexts |
495 _contexts.forEach((Folder folder, ContextInfo info) { | 532 for (ContextInfo info in _rootInfo.descendants) { |
496 String newPackageRoot = normalizedPackageRoots[folder.path]; | 533 String newPackageRoot = normalizedPackageRoots[info.folder.path]; |
497 if (info.packageRoot != newPackageRoot) { | 534 if (info.packageRoot != newPackageRoot) { |
498 info.packageRoot = newPackageRoot; | 535 info.packageRoot = newPackageRoot; |
499 _recomputePackageUriResolver(info); | 536 _recomputePackageUriResolver(info); |
500 } | 537 } |
501 }); | 538 } |
502 // create new contexts | 539 // create new contexts |
503 for (Folder includedFolder in includedFolders) { | 540 for (Folder includedFolder in includedFolders) { |
504 bool wasIncluded = contextFolders.any((folder) { | 541 bool wasIncluded = contextInfos.any((info) { |
505 return folder.isOrContains(includedFolder.path); | 542 return info.folder.isOrContains(includedFolder.path); |
506 }); | 543 }); |
507 if (!wasIncluded) { | 544 if (!wasIncluded) { |
508 _createContexts(_rootInfo, includedFolder, false); | 545 _createContexts(_rootInfo, includedFolder, false); |
509 } | 546 } |
510 } | 547 } |
511 // remove newly excluded sources | 548 // remove newly excluded sources |
512 _contexts.forEach((folder, info) { | 549 for (ContextInfo info in _rootInfo.descendants) { |
513 // prepare excluded sources | 550 // prepare excluded sources |
514 Map<String, Source> excludedSources = new HashMap<String, Source>(); | 551 Map<String, Source> excludedSources = new HashMap<String, Source>(); |
515 info.sources.forEach((String path, Source source) { | 552 info.sources.forEach((String path, Source source) { |
516 if (_isExcludedBy(excludedPaths, path) && | 553 if (_isExcludedBy(excludedPaths, path) && |
517 !_isExcludedBy(oldExcludedPaths, path)) { | 554 !_isExcludedBy(oldExcludedPaths, path)) { |
518 excludedSources[path] = source; | 555 excludedSources[path] = source; |
519 } | 556 } |
520 }); | 557 }); |
521 // apply exclusion | 558 // apply exclusion |
522 ChangeSet changeSet = new ChangeSet(); | 559 ChangeSet changeSet = new ChangeSet(); |
523 excludedSources.forEach((String path, Source source) { | 560 excludedSources.forEach((String path, Source source) { |
524 info.sources.remove(path); | 561 info.sources.remove(path); |
525 changeSet.removedSource(source); | 562 changeSet.removedSource(source); |
526 }); | 563 }); |
527 callbacks.applyChangesToContext(folder, changeSet); | 564 callbacks.applyChangesToContext(info.folder, changeSet); |
528 }); | 565 } |
529 // add previously excluded sources | 566 // add previously excluded sources |
530 _contexts.forEach((folder, info) { | 567 for (ContextInfo info in _rootInfo.descendants) { |
531 ChangeSet changeSet = new ChangeSet(); | 568 ChangeSet changeSet = new ChangeSet(); |
532 _addPreviouslyExcludedSources(info, changeSet, folder, oldExcludedPaths); | 569 _addPreviouslyExcludedSources( |
533 callbacks.applyChangesToContext(folder, changeSet); | 570 info, changeSet, info.folder, oldExcludedPaths); |
534 }); | 571 callbacks.applyChangesToContext(info.folder, changeSet); |
| 572 } |
535 } | 573 } |
536 | 574 |
537 /** | 575 /** |
538 * Resursively adds all Dart and HTML files to the [changeSet]. | 576 * Resursively adds all Dart and HTML files to the [changeSet]. |
539 */ | 577 */ |
540 void _addPreviouslyExcludedSources(ContextInfo info, ChangeSet changeSet, | 578 void _addPreviouslyExcludedSources(ContextInfo info, ChangeSet changeSet, |
541 Folder folder, List<String> oldExcludedPaths) { | 579 Folder folder, List<String> oldExcludedPaths) { |
542 if (info.excludesResource(folder)) { | 580 if (info.excludesResource(folder)) { |
543 return; | 581 return; |
544 } | 582 } |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 } | 682 } |
645 } | 683 } |
646 } | 684 } |
647 | 685 |
648 /** | 686 /** |
649 * Compute the set of files that are being flushed, this is defined as | 687 * Compute the set of files that are being flushed, this is defined as |
650 * the set of sources in the removed context (context.sources), that are | 688 * the set of sources in the removed context (context.sources), that are |
651 * orphaned by this context being removed (no other context includes this | 689 * orphaned by this context being removed (no other context includes this |
652 * file.) | 690 * file.) |
653 */ | 691 */ |
654 List<String> _computeFlushedFiles(Folder folder) { | 692 List<String> _computeFlushedFiles(ContextInfo info) { |
655 AnalysisContext context = _contexts[folder].context; | 693 AnalysisContext context = info.context; |
656 HashSet<String> flushedFiles = new HashSet<String>(); | 694 HashSet<String> flushedFiles = new HashSet<String>(); |
657 for (Source source in context.sources) { | 695 for (Source source in context.sources) { |
658 flushedFiles.add(source.fullName); | 696 flushedFiles.add(source.fullName); |
659 } | 697 } |
660 for (ContextInfo contextInfo in _contexts.values) { | 698 for (ContextInfo contextInfo in _rootInfo.descendants) { |
661 AnalysisContext contextN = contextInfo.context; | 699 AnalysisContext contextN = contextInfo.context; |
662 if (context != contextN) { | 700 if (context != contextN) { |
663 for (Source source in contextN.sources) { | 701 for (Source source in contextN.sources) { |
664 flushedFiles.remove(source.fullName); | 702 flushedFiles.remove(source.fullName); |
665 } | 703 } |
666 } | 704 } |
667 } | 705 } |
668 return flushedFiles.toList(growable: false); | 706 return flushedFiles.toList(growable: false); |
669 } | 707 } |
670 | 708 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
745 } | 783 } |
746 | 784 |
747 /** | 785 /** |
748 * Create a new empty context associated with [folder], having parent | 786 * Create a new empty context associated with [folder], having parent |
749 * [parent] and using [packagespecFile] to resolve package URI's. | 787 * [parent] and using [packagespecFile] to resolve package URI's. |
750 */ | 788 */ |
751 ContextInfo _createContext( | 789 ContextInfo _createContext( |
752 ContextInfo parent, Folder folder, File packagespecFile) { | 790 ContextInfo parent, Folder folder, File packagespecFile) { |
753 ContextInfo info = new ContextInfo( | 791 ContextInfo info = new ContextInfo( |
754 parent, folder, packagespecFile, normalizedPackageRoots[folder.path]); | 792 parent, folder, packagespecFile, normalizedPackageRoots[folder.path]); |
755 _contexts[folder] = info; | |
756 Map<String, YamlNode> options = analysisOptionsProvider.getOptions(folder); | 793 Map<String, YamlNode> options = analysisOptionsProvider.getOptions(folder); |
757 processOptionsForContext(info, options); | 794 processOptionsForContext(info, options); |
758 info.changeSubscription = folder.changes.listen((WatchEvent event) { | 795 info.changeSubscription = folder.changes.listen((WatchEvent event) { |
759 _handleWatchEvent(folder, info, event); | 796 _handleWatchEvent(folder, info, event); |
760 }); | 797 }); |
761 try { | 798 try { |
762 Packages packages; | 799 Packages packages; |
763 UriResolver packageUriResolver; | 800 UriResolver packageUriResolver; |
764 | 801 |
765 if (ENABLE_PACKAGESPEC_SUPPORT) { | 802 if (ENABLE_PACKAGESPEC_SUPPORT) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
834 // don't belong to the children. | 871 // don't belong to the children. |
835 ChangeSet changeSet = new ChangeSet(); | 872 ChangeSet changeSet = new ChangeSet(); |
836 _addSourceFiles(changeSet, folder, parent); | 873 _addSourceFiles(changeSet, folder, parent); |
837 callbacks.applyChangesToContext(folder, changeSet); | 874 callbacks.applyChangesToContext(folder, changeSet); |
838 } | 875 } |
839 } | 876 } |
840 | 877 |
841 /** | 878 /** |
842 * Clean up and destroy the context associated with the given folder. | 879 * Clean up and destroy the context associated with the given folder. |
843 */ | 880 */ |
844 void _destroyContext(Folder folder) { | 881 void _destroyContext(ContextInfo info) { |
845 ContextInfo info = _contexts[folder]; | |
846 info.changeSubscription.cancel(); | 882 info.changeSubscription.cancel(); |
847 _cancelDependencySubscriptions(info); | 883 _cancelDependencySubscriptions(info); |
848 callbacks.removeContext(folder, _computeFlushedFiles(folder)); | 884 callbacks.removeContext(info.folder, _computeFlushedFiles(info)); |
849 bool wasRemoved = info.parent.children.remove(info); | 885 bool wasRemoved = info.parent.children.remove(info); |
850 assert(wasRemoved); | 886 assert(wasRemoved); |
851 _contexts.remove(folder); | |
852 } | 887 } |
853 | 888 |
854 /** | 889 /** |
855 * Extract a new [packagespecFile]-based context from [oldInfo]. | 890 * Extract a new [packagespecFile]-based context from [oldInfo]. |
856 */ | 891 */ |
857 void _extractContext(ContextInfo oldInfo, File packagespecFile) { | 892 void _extractContext(ContextInfo oldInfo, File packagespecFile) { |
858 Folder newFolder = packagespecFile.parent; | 893 Folder newFolder = packagespecFile.parent; |
859 ContextInfo newInfo = _createContext(oldInfo, newFolder, packagespecFile); | 894 ContextInfo newInfo = _createContext(oldInfo, newFolder, packagespecFile); |
860 // prepare sources to extract | 895 // prepare sources to extract |
861 Map<String, Source> extractedSources = new HashMap<String, Source>(); | 896 Map<String, Source> extractedSources = new HashMap<String, Source>(); |
(...skipping 18 matching lines...) Expand all Loading... |
880 oldInfo.sources.remove(path); | 915 oldInfo.sources.remove(path); |
881 changeSet.removedSource(source); | 916 changeSet.removedSource(source); |
882 }); | 917 }); |
883 callbacks.applyChangesToContext(oldInfo.folder, changeSet); | 918 callbacks.applyChangesToContext(oldInfo.folder, changeSet); |
884 } | 919 } |
885 // TODO(paulberry): every context that was previously a child of oldInfo is | 920 // TODO(paulberry): every context that was previously a child of oldInfo is |
886 // is still a child of oldInfo. This is wrong--some of them ought to be | 921 // is still a child of oldInfo. This is wrong--some of them ought to be |
887 // adopted by newInfo now. | 922 // adopted by newInfo now. |
888 } | 923 } |
889 | 924 |
| 925 /** |
| 926 * Return the [ContextInfo] for the "innermost" context whose associated |
| 927 * folder is or contains the given path. ("innermost" refers to the nesting |
| 928 * of contexts, so if there is a context for path /foo and a context for |
| 929 * path /foo/bar, then the innermost context containing /foo/bar/baz.dart is |
| 930 * the context for /foo/bar.) |
| 931 * |
| 932 * If no context contains the given path, `null` is returned. |
| 933 */ |
| 934 ContextInfo _getInnermostContextInfoFor(String path) { |
| 935 ContextInfo info = _rootInfo.findChildInfoFor(path); |
| 936 if (info == null) { |
| 937 return null; |
| 938 } |
| 939 while (true) { |
| 940 ContextInfo childInfo = info.findChildInfoFor(path); |
| 941 if (childInfo == null) { |
| 942 return info; |
| 943 } |
| 944 info = childInfo; |
| 945 } |
| 946 } |
| 947 |
890 void _handleWatchEvent(Folder folder, ContextInfo info, WatchEvent event) { | 948 void _handleWatchEvent(Folder folder, ContextInfo info, WatchEvent event) { |
891 // TODO(brianwilkerson) If a file is explicitly included in one context | 949 // TODO(brianwilkerson) If a file is explicitly included in one context |
892 // but implicitly referenced in another context, we will only send a | 950 // but implicitly referenced in another context, we will only send a |
893 // changeSet to the context that explicitly includes the file (because | 951 // changeSet to the context that explicitly includes the file (because |
894 // that's the only context that's watching the file). | 952 // that's the only context that's watching the file). |
895 _instrumentationService.logWatchEvent( | 953 _instrumentationService.logWatchEvent( |
896 folder.path, event.path, event.type.toString()); | 954 folder.path, event.path, event.type.toString()); |
897 String path = event.path; | 955 String path = event.path; |
898 // maybe excluded globally | 956 // maybe excluded globally |
899 if (_isExcluded(path)) { | 957 if (_isExcluded(path)) { |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1063 bool _isPackagespec(String path) => | 1121 bool _isPackagespec(String path) => |
1064 pathContext.basename(path) == PACKAGE_SPEC_NAME; | 1122 pathContext.basename(path) == PACKAGE_SPEC_NAME; |
1065 | 1123 |
1066 bool _isPubspec(String path) => pathContext.basename(path) == PUBSPEC_NAME; | 1124 bool _isPubspec(String path) => pathContext.basename(path) == PUBSPEC_NAME; |
1067 | 1125 |
1068 /** | 1126 /** |
1069 * Merges [info] context into its parent. | 1127 * Merges [info] context into its parent. |
1070 */ | 1128 */ |
1071 void _mergeContext(ContextInfo info) { | 1129 void _mergeContext(ContextInfo info) { |
1072 // destroy the context | 1130 // destroy the context |
1073 _destroyContext(info.folder); | 1131 _destroyContext(info); |
1074 // add files to the parent context | 1132 // add files to the parent context |
1075 ContextInfo parentInfo = info.parent; | 1133 ContextInfo parentInfo = info.parent; |
1076 if (parentInfo != null) { | 1134 if (parentInfo != null) { |
1077 parentInfo.children.remove(info); | 1135 parentInfo.children.remove(info); |
1078 ChangeSet changeSet = new ChangeSet(); | 1136 ChangeSet changeSet = new ChangeSet(); |
1079 info.sources.forEach((path, source) { | 1137 info.sources.forEach((path, source) { |
1080 parentInfo.sources[path] = source; | 1138 parentInfo.sources[path] = source; |
1081 changeSet.addedSource(source); | 1139 changeSet.addedSource(source); |
1082 }); | 1140 }); |
1083 callbacks.applyChangesToContext(parentInfo.folder, changeSet); | 1141 callbacks.applyChangesToContext(parentInfo.folder, changeSet); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1151 */ | 1209 */ |
1152 final List<AnalysisContext> removed; | 1210 final List<AnalysisContext> removed; |
1153 | 1211 |
1154 /** | 1212 /** |
1155 * Initialize a newly created event to indicate which contexts have changed. | 1213 * Initialize a newly created event to indicate which contexts have changed. |
1156 */ | 1214 */ |
1157 ContextsChangedEvent({this.added: AnalysisContext.EMPTY_LIST, | 1215 ContextsChangedEvent({this.added: AnalysisContext.EMPTY_LIST, |
1158 this.changed: AnalysisContext.EMPTY_LIST, | 1216 this.changed: AnalysisContext.EMPTY_LIST, |
1159 this.removed: AnalysisContext.EMPTY_LIST}); | 1217 this.removed: AnalysisContext.EMPTY_LIST}); |
1160 } | 1218 } |
OLD | NEW |