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 13 matching lines...) Expand all Loading... |
24 import 'package:analyzer/source/sdk_ext.dart'; | 24 import 'package:analyzer/source/sdk_ext.dart'; |
25 import 'package:analyzer/src/context/context.dart' as context; | 25 import 'package:analyzer/src/context/context.dart' as context; |
26 import 'package:analyzer/src/context/source.dart'; | 26 import 'package:analyzer/src/context/source.dart'; |
27 import 'package:analyzer/src/generated/engine.dart'; | 27 import 'package:analyzer/src/generated/engine.dart'; |
28 import 'package:analyzer/src/generated/java_engine.dart'; | 28 import 'package:analyzer/src/generated/java_engine.dart'; |
29 import 'package:analyzer/src/generated/java_io.dart'; | 29 import 'package:analyzer/src/generated/java_io.dart'; |
30 import 'package:analyzer/src/generated/source.dart'; | 30 import 'package:analyzer/src/generated/source.dart'; |
31 import 'package:analyzer/src/generated/source_io.dart'; | 31 import 'package:analyzer/src/generated/source_io.dart'; |
32 import 'package:analyzer/src/task/options.dart'; | 32 import 'package:analyzer/src/task/options.dart'; |
33 import 'package:analyzer/src/util/absolute_path.dart'; | 33 import 'package:analyzer/src/util/absolute_path.dart'; |
| 34 import 'package:analyzer/src/util/glob.dart'; |
34 import 'package:analyzer/src/util/yaml.dart'; | 35 import 'package:analyzer/src/util/yaml.dart'; |
35 import 'package:package_config/packages.dart'; | 36 import 'package:package_config/packages.dart'; |
36 import 'package:package_config/packages_file.dart' as pkgfile show parse; | 37 import 'package:package_config/packages_file.dart' as pkgfile show parse; |
37 import 'package:package_config/src/packages_impl.dart' show MapPackages; | 38 import 'package:package_config/src/packages_impl.dart' show MapPackages; |
38 import 'package:path/path.dart' as pathos; | 39 import 'package:path/path.dart' as pathos; |
39 import 'package:watcher/watcher.dart'; | 40 import 'package:watcher/watcher.dart'; |
40 import 'package:yaml/yaml.dart'; | 41 import 'package:yaml/yaml.dart'; |
41 | 42 |
42 /** | 43 /** |
43 * Information tracked by the [ContextManager] for each context. | 44 * Information tracked by the [ContextManager] for each context. |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet); | 330 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet); |
330 | 331 |
331 /** | 332 /** |
332 * Remove the context associated with the given [folder]. [flushedFiles] is | 333 * Remove the context associated with the given [folder]. [flushedFiles] is |
333 * a list of the files which will be "orphaned" by removing this context | 334 * a list of the files which will be "orphaned" by removing this context |
334 * (they will no longer be analyzed by any context). | 335 * (they will no longer be analyzed by any context). |
335 */ | 336 */ |
336 void removeContext(Folder folder, List<String> flushedFiles); | 337 void removeContext(Folder folder, List<String> flushedFiles); |
337 | 338 |
338 /** | 339 /** |
339 * Return `true` if the given [file] should be analyzed. | |
340 */ | |
341 bool shouldFileBeAnalyzed(File file); | |
342 | |
343 /** | |
344 * Called when the disposition for a context has changed. | 340 * Called when the disposition for a context has changed. |
345 */ | 341 */ |
346 void updateContextPackageUriResolver( | 342 void updateContextPackageUriResolver( |
347 Folder contextFolder, FolderDisposition disposition); | 343 Folder contextFolder, FolderDisposition disposition); |
348 } | 344 } |
349 | 345 |
350 /** | 346 /** |
351 * Class that maintains a mapping from included/excluded paths to a set of | 347 * Class that maintains a mapping from included/excluded paths to a set of |
352 * folders that should correspond to analysis contexts. | 348 * folders that should correspond to analysis contexts. |
353 */ | 349 */ |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 * Provider which is used to determine the mapping from package name to | 431 * Provider which is used to determine the mapping from package name to |
436 * package folder. | 432 * package folder. |
437 */ | 433 */ |
438 final PubPackageMapProvider _packageMapProvider; | 434 final PubPackageMapProvider _packageMapProvider; |
439 | 435 |
440 /// Provider of analysis options. | 436 /// Provider of analysis options. |
441 AnalysisOptionsProvider analysisOptionsProvider = | 437 AnalysisOptionsProvider analysisOptionsProvider = |
442 new AnalysisOptionsProvider(); | 438 new AnalysisOptionsProvider(); |
443 | 439 |
444 /** | 440 /** |
| 441 * A list of the globs used to determine which files should be analyzed. |
| 442 */ |
| 443 final List<Glob> analyzedFilesGlobs; |
| 444 |
| 445 /** |
| 446 * The default options used to create new analysis contexts. |
| 447 */ |
| 448 final AnalysisOptionsImpl defaultContextOptions; |
| 449 |
| 450 /** |
445 * The instrumentation service used to report instrumentation data. | 451 * The instrumentation service used to report instrumentation data. |
446 */ | 452 */ |
447 final InstrumentationService _instrumentationService; | 453 final InstrumentationService _instrumentationService; |
448 | 454 |
449 /** | |
450 * The default options used to create new analysis contexts. | |
451 */ | |
452 final AnalysisOptionsImpl defaultContextOptions; | |
453 | |
454 @override | 455 @override |
455 ContextManagerCallbacks callbacks; | 456 ContextManagerCallbacks callbacks; |
456 | 457 |
457 /** | 458 /** |
458 * Virtual [ContextInfo] which acts as the ancestor of all other | 459 * Virtual [ContextInfo] which acts as the ancestor of all other |
459 * [ContextInfo]s. | 460 * [ContextInfo]s. |
460 */ | 461 */ |
461 final ContextInfo rootInfo = new ContextInfo._root(); | 462 final ContextInfo rootInfo = new ContextInfo._root(); |
462 | 463 |
463 /** | 464 /** |
464 * The controller that is notified when we are starting or ending the | 465 * The controller that is notified when we are starting or ending the |
465 * computation of a package map. | 466 * computation of a package map. |
466 */ | 467 */ |
467 StreamController<bool> _onComputingPackageMapController; | 468 StreamController<bool> _onComputingPackageMapController; |
468 | 469 |
469 /** | 470 /** |
470 * Stream subscription we are using to watch each analysis root directory for | 471 * Stream subscription we are using to watch each analysis root directory for |
471 * changes. | 472 * changes. |
472 */ | 473 */ |
473 final Map<Folder, StreamSubscription<WatchEvent>> changeSubscriptions = | 474 final Map<Folder, StreamSubscription<WatchEvent>> changeSubscriptions = |
474 <Folder, StreamSubscription<WatchEvent>>{}; | 475 <Folder, StreamSubscription<WatchEvent>>{}; |
475 | 476 |
476 ContextManagerImpl( | 477 ContextManagerImpl( |
477 this.resourceProvider, | 478 this.resourceProvider, |
478 this.packageResolverProvider, | 479 this.packageResolverProvider, |
479 this.embeddedUriResolverProvider, | 480 this.embeddedUriResolverProvider, |
480 this._packageMapProvider, | 481 this._packageMapProvider, |
| 482 this.analyzedFilesGlobs, |
481 this._instrumentationService, | 483 this._instrumentationService, |
482 this.defaultContextOptions) { | 484 this.defaultContextOptions) { |
483 absolutePathContext = resourceProvider.absolutePathContext; | 485 absolutePathContext = resourceProvider.absolutePathContext; |
484 pathContext = resourceProvider.pathContext; | 486 pathContext = resourceProvider.pathContext; |
485 _onComputingPackageMapController = new StreamController.broadcast(); | 487 _onComputingPackageMapController = new StreamController.broadcast(); |
486 } | 488 } |
487 | 489 |
488 @override | 490 @override |
489 Stream<bool> get onComputingPackageMap { | 491 Stream<bool> get onComputingPackageMap { |
490 return _onComputingPackageMapController.stream; | 492 return _onComputingPackageMapController.stream; |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
780 } | 782 } |
781 for (Resource child in children) { | 783 for (Resource child in children) { |
782 String path = child.path; | 784 String path = child.path; |
783 // Path is being ignored. | 785 // Path is being ignored. |
784 if (info.ignored(path)) { | 786 if (info.ignored(path)) { |
785 continue; | 787 continue; |
786 } | 788 } |
787 // add files, recurse into folders | 789 // add files, recurse into folders |
788 if (child is File) { | 790 if (child is File) { |
789 // ignore if should not be analyzed at all | 791 // ignore if should not be analyzed at all |
790 if (!callbacks.shouldFileBeAnalyzed(child)) { | 792 if (!_shouldFileBeAnalyzed(child)) { |
791 continue; | 793 continue; |
792 } | 794 } |
793 // ignore if was not excluded | 795 // ignore if was not excluded |
794 bool wasExcluded = _isExcludedBy(oldExcludedPaths, path) && | 796 bool wasExcluded = _isExcludedBy(oldExcludedPaths, path) && |
795 !_isExcludedBy(excludedPaths, path); | 797 !_isExcludedBy(excludedPaths, path); |
796 if (!wasExcluded) { | 798 if (!wasExcluded) { |
797 continue; | 799 continue; |
798 } | 800 } |
799 // do add the file | 801 // do add the file |
800 Source source = createSourceInContext(info.context, child); | 802 Source source = createSourceInContext(info.context, child); |
(...skipping 26 matching lines...) Expand all Loading... |
827 return; | 829 return; |
828 } | 830 } |
829 for (Resource child in children) { | 831 for (Resource child in children) { |
830 String path = child.path; | 832 String path = child.path; |
831 // ignore excluded files or folders | 833 // ignore excluded files or folders |
832 if (_isExcluded(path) || info.excludes(path) || info.ignored(path)) { | 834 if (_isExcluded(path) || info.excludes(path) || info.ignored(path)) { |
833 continue; | 835 continue; |
834 } | 836 } |
835 // add files, recurse into folders | 837 // add files, recurse into folders |
836 if (child is File) { | 838 if (child is File) { |
837 if (callbacks.shouldFileBeAnalyzed(child)) { | 839 if (_shouldFileBeAnalyzed(child)) { |
838 Source source = createSourceInContext(info.context, child); | 840 Source source = createSourceInContext(info.context, child); |
839 changeSet.addedSource(source); | 841 changeSet.addedSource(source); |
840 info.sources[path] = source; | 842 info.sources[path] = source; |
841 } | 843 } |
842 } else if (child is Folder) { | 844 } else if (child is Folder) { |
843 String shortName = child.shortName; | 845 String shortName = child.shortName; |
844 if (shortName == PACKAGES_NAME) { | 846 if (shortName == PACKAGES_NAME) { |
845 continue; | 847 continue; |
846 } | 848 } |
847 _addSourceFiles(changeSet, child, info); | 849 _addSourceFiles(changeSet, child, info); |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1301 } | 1303 } |
1302 } | 1304 } |
1303 } | 1305 } |
1304 } | 1306 } |
1305 | 1307 |
1306 // If the file went away and was replaced by a folder before we | 1308 // If the file went away and was replaced by a folder before we |
1307 // had a chance to process the event, resource might be a Folder. In | 1309 // had a chance to process the event, resource might be a Folder. In |
1308 // that case don't add it. | 1310 // that case don't add it. |
1309 if (resource is File) { | 1311 if (resource is File) { |
1310 File file = resource; | 1312 File file = resource; |
1311 if (callbacks.shouldFileBeAnalyzed(file)) { | 1313 if (_shouldFileBeAnalyzed(file)) { |
1312 ChangeSet changeSet = new ChangeSet(); | 1314 ChangeSet changeSet = new ChangeSet(); |
1313 Source source = createSourceInContext(info.context, file); | 1315 Source source = createSourceInContext(info.context, file); |
1314 changeSet.addedSource(source); | 1316 changeSet.addedSource(source); |
1315 callbacks.applyChangesToContext(info.folder, changeSet); | 1317 callbacks.applyChangesToContext(info.folder, changeSet); |
1316 info.sources[path] = source; | 1318 info.sources[path] = source; |
1317 } | 1319 } |
1318 } | 1320 } |
1319 break; | 1321 break; |
1320 case ChangeType.REMOVE: | 1322 case ChangeType.REMOVE: |
1321 | 1323 |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1485 // while we're rerunning "pub list", since any analysis we complete while | 1487 // while we're rerunning "pub list", since any analysis we complete while |
1486 // "pub list" is in progress is just going to get thrown away anyhow. | 1488 // "pub list" is in progress is just going to get thrown away anyhow. |
1487 List<String> dependencies = <String>[]; | 1489 List<String> dependencies = <String>[]; |
1488 FolderDisposition disposition = _computeFolderDisposition( | 1490 FolderDisposition disposition = _computeFolderDisposition( |
1489 info.folder, dependencies.add, _findPackageSpecFile(info.folder)); | 1491 info.folder, dependencies.add, _findPackageSpecFile(info.folder)); |
1490 info.setDependencies(dependencies); | 1492 info.setDependencies(dependencies); |
1491 callbacks.updateContextPackageUriResolver(info.folder, disposition); | 1493 callbacks.updateContextPackageUriResolver(info.folder, disposition); |
1492 } | 1494 } |
1493 | 1495 |
1494 /** | 1496 /** |
| 1497 * Return `true` if the given [file] should be analyzed. |
| 1498 */ |
| 1499 bool _shouldFileBeAnalyzed(File file) { |
| 1500 for (Glob glob in analyzedFilesGlobs) { |
| 1501 if (glob.matches(file.path)) { |
| 1502 // Emacs creates dummy links to track the fact that a file is open for |
| 1503 // editing and has unsaved changes (e.g. having unsaved changes to |
| 1504 // 'foo.dart' causes a link '.#foo.dart' to be created, which points to |
| 1505 // the non-existent file 'username@hostname.pid'. To avoid these dummy |
| 1506 // links causing the analyzer to thrash, just ignore links to |
| 1507 // non-existent files. |
| 1508 return file.exists; |
| 1509 } |
| 1510 } |
| 1511 return false; |
| 1512 } |
| 1513 |
| 1514 /** |
1495 * Create and return a source representing the given [file] within the given | 1515 * Create and return a source representing the given [file] within the given |
1496 * [context]. | 1516 * [context]. |
1497 */ | 1517 */ |
1498 static Source createSourceInContext(AnalysisContext context, File file) { | 1518 static Source createSourceInContext(AnalysisContext context, File file) { |
1499 // TODO(brianwilkerson) Optimize this, by allowing support for source | 1519 // TODO(brianwilkerson) Optimize this, by allowing support for source |
1500 // factories to restore URI's from a file path rather than a source. | 1520 // factories to restore URI's from a file path rather than a source. |
1501 Source source = file.createSource(); | 1521 Source source = file.createSource(); |
1502 if (context == null) { | 1522 if (context == null) { |
1503 return source; | 1523 return source; |
1504 } | 1524 } |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1679 ResourceProvider resourceProvider) { | 1699 ResourceProvider resourceProvider) { |
1680 if (packages != null) { | 1700 if (packages != null) { |
1681 // Construct package map for the SdkExtUriResolver. | 1701 // Construct package map for the SdkExtUriResolver. |
1682 Map<String, List<Folder>> packageMap = buildPackageMap(resourceProvider); | 1702 Map<String, List<Folder>> packageMap = buildPackageMap(resourceProvider); |
1683 return <UriResolver>[new SdkExtUriResolver(packageMap)]; | 1703 return <UriResolver>[new SdkExtUriResolver(packageMap)]; |
1684 } else { | 1704 } else { |
1685 return const <UriResolver>[]; | 1705 return const <UriResolver>[]; |
1686 } | 1706 } |
1687 } | 1707 } |
1688 } | 1708 } |
OLD | NEW |