| 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/package_map_provider.dart'; | 10 import 'package:analysis_server/src/package_map_provider.dart'; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 /** | 81 /** |
| 82 * Remove the context associated with the given [folder]. | 82 * Remove the context associated with the given [folder]. |
| 83 */ | 83 */ |
| 84 void removeContext(Folder folder); | 84 void removeContext(Folder folder); |
| 85 | 85 |
| 86 /** | 86 /** |
| 87 * Change the set of paths which should be used as starting points to | 87 * Change the set of paths which should be used as starting points to |
| 88 * determine the context directories. | 88 * determine the context directories. |
| 89 */ | 89 */ |
| 90 void setRoots(List<String> includedPaths, List<String> excludedPaths) { | 90 void setRoots(List<String> includedPaths, List<String> excludedPaths) { |
| 91 List<Folder> contextFolders = _contexts.keys.toList(); |
| 91 // included | 92 // included |
| 92 Set<Folder> includedFolders = new HashSet<Folder>(); | 93 Set<Folder> includedFolders = new HashSet<Folder>(); |
| 93 for (int i = 0; i < includedPaths.length; i++) { | 94 for (int i = 0; i < includedPaths.length; i++) { |
| 94 String path = includedPaths[i]; | 95 String path = includedPaths[i]; |
| 95 Resource resource = resourceProvider.getResource(path); | 96 Resource resource = resourceProvider.getResource(path); |
| 96 if (resource is Folder) { | 97 if (resource is Folder) { |
| 97 includedFolders.add(resource); | 98 includedFolders.add(resource); |
| 98 } else { | 99 } else { |
| 99 // TODO(scheglov) implemented separate files analysis | 100 // TODO(scheglov) implemented separate files analysis |
| 100 throw new UnimplementedError( | 101 throw new UnimplementedError( |
| 101 '$path is not a folder. ' | 102 '$path is not a folder. ' |
| 102 'Only support for folder analysis is implemented currently.'); | 103 'Only support for folder analysis is implemented currently.'); |
| 103 } | 104 } |
| 104 } | 105 } |
| 105 // excluded | 106 // excluded |
| 106 // TODO(scheglov) remove when implemented | 107 // TODO(scheglov) remove when implemented |
| 107 if (excludedPaths.isNotEmpty) { | 108 if (excludedPaths.isNotEmpty) { |
| 108 throw new UnimplementedError('Excluded paths are not supported yet'); | 109 throw new UnimplementedError('Excluded paths are not supported yet'); |
| 109 } | 110 } |
| 110 Set<Folder> excludedFolders = new HashSet<Folder>(); | 111 Set<Folder> excludedFolders = new HashSet<Folder>(); |
| 111 // diff | 112 // destroy old contexts |
| 112 Set<Folder> currentFolders = _contexts.keys.toSet(); | 113 for (Folder contextFolder in contextFolders) { |
| 113 Set<Folder> newFolders = new HashSet<Folder>(); | |
| 114 Set<Folder> oldFolders = new HashSet<Folder>(); | |
| 115 for (Folder currentFolder in currentFolders) { | |
| 116 bool isIncluded = includedFolders.any((folder) { | 114 bool isIncluded = includedFolders.any((folder) { |
| 117 return folder.contains(currentFolder.path); | 115 return folder.contains(contextFolder.path); |
| 118 }); | 116 }); |
| 119 if (!isIncluded) { | 117 if (!isIncluded) { |
| 120 oldFolders.add(currentFolder); | 118 _destroyContext(contextFolder); |
| 121 } | 119 } |
| 122 } | 120 } |
| 121 // create new contexts |
| 123 for (Folder includedFolder in includedFolders) { | 122 for (Folder includedFolder in includedFolders) { |
| 124 bool wasIncluded = currentFolders.any((folder) { | 123 bool wasIncluded = contextFolders.any((folder) { |
| 125 return folder.contains(includedFolder.path); | 124 return folder.contains(includedFolder.path); |
| 126 }); | 125 }); |
| 127 if (!wasIncluded) { | 126 if (!wasIncluded) { |
| 128 newFolders.add(includedFolder); | 127 _createContexts(includedFolder, false); |
| 129 } | 128 } |
| 130 } | 129 } |
| 131 // destroy old contexts | |
| 132 for (Folder folder in oldFolders) { | |
| 133 _destroyContext(folder); | |
| 134 } | |
| 135 // create new contexts | |
| 136 for (Folder folder in newFolders) { | |
| 137 _createContexts(folder, false); | |
| 138 } | |
| 139 } | 130 } |
| 140 | 131 |
| 141 /** | 132 /** |
| 142 * Called when the package map for a context has changed. | 133 * Called when the package map for a context has changed. |
| 143 */ | 134 */ |
| 144 void updateContextPackageMap(Folder contextFolder, Map<String, | 135 void updateContextPackageMap(Folder contextFolder, Map<String, |
| 145 List<Folder>> packageMap); | 136 List<Folder>> packageMap); |
| 146 | 137 |
| 147 /** | 138 /** |
| 148 * Create a new empty context associated with [folder]. | 139 * Create a new empty context associated with [folder]. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 176 | 167 |
| 177 /** | 168 /** |
| 178 * Creates a new context associated with [folder]. | 169 * Creates a new context associated with [folder]. |
| 179 * | 170 * |
| 180 * If there are subfolders with 'pubspec.yaml' files, separate contexts | 171 * If there are subfolders with 'pubspec.yaml' files, separate contexts |
| 181 * are created for them, and excluded from the context associated with | 172 * are created for them, and excluded from the context associated with |
| 182 * [folder]. | 173 * [folder]. |
| 183 * | 174 * |
| 184 * If [folder] itself contains a 'pubspec.yaml' file, subfolders are ignored. | 175 * If [folder] itself contains a 'pubspec.yaml' file, subfolders are ignored. |
| 185 * | 176 * |
| 177 * If [withPubspecOnly] is `true`, a context will be created only if there |
| 178 * is a 'pubspec.yaml' file in [folder]. |
| 179 * |
| 186 * Returns create pubspec-based contexts. | 180 * Returns create pubspec-based contexts. |
| 187 */ | 181 */ |
| 188 List<_ContextInfo> _createContexts(Folder folder, bool withPubspecOnly) { | 182 List<_ContextInfo> _createContexts(Folder folder, bool withPubspecOnly) { |
| 189 // check if there is a pubspec in the folder | 183 // check if there is a pubspec in the folder |
| 190 { | 184 { |
| 191 File pubspecFile = folder.getChild(PUBSPEC_NAME); | 185 File pubspecFile = folder.getChild(PUBSPEC_NAME); |
| 192 if (pubspecFile.exists) { | 186 if (pubspecFile.exists) { |
| 193 _ContextInfo info = _createContextWithSources(folder, <_ContextInfo>[]); | 187 _ContextInfo info = _createContextWithSources(folder, <_ContextInfo>[]); |
| 194 return [info]; | 188 return [info]; |
| 195 } | 189 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 221 } | 215 } |
| 222 | 216 |
| 223 /** | 217 /** |
| 224 * Extract a new [pubspecFile]-based context from [oldInfo]. | 218 * Extract a new [pubspecFile]-based context from [oldInfo]. |
| 225 */ | 219 */ |
| 226 void _extractContext(_ContextInfo oldInfo, File pubspecFile) { | 220 void _extractContext(_ContextInfo oldInfo, File pubspecFile) { |
| 227 Folder newFolder = pubspecFile.parent; | 221 Folder newFolder = pubspecFile.parent; |
| 228 _ContextInfo newInfo = _createContext(newFolder, []); | 222 _ContextInfo newInfo = _createContext(newFolder, []); |
| 229 newInfo.parent = oldInfo; | 223 newInfo.parent = oldInfo; |
| 230 // prepare sources to extract | 224 // prepare sources to extract |
| 231 Map<String, Source> extractSources = new HashMap<String, Source>(); | 225 Map<String, Source> extractedSources = new HashMap<String, Source>(); |
| 232 oldInfo.sources.forEach((path, source) { | 226 oldInfo.sources.forEach((path, source) { |
| 233 if (newFolder.contains(path)) { | 227 if (newFolder.contains(path)) { |
| 234 extractSources[path] = source; | 228 extractedSources[path] = source; |
| 235 } | 229 } |
| 236 }); | 230 }); |
| 237 // update new context | 231 // update new context |
| 238 { | 232 { |
| 239 ChangeSet changeSet = new ChangeSet(); | 233 ChangeSet changeSet = new ChangeSet(); |
| 240 extractSources.forEach((path, source) { | 234 extractedSources.forEach((path, source) { |
| 241 newInfo.sources[path] = source; | 235 newInfo.sources[path] = source; |
| 242 changeSet.addedSource(source); | 236 changeSet.addedSource(source); |
| 243 }); | 237 }); |
| 244 applyChangesToContext(newFolder, changeSet); | 238 applyChangesToContext(newFolder, changeSet); |
| 245 } | 239 } |
| 246 // update old context | 240 // update old context |
| 247 { | 241 { |
| 248 ChangeSet changeSet = new ChangeSet(); | 242 ChangeSet changeSet = new ChangeSet(); |
| 249 extractSources.forEach((path, source) { | 243 extractedSources.forEach((path, source) { |
| 250 oldInfo.sources.remove(path); | 244 oldInfo.sources.remove(path); |
| 251 changeSet.removedSource(source); | 245 changeSet.removedSource(source); |
| 252 }); | 246 }); |
| 253 applyChangesToContext(oldInfo.folder, changeSet); | 247 applyChangesToContext(oldInfo.folder, changeSet); |
| 254 } | 248 } |
| 255 } | 249 } |
| 256 | 250 |
| 257 void _handleWatchEvent(Folder folder, _ContextInfo info, WatchEvent event) { | 251 void _handleWatchEvent(Folder folder, _ContextInfo info, WatchEvent event) { |
| 258 String path = event.path; | 252 String path = event.path; |
| 259 // maybe excluded, so other context will handle it | 253 // maybe excluded, so other context will handle it |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 * Merges [info] context into its parent. | 344 * Merges [info] context into its parent. |
| 351 */ | 345 */ |
| 352 void _mergeContext(_ContextInfo info) { | 346 void _mergeContext(_ContextInfo info) { |
| 353 // destroy the context | 347 // destroy the context |
| 354 _destroyContext(info.folder); | 348 _destroyContext(info.folder); |
| 355 // add files to the parent context | 349 // add files to the parent context |
| 356 _ContextInfo parentInfo = info.parent; | 350 _ContextInfo parentInfo = info.parent; |
| 357 if (parentInfo != null) { | 351 if (parentInfo != null) { |
| 358 parentInfo.children.remove(info); | 352 parentInfo.children.remove(info); |
| 359 ChangeSet changeSet = new ChangeSet(); | 353 ChangeSet changeSet = new ChangeSet(); |
| 360 _addSourceFiles(changeSet, info.folder, parentInfo); | 354 info.sources.forEach((path, source) { |
| 355 parentInfo.sources[path] = source; |
| 356 changeSet.addedSource(source); |
| 357 }); |
| 361 applyChangesToContext(parentInfo.folder, changeSet); | 358 applyChangesToContext(parentInfo.folder, changeSet); |
| 362 } | 359 } |
| 363 } | 360 } |
| 364 | 361 |
| 365 /** | 362 /** |
| 366 * Resursively adds all Dart and HTML files to the [changeSet]. | 363 * Resursively adds all Dart and HTML files to the [changeSet]. |
| 367 */ | 364 */ |
| 368 static void _addSourceFiles(ChangeSet changeSet, Folder folder, | 365 static void _addSourceFiles(ChangeSet changeSet, Folder folder, |
| 369 _ContextInfo info) { | 366 _ContextInfo info) { |
| 370 if (info.excludesResource(folder)) { | 367 if (info.excludesResource(folder)) { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 return excludes(resource.path); | 465 return excludes(resource.path); |
| 469 } | 466 } |
| 470 | 467 |
| 471 /** | 468 /** |
| 472 * Returns `true` if [path] is the pubspec file of this context. | 469 * Returns `true` if [path] is the pubspec file of this context. |
| 473 */ | 470 */ |
| 474 bool isPubspec(String path) { | 471 bool isPubspec(String path) { |
| 475 return path == pubspecPath; | 472 return path == pubspecPath; |
| 476 } | 473 } |
| 477 } | 474 } |
| OLD | NEW |