| 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 | 9 |
| 10 import 'package:analysis_server/src/resource.dart'; | 10 import 'package:analysis_server/src/resource.dart'; |
| 11 import 'package:analyzer/src/generated/engine.dart'; | 11 import 'package:analyzer/src/generated/engine.dart'; |
| 12 import 'package:analyzer/src/generated/source.dart'; | 12 import 'package:analyzer/src/generated/source.dart'; |
| 13 import 'package:watcher/watcher.dart'; | 13 import 'package:watcher/watcher.dart'; |
| 14 | 14 |
| 15 /** | 15 /** |
| 16 * Information tracked by the [ContextDirectoryManager] for each context. | 16 * Information tracked by the [ContextDirectoryManager] for each context. |
| 17 */ | 17 */ |
| 18 class _ContextDirectoryInfo { | 18 class _ContextDirectoryInfo { |
| 19 /** | 19 /** |
| 20 * Stream subscription we are using to watch the context's directory for | 20 * Stream subscription we are using to watch the context's directory for |
| 21 * changes. | 21 * changes. |
| 22 */ | 22 */ |
| 23 StreamSubscription<WatchEvent> changeSubscription; | 23 StreamSubscription<WatchEvent> changeSubscription; |
| 24 | 24 |
| 25 /** | 25 /** |
| 26 * Map from full path to the [Source] object, for each source that has been | 26 * Map from full path to the [Source] object, for each source that has been |
| 27 * added to the context. | 27 * added to the context. |
| 28 */ | 28 */ |
| 29 Map<String, Source> sources = new HashMap<String, Source>(); | 29 Map<String, Source> sources = new HashMap<String, Source>(); |
| 30 | |
| 31 /** | |
| 32 * Pubspec file for this context, if there is one. Otherwise null. | |
| 33 */ | |
| 34 File pubspecFile = null; | |
| 35 | |
| 36 /** | |
| 37 * Path to that the pubspec file for this context would have, if it has one. | |
| 38 * Otherwise path that the pubspec file would have. | |
| 39 */ | |
| 40 String pubspecPath; | |
| 41 } | 30 } |
| 42 | 31 |
| 43 /** | 32 /** |
| 44 * Class that maintains a mapping from included/excluded paths to a set of | 33 * Class that maintains a mapping from included/excluded paths to a set of |
| 45 * folders that should correspond to analysis contexts. | 34 * folders that should correspond to analysis contexts. |
| 46 */ | 35 */ |
| 47 abstract class ContextDirectoryManager { | 36 abstract class ContextDirectoryManager { |
| 48 /** | 37 /** |
| 49 * File name of pubspec files. | 38 * File name of pubspec files. |
| 50 */ | 39 */ |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 /** | 97 /** |
| 109 * Create a new context associated with the given folder. | 98 * Create a new context associated with the given folder. |
| 110 */ | 99 */ |
| 111 void _createContext(Folder folder) { | 100 void _createContext(Folder folder) { |
| 112 _ContextDirectoryInfo info = new _ContextDirectoryInfo(); | 101 _ContextDirectoryInfo info = new _ContextDirectoryInfo(); |
| 113 _currentDirectoryInfo[folder] = info; | 102 _currentDirectoryInfo[folder] = info; |
| 114 info.changeSubscription = folder.changes.listen((WatchEvent event) { | 103 info.changeSubscription = folder.changes.listen((WatchEvent event) { |
| 115 _handleWatchEvent(folder, info, event); | 104 _handleWatchEvent(folder, info, event); |
| 116 }); | 105 }); |
| 117 File pubspecFile = folder.getChild(PUBSPEC_NAME); | 106 File pubspecFile = folder.getChild(PUBSPEC_NAME); |
| 118 info.pubspecPath = pubspecFile.path; | 107 addContext(folder); |
| 119 if (pubspecFile.exists) { | |
| 120 info.pubspecFile = pubspecFile; | |
| 121 } | |
| 122 addContext(folder, info.pubspecFile); | |
| 123 ChangeSet changeSet = new ChangeSet(); | 108 ChangeSet changeSet = new ChangeSet(); |
| 124 _addSourceFiles(changeSet, folder, info); | 109 _addSourceFiles(changeSet, folder, info); |
| 125 applyChangesToContext(folder, changeSet); | 110 applyChangesToContext(folder, changeSet); |
| 126 } | 111 } |
| 127 | 112 |
| 128 /** | 113 /** |
| 129 * Clean up and destroy the context associated with the given folder. | 114 * Clean up and destroy the context associated with the given folder. |
| 130 */ | 115 */ |
| 131 void _destroyContext(Folder folder) { | 116 void _destroyContext(Folder folder) { |
| 132 _currentDirectoryInfo[folder].changeSubscription.cancel(); | 117 _currentDirectoryInfo[folder].changeSubscription.cancel(); |
| 133 _currentDirectoryInfo.remove(folder); | 118 _currentDirectoryInfo.remove(folder); |
| 134 removeContext(folder); | 119 removeContext(folder); |
| 135 } | 120 } |
| 136 | 121 |
| 137 void _handleWatchEvent(Folder folder, _ContextDirectoryInfo info, WatchEvent e
vent) { | 122 void _handleWatchEvent(Folder folder, _ContextDirectoryInfo info, WatchEvent e
vent) { |
| 138 switch (event.type) { | 123 switch (event.type) { |
| 139 case ChangeType.ADD: | 124 case ChangeType.ADD: |
| 140 if (_isInPackagesDir(event.path, folder)) { | 125 if (_isInPackagesDir(event.path, folder)) { |
| 141 // TODO(paulberry): perhaps we should only skip packages dirs if | 126 // TODO(paulberry): perhaps we should only skip packages dirs if |
| 142 // there is a pubspec.yaml? | 127 // there is a pubspec.yaml? |
| 143 break; | 128 break; |
| 144 } | 129 } |
| 145 if (info.pubspecFile == null && event.path == info.pubspecPath) { | |
| 146 // Pubspec file added. This is likely to be such a rare event that | |
| 147 // there's no need to try to be clever. Just destroy the old context | |
| 148 // and create a new one. | |
| 149 _destroyContext(folder); | |
| 150 _createContext(folder); | |
| 151 return; | |
| 152 } | |
| 153 if (_shouldFileBeAnalyzed(event.path)) { | 130 if (_shouldFileBeAnalyzed(event.path)) { |
| 154 ChangeSet changeSet = new ChangeSet(); | 131 ChangeSet changeSet = new ChangeSet(); |
| 155 Resource resource = resourceProvider.getResource(event.path); | 132 Resource resource = resourceProvider.getResource(event.path); |
| 156 // If the file went away and was replaced by a folder before we | 133 // If the file went away and was replaced by a folder before we |
| 157 // had a chance to process the event, resource might be a Folder. In | 134 // had a chance to process the event, resource might be a Folder. In |
| 158 // that case don't add it. | 135 // that case don't add it. |
| 159 if (resource is File) { | 136 if (resource is File) { |
| 160 File file = resource; | 137 File file = resource; |
| 161 Source source = file.createSource(UriKind.FILE_URI); | 138 Source source = file.createSource(UriKind.FILE_URI); |
| 162 changeSet.addedSource(source); | 139 changeSet.addedSource(source); |
| 163 applyChangesToContext(folder, changeSet); | 140 applyChangesToContext(folder, changeSet); |
| 164 info.sources[event.path]= source; | 141 info.sources[event.path]= source; |
| 165 } | 142 } |
| 166 } | 143 } |
| 167 break; | 144 break; |
| 168 case ChangeType.REMOVE: | 145 case ChangeType.REMOVE: |
| 169 if (info.pubspecFile != null && event.path == info.pubspecPath) { | |
| 170 // Pubspec file removed. This is likely to be such a rare event that | |
| 171 // there's no need to try to be clever. Just destroy the old context | |
| 172 // and create a new one. | |
| 173 _destroyContext(folder); | |
| 174 _createContext(folder); | |
| 175 return; | |
| 176 } | |
| 177 // TODO(paulberry): handle removing pubspec.yaml | |
| 178 Source source = info.sources[event.path]; | 146 Source source = info.sources[event.path]; |
| 179 if (source != null) { | 147 if (source != null) { |
| 180 ChangeSet changeSet = new ChangeSet(); | 148 ChangeSet changeSet = new ChangeSet(); |
| 181 changeSet.removedSource(source); | 149 changeSet.removedSource(source); |
| 182 applyChangesToContext(folder, changeSet); | 150 applyChangesToContext(folder, changeSet); |
| 183 info.sources.remove(event.path); | 151 info.sources.remove(event.path); |
| 184 } | 152 } |
| 185 break; | 153 break; |
| 186 case ChangeType.MODIFY: | 154 case ChangeType.MODIFY: |
| 187 Source source = info.sources[event.path]; | 155 Source source = info.sources[event.path]; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 } | 199 } |
| 232 } | 200 } |
| 233 } | 201 } |
| 234 | 202 |
| 235 static bool _shouldFileBeAnalyzed(String path) { | 203 static bool _shouldFileBeAnalyzed(String path) { |
| 236 return AnalysisEngine.isDartFileName(path) | 204 return AnalysisEngine.isDartFileName(path) |
| 237 || AnalysisEngine.isHtmlFileName(path); | 205 || AnalysisEngine.isHtmlFileName(path); |
| 238 } | 206 } |
| 239 | 207 |
| 240 /** | 208 /** |
| 241 * Called when a new context needs to be created. If the context is | 209 * Called when a new context needs to be created. |
| 242 * associated with a pubspec file, that file is passed in [pubspecFile]; | |
| 243 * otherwise it is null. | |
| 244 */ | 210 */ |
| 245 void addContext(Folder folder, File pubspecFile); | 211 void addContext(Folder folder); |
| 246 | 212 |
| 247 /** | 213 /** |
| 248 * Called when the set of files associated with a context have changed (or | 214 * Called when the set of files associated with a context have changed (or |
| 249 * some of those files have been modified). [changeSet] is the set of | 215 * some of those files have been modified). [changeSet] is the set of |
| 250 * changes that need to be applied to the context. | 216 * changes that need to be applied to the context. |
| 251 */ | 217 */ |
| 252 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet); | 218 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet); |
| 253 | 219 |
| 254 /** | 220 /** |
| 255 * Remove the context associated with the given [folder]. | 221 * Remove the context associated with the given [folder]. |
| 256 */ | 222 */ |
| 257 void removeContext(Folder folder); | 223 void removeContext(Folder folder); |
| 258 } | 224 } |
| OLD | NEW |