Chromium Code Reviews| 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'; | |
| 8 | |
| 7 import 'package:analysis_server/src/resource.dart'; | 9 import 'package:analysis_server/src/resource.dart'; |
| 8 import 'package:analyzer/src/generated/engine.dart'; | 10 import 'package:analyzer/src/generated/engine.dart'; |
| 9 import 'package:analyzer/src/generated/source.dart'; | 11 import 'package:analyzer/src/generated/source.dart'; |
| 12 import 'package:watcher/watcher.dart'; | |
| 13 | |
| 14 /** | |
| 15 * Information tracked by the [ContextDirectoryManager] for each context. | |
| 16 */ | |
| 17 class _ContextDirectoryInfo { | |
| 18 /** | |
| 19 * Stream subscription we are using to watch the context's directory for | |
| 20 * changes. | |
| 21 */ | |
| 22 StreamSubscription<WatchEvent> changeSubscription; | |
| 23 | |
| 24 /** | |
| 25 * Map from full path to the [Source] object, for each source that has been | |
| 26 * added to the context. | |
| 27 */ | |
| 28 Map<String, Source> sources = <String, Source>{}; | |
| 29 } | |
| 10 | 30 |
| 11 /** | 31 /** |
| 12 * Class that maintains a mapping from included/excluded paths to a set of | 32 * Class that maintains a mapping from included/excluded paths to a set of |
| 13 * folders that should correspond to analysis contexts. | 33 * folders that should correspond to analysis contexts. |
| 14 */ | 34 */ |
| 15 abstract class ContextDirectoryManager { | 35 abstract class ContextDirectoryManager { |
| 16 /** | 36 /** |
| 17 * The set of included folders in the most recent successful call to | 37 * [_ContextDirectoryInfo] object for each included directory in the most |
| 18 * [setRoots]. | 38 * recent successful call to [setRoots]. |
| 19 */ | 39 */ |
| 20 Set<Folder> currentFolders = new Set<Folder>(); | 40 Map<Folder, _ContextDirectoryInfo> _currentDirectoryInfo = |
| 41 <Folder, _ContextDirectoryInfo>{}; | |
|
danrubel
2014/05/29 18:14:43
Do you need the extra type declaration here since
Paul Berry
2014/05/29 18:30:23
Heh, I was just talking about this yesterday with
| |
| 21 | 42 |
| 22 /** | 43 /** |
| 23 * The [ResourceProvider] using which paths are converted into [Resource]s. | 44 * The [ResourceProvider] using which paths are converted into [Resource]s. |
| 24 */ | 45 */ |
| 25 final ResourceProvider resourceProvider; | 46 final ResourceProvider resourceProvider; |
| 26 | 47 |
| 27 ContextDirectoryManager(this.resourceProvider); | 48 ContextDirectoryManager(this.resourceProvider); |
| 28 | 49 |
| 29 /** | 50 /** |
| 30 * Change the set of paths which should be used as starting points to | 51 * Change the set of paths which should be used as starting points to |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 47 } | 68 } |
| 48 } | 69 } |
| 49 // excluded | 70 // excluded |
| 50 // TODO(scheglov) remove when implemented | 71 // TODO(scheglov) remove when implemented |
| 51 if (excludedPaths.isNotEmpty) { | 72 if (excludedPaths.isNotEmpty) { |
| 52 throw new UnimplementedError( | 73 throw new UnimplementedError( |
| 53 'Excluded paths are not supported yet'); | 74 'Excluded paths are not supported yet'); |
| 54 } | 75 } |
| 55 Set<Folder> excludedFolders = new Set<Folder>(); | 76 Set<Folder> excludedFolders = new Set<Folder>(); |
| 56 // diff | 77 // diff |
| 78 Set<Folder> currentFolders = _currentDirectoryInfo.keys.toSet(); | |
| 57 Set<Folder> newFolders = includedFolders.difference(currentFolders); | 79 Set<Folder> newFolders = includedFolders.difference(currentFolders); |
| 58 Set<Folder> oldFolders = currentFolders.difference(includedFolders); | 80 Set<Folder> oldFolders = currentFolders.difference(includedFolders); |
| 59 // remove old contexts | 81 // remove old contexts |
| 60 for (Folder folder in oldFolders) { | 82 for (Folder folder in oldFolders) { |
| 61 // TODO(scheglov) implement | 83 // TODO(scheglov) implement |
| 62 } | 84 } |
| 63 // add new contexts | 85 // add new contexts |
| 64 for (Folder folder in newFolders) { | 86 for (Folder folder in newFolders) { |
| 87 _ContextDirectoryInfo info = new _ContextDirectoryInfo(); | |
| 88 _currentDirectoryInfo[folder] = info; | |
| 89 info.changeSubscription = folder.changes.listen((WatchEvent event) { | |
| 90 _handleWatchEvent(folder, info, event); | |
| 91 }); | |
| 65 File pubspecFile = folder.getChild('pubspec.yaml'); | 92 File pubspecFile = folder.getChild('pubspec.yaml'); |
| 66 addContext(folder, pubspecFile.exists ? pubspecFile : null); | 93 addContext(folder, pubspecFile.exists ? pubspecFile : null); |
| 67 ChangeSet changeSet = new ChangeSet(); | 94 ChangeSet changeSet = new ChangeSet(); |
| 68 _addSourceFiles(changeSet, folder); | 95 _addSourceFiles(changeSet, folder, info); |
| 69 applyChangesToContext(folder, changeSet); | 96 applyChangesToContext(folder, changeSet); |
| 70 } | 97 } |
| 71 currentFolders = new Set<Folder>.from(includedFolders); | 98 } |
| 99 | |
| 100 void _handleWatchEvent(Folder folder, _ContextDirectoryInfo info, WatchEvent e vent) { | |
| 101 switch (event.type) { | |
| 102 case ChangeType.ADD: | |
| 103 // TODO(paulberry): handle adding pubspec.yaml | |
| 104 String shortName = resourceProvider.pathContext.basename(event.path); | |
|
scheglov
2014/05/29 17:37:03
Should we hide using "path" package and just add s
Paul Berry
2014/05/29 17:57:21
That's not a bad idea--it would decrease our risk
| |
| 105 if (_shouldFileBeAnalyzed(shortName)) { | |
| 106 ChangeSet changeSet = new ChangeSet(); | |
| 107 Resource resource = resourceProvider.getResource(event.path); | |
| 108 // Only add the file if it didn't go away before we had a chance | |
| 109 // to process the event. | |
| 110 if (resource is File) { | |
|
scheglov
2014/05/29 17:37:03
AFAIK getResource() will always return a File, it
Paul Berry
2014/05/29 17:57:21
Ok, my comment is wrong, but I believe this if-tes
| |
| 111 File file = resource; | |
| 112 Source source = file.createSource(UriKind.FILE_URI); | |
| 113 changeSet.addedSource(source); | |
| 114 applyChangesToContext(folder, changeSet); | |
| 115 info.sources[event.path]= source; | |
| 116 } | |
| 117 } | |
| 118 break; | |
| 119 case ChangeType.REMOVE: | |
| 120 // TODO(paulberry): handle removing pubspec.yaml | |
| 121 Source source = info.sources[event.path]; | |
| 122 if (source != null) { | |
| 123 ChangeSet changeSet = new ChangeSet(); | |
| 124 changeSet.removedSource(source); | |
| 125 applyChangesToContext(folder, changeSet); | |
| 126 info.sources.remove(event.path); | |
| 127 } | |
| 128 break; | |
| 129 case ChangeType.MODIFY: | |
| 130 // TODO(paulberry): handle modification events | |
| 131 break; | |
| 132 } | |
| 72 } | 133 } |
| 73 | 134 |
| 74 /** | 135 /** |
| 75 * Resursively adds all Dart and HTML files to the [changeSet]. | 136 * Resursively adds all Dart and HTML files to the [changeSet]. |
| 76 */ | 137 */ |
| 77 static void _addSourceFiles(ChangeSet changeSet, Folder folder) { | 138 static void _addSourceFiles(ChangeSet changeSet, Folder folder, _ContextDirect oryInfo info) { |
| 78 List<Resource> children = folder.getChildren(); | 139 List<Resource> children = folder.getChildren(); |
| 79 for (Resource child in children) { | 140 for (Resource child in children) { |
| 80 if (child is File) { | 141 if (child is File) { |
| 81 String fileName = child.shortName; | 142 String fileName = child.shortName; |
| 82 if (AnalysisEngine.isDartFileName(fileName) | 143 if (_shouldFileBeAnalyzed(fileName)) { |
| 83 || AnalysisEngine.isHtmlFileName(fileName)) { | |
| 84 Source source = child.createSource(UriKind.FILE_URI); | 144 Source source = child.createSource(UriKind.FILE_URI); |
| 85 changeSet.addedSource(source); | 145 changeSet.addedSource(source); |
| 146 // TODO(paulberry): this assumes child.fullName is synonymous with | |
| 147 // path. Can we rely on that? If so, maybe we should rename | |
| 148 // child.fullName to child.path. | |
|
scheglov
2014/05/29 17:37:03
SGTM
| |
| 149 info.sources[child.fullName] = source; | |
| 86 } | 150 } |
| 87 } else if (child is Folder) { | 151 } else if (child is Folder) { |
| 88 _addSourceFiles(changeSet, child); | 152 _addSourceFiles(changeSet, child, info); |
| 89 } | 153 } |
| 90 } | 154 } |
| 91 } | 155 } |
| 92 | 156 |
| 157 static bool _shouldFileBeAnalyzed(String shortName) { | |
|
scheglov
2014/05/29 17:37:03
I don't think isDartFileName() cares if it is give
Paul Berry
2014/05/29 17:57:21
You're right. I'll rework this to remove the call
| |
| 158 return AnalysisEngine.isDartFileName(shortName) | |
| 159 || AnalysisEngine.isHtmlFileName(shortName); | |
| 160 } | |
| 161 | |
| 93 /** | 162 /** |
| 94 * Called when a new context needs to be created. If the context is | 163 * Called when a new context needs to be created. If the context is |
| 95 * associated with a pubspec file, that file is passed in [pubspecFile]; | 164 * associated with a pubspec file, that file is passed in [pubspecFile]; |
| 96 * otherwise it is null. | 165 * otherwise it is null. |
| 97 */ | 166 */ |
| 98 void addContext(Folder folder, File pubspecFile); | 167 void addContext(Folder folder, File pubspecFile); |
| 99 | 168 |
| 100 /** | 169 /** |
| 101 * Called when the set of files associated with a context have changed (or | 170 * Called when the set of files associated with a context have changed (or |
| 102 * some of those files have been modified). [changeSet] is the set of | 171 * some of those files have been modified). [changeSet] is the set of |
| 103 * changes that need to be applied to the context. | 172 * changes that need to be applied to the context. |
| 104 */ | 173 */ |
| 105 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet); | 174 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet); |
| 106 } | 175 } |
| OLD | NEW |