| 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 analysis.server; | 5 library analysis.server; |
| 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/analysis_logger.dart'; | 10 import 'package:analysis_server/src/analysis_logger.dart'; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 * The default options used to create new analysis contexts. | 43 * The default options used to create new analysis contexts. |
| 44 */ | 44 */ |
| 45 AnalysisOptionsImpl defaultOptions = new AnalysisOptionsImpl(); | 45 AnalysisOptionsImpl defaultOptions = new AnalysisOptionsImpl(); |
| 46 | 46 |
| 47 AnalysisServerContextDirectoryManager( | 47 AnalysisServerContextDirectoryManager( |
| 48 this.analysisServer, ResourceProvider resourceProvider, | 48 this.analysisServer, ResourceProvider resourceProvider, |
| 49 PackageMapProvider packageMapProvider) | 49 PackageMapProvider packageMapProvider) |
| 50 : super(resourceProvider, packageMapProvider); | 50 : super(resourceProvider, packageMapProvider); |
| 51 | 51 |
| 52 @override | 52 @override |
| 53 void addContext(Folder folder, Map<String, List<Folder>> packageMap) { | 53 void addContext(Folder folder, HashMap<String, List<Folder>> packageMap) { |
| 54 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext(); | 54 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext(); |
| 55 analysisServer.folderMap[folder] = context; | 55 analysisServer.folderMap[folder] = context; |
| 56 context.sourceFactory = _createSourceFactory(packageMap); | 56 context.sourceFactory = _createSourceFactory(packageMap); |
| 57 context.analysisOptions = new AnalysisOptionsImpl.con1(defaultOptions); | 57 context.analysisOptions = new AnalysisOptionsImpl.con1(defaultOptions); |
| 58 analysisServer.schedulePerformAnalysisOperation(context); | 58 analysisServer.schedulePerformAnalysisOperation(context); |
| 59 } | 59 } |
| 60 | 60 |
| 61 @override | 61 @override |
| 62 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) { | 62 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) { |
| 63 AnalysisContext context = analysisServer.folderMap[contextFolder]; | 63 AnalysisContext context = analysisServer.folderMap[contextFolder]; |
| 64 context.applyChanges(changeSet); | 64 context.applyChanges(changeSet); |
| 65 analysisServer.schedulePerformAnalysisOperation(context); | 65 analysisServer.schedulePerformAnalysisOperation(context); |
| 66 } | 66 } |
| 67 | 67 |
| 68 @override | 68 @override |
| 69 void removeContext(Folder folder) { | 69 void removeContext(Folder folder) { |
| 70 analysisServer.folderMap.remove(folder); | 70 analysisServer.folderMap.remove(folder); |
| 71 } | 71 } |
| 72 | 72 |
| 73 @override | 73 @override |
| 74 void updateContextPackageMap(Folder contextFolder, | 74 void updateContextPackageMap(Folder contextFolder, |
| 75 Map<String, List<Folder>> packageMap) { | 75 HashMap<String, List<Folder>> packageMap) { |
| 76 AnalysisContext context = analysisServer.folderMap[contextFolder]; | 76 AnalysisContext context = analysisServer.folderMap[contextFolder]; |
| 77 context.sourceFactory = _createSourceFactory(packageMap); | 77 context.sourceFactory = _createSourceFactory(packageMap); |
| 78 analysisServer.schedulePerformAnalysisOperation(context); | 78 analysisServer.schedulePerformAnalysisOperation(context); |
| 79 } | 79 } |
| 80 | 80 |
| 81 /** | 81 /** |
| 82 * Set up a [SourceFactory] that resolves packages using the given | 82 * Set up a [SourceFactory] that resolves packages using the given |
| 83 * [packageMap]. | 83 * [packageMap]. |
| 84 */ | 84 */ |
| 85 SourceFactory _createSourceFactory(Map<String, List<Folder>> packageMap) { | 85 SourceFactory _createSourceFactory(HashMap<String, List<Folder>> packageMap) { |
| 86 List<UriResolver> resolvers = <UriResolver>[ | 86 List<UriResolver> resolvers = <UriResolver>[ |
| 87 new DartUriResolver(analysisServer.defaultSdk), | 87 new DartUriResolver(analysisServer.defaultSdk), |
| 88 new ResourceUriResolver(resourceProvider), | 88 new ResourceUriResolver(resourceProvider), |
| 89 new PackageMapUriResolver(resourceProvider, packageMap) | 89 new PackageMapUriResolver(resourceProvider, packageMap) |
| 90 ]; | 90 ]; |
| 91 return new SourceFactory(resolvers); | 91 return new SourceFactory(resolvers); |
| 92 } | 92 } |
| 93 } | 93 } |
| 94 | 94 |
| 95 /** | 95 /** |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 List<RequestHandler> handlers; | 134 List<RequestHandler> handlers; |
| 135 | 135 |
| 136 /** | 136 /** |
| 137 * The current default [DartSdk]. | 137 * The current default [DartSdk]. |
| 138 */ | 138 */ |
| 139 DartSdk defaultSdk = SHARED_SDK; | 139 DartSdk defaultSdk = SHARED_SDK; |
| 140 | 140 |
| 141 /** | 141 /** |
| 142 * A table mapping [Folder]s to the [AnalysisContext]s associated with them. | 142 * A table mapping [Folder]s to the [AnalysisContext]s associated with them. |
| 143 */ | 143 */ |
| 144 final Map<Folder, AnalysisContext> folderMap = | 144 final HashMap<Folder, AnalysisContext> folderMap = |
| 145 new HashMap<Folder, AnalysisContext>(); | 145 new HashMap<Folder, AnalysisContext>(); |
| 146 | 146 |
| 147 /** | 147 /** |
| 148 * A queue of the operations to perform in this server. | 148 * A queue of the operations to perform in this server. |
| 149 * | 149 * |
| 150 * Invariant: when this queue is non-empty, there is exactly one pending call | 150 * Invariant: when this queue is non-empty, there is exactly one pending call |
| 151 * to [performOperation] on the event queue. When this list is empty, there a
re | 151 * to [performOperation] on the event queue. When this list is empty, there a
re |
| 152 * no calls to [performOperation] on the event queue. | 152 * no calls to [performOperation] on the event queue. |
| 153 */ | 153 */ |
| 154 ServerOperationQueue operationQueue; | 154 ServerOperationQueue operationQueue; |
| 155 | 155 |
| 156 /** | 156 /** |
| 157 * A set of the [ServerService]s to send notifications for. | 157 * A set of the [ServerService]s to send notifications for. |
| 158 */ | 158 */ |
| 159 Set<ServerService> serverServices = new HashSet<ServerService>(); | 159 Set<ServerService> serverServices = new HashSet<ServerService>(); |
| 160 | 160 |
| 161 /** | 161 /** |
| 162 * A table mapping [AnalysisService]s to the file paths for which these | 162 * A table mapping [AnalysisService]s to the file paths for which these |
| 163 * notifications should be sent. | 163 * notifications should be sent. |
| 164 */ | 164 */ |
| 165 Map<AnalysisService, Set<String>> analysisServices = | 165 HashMap<AnalysisService, Set<String>> analysisServices = |
| 166 new HashMap<AnalysisService, Set<String>>(); | 166 new HashMap<AnalysisService, Set<String>>(); |
| 167 | 167 |
| 168 /** | 168 /** |
| 169 * True if any exceptions thrown by analysis should be propagated up the call | 169 * True if any exceptions thrown by analysis should be propagated up the call |
| 170 * stack. | 170 * stack. |
| 171 */ | 171 */ |
| 172 bool rethrowExceptions; | 172 bool rethrowExceptions; |
| 173 | 173 |
| 174 /** | 174 /** |
| 175 * Initialize a newly created server to receive requests from and send | 175 * Initialize a newly created server to receive requests from and send |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 * Send the given [notification] to the client. | 215 * Send the given [notification] to the client. |
| 216 */ | 216 */ |
| 217 void sendNotification(Notification notification) { | 217 void sendNotification(Notification notification) { |
| 218 channel.sendNotification(notification); | 218 channel.sendNotification(notification); |
| 219 } | 219 } |
| 220 | 220 |
| 221 /** | 221 /** |
| 222 * Set the priority files to the given [files]. | 222 * Set the priority files to the given [files]. |
| 223 */ | 223 */ |
| 224 void setPriorityFiles(Request request, List<String> files) { | 224 void setPriorityFiles(Request request, List<String> files) { |
| 225 Map<AnalysisContext, List<Source>> sourceMap = | 225 HashMap<AnalysisContext, List<Source>> sourceMap = |
| 226 new HashMap<AnalysisContext, List<Source>>(); | 226 new HashMap<AnalysisContext, List<Source>>(); |
| 227 List<String> unanalyzed = new List<String>(); | 227 List<String> unanalyzed = new List<String>(); |
| 228 files.forEach((file) { | 228 files.forEach((file) { |
| 229 AnalysisContext analysisContext = _getAnalysisContext(file); | 229 AnalysisContext analysisContext = _getAnalysisContext(file); |
| 230 if (analysisContext == null) { | 230 if (analysisContext == null) { |
| 231 unanalyzed.add(file); | 231 unanalyzed.add(file); |
| 232 } else { | 232 } else { |
| 233 List<Source> sourceList = sourceMap[analysisContext]; | 233 List<Source> sourceList = sourceMap[analysisContext]; |
| 234 if (sourceList == null) { | 234 if (sourceList == null) { |
| 235 sourceList = <Source>[]; | 235 sourceList = <Source>[]; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 * being performed or `null` if analysis is complete. | 392 * being performed or `null` if analysis is complete. |
| 393 */ | 393 */ |
| 394 void sendStatusNotification(ServerOperation operation) { | 394 void sendStatusNotification(ServerOperation operation) { |
| 395 // Only send status when it changes | 395 // Only send status when it changes |
| 396 bool isAnalyzing = operation != null; | 396 bool isAnalyzing = operation != null; |
| 397 if (statusAnalyzing == isAnalyzing) { | 397 if (statusAnalyzing == isAnalyzing) { |
| 398 return; | 398 return; |
| 399 } | 399 } |
| 400 statusAnalyzing = isAnalyzing; | 400 statusAnalyzing = isAnalyzing; |
| 401 Notification notification = new Notification(SERVER_STATUS); | 401 Notification notification = new Notification(SERVER_STATUS); |
| 402 Map<String, Object> analysis = new Map(); | 402 HashMap<String, Object> analysis = new HashMap(); |
| 403 analysis['analyzing'] = isAnalyzing; | 403 analysis['analyzing'] = isAnalyzing; |
| 404 notification.params['analysis'] = analysis; | 404 notification.params['analysis'] = analysis; |
| 405 channel.sendNotification(notification); | 405 channel.sendNotification(notification); |
| 406 } | 406 } |
| 407 | 407 |
| 408 /** | 408 /** |
| 409 * Implementation for `analysis.setAnalysisRoots`. | 409 * Implementation for `analysis.setAnalysisRoots`. |
| 410 * | 410 * |
| 411 * TODO(scheglov) implement complete projects/contexts semantics. | 411 * TODO(scheglov) implement complete projects/contexts semantics. |
| 412 * | 412 * |
| (...skipping 12 matching lines...) Expand all Loading... |
| 425 } on UnimplementedError catch (e) { | 425 } on UnimplementedError catch (e) { |
| 426 throw new RequestFailure( | 426 throw new RequestFailure( |
| 427 new Response.unsupportedFeature( | 427 new Response.unsupportedFeature( |
| 428 requestId, e.message)); | 428 requestId, e.message)); |
| 429 } | 429 } |
| 430 } | 430 } |
| 431 | 431 |
| 432 /** | 432 /** |
| 433 * Implementation for `analysis.updateContent`. | 433 * Implementation for `analysis.updateContent`. |
| 434 */ | 434 */ |
| 435 void updateContent(Map<String, ContentChange> changes) { | 435 void updateContent(HashMap<String, ContentChange> changes) { |
| 436 changes.forEach((file, change) { | 436 changes.forEach((file, change) { |
| 437 AnalysisContext analysisContext = _getAnalysisContext(file); | 437 AnalysisContext analysisContext = _getAnalysisContext(file); |
| 438 // TODO(paulberry): handle the case where a file is referred to by more | 438 // TODO(paulberry): handle the case where a file is referred to by more |
| 439 // than one context (e.g package A depends on package B using a local | 439 // than one context (e.g package A depends on package B using a local |
| 440 // path, user has both packages open for editing in separate contexts, | 440 // path, user has both packages open for editing in separate contexts, |
| 441 // and user modifies a file in package B). | 441 // and user modifies a file in package B). |
| 442 if (analysisContext != null) { | 442 if (analysisContext != null) { |
| 443 Source source = _getSource(file); | 443 Source source = _getSource(file); |
| 444 if (change.offset == null) { | 444 if (change.offset == null) { |
| 445 analysisContext.setContents(source, change.content); | 445 analysisContext.setContents(source, change.content); |
| 446 } else { | 446 } else { |
| 447 analysisContext.setChangedContents(source, change.content, | 447 analysisContext.setChangedContents(source, change.content, |
| 448 change.offset, change.oldLength, change.newLength); | 448 change.offset, change.oldLength, change.newLength); |
| 449 } | 449 } |
| 450 schedulePerformAnalysisOperation(analysisContext); | 450 schedulePerformAnalysisOperation(analysisContext); |
| 451 } | 451 } |
| 452 }); | 452 }); |
| 453 } | 453 } |
| 454 | 454 |
| 455 /** | 455 /** |
| 456 * Implementation for `analysis.setSubscriptions`. | 456 * Implementation for `analysis.setSubscriptions`. |
| 457 */ | 457 */ |
| 458 void setAnalysisSubscriptions(Map<AnalysisService, Set<String>> subscriptions)
{ | 458 void setAnalysisSubscriptions(HashMap<AnalysisService, Set<String>> subscripti
ons) { |
| 459 // send notifications for already analyzed sources | 459 // send notifications for already analyzed sources |
| 460 subscriptions.forEach((service, Set<String> newFiles) { | 460 subscriptions.forEach((service, Set<String> newFiles) { |
| 461 Set<String> oldFiles = analysisServices[service]; | 461 Set<String> oldFiles = analysisServices[service]; |
| 462 Set<String> todoFiles = oldFiles != null ? newFiles.difference(oldFiles) :
newFiles; | 462 Set<String> todoFiles = oldFiles != null ? newFiles.difference(oldFiles) :
newFiles; |
| 463 for (String file in todoFiles) { | 463 for (String file in todoFiles) { |
| 464 if (service == AnalysisService.ERRORS) { | 464 if (service == AnalysisService.ERRORS) { |
| 465 Source source = _getSource(file); | 465 Source source = _getSource(file); |
| 466 AnalysisContext analysisContext = _getAnalysisContext(file); | 466 AnalysisContext analysisContext = _getAnalysisContext(file); |
| 467 List<AnalysisError> errors = analysisContext.getErrors(source).errors; | 467 List<AnalysisError> errors = analysisContext.getErrors(source).errors; |
| 468 sendAnalysisNotificationErrors(this, file, errors); | 468 sendAnalysisNotificationErrors(this, file, errors); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 596 /** | 596 /** |
| 597 * An enumeration of the services provided by the server domain. | 597 * An enumeration of the services provided by the server domain. |
| 598 */ | 598 */ |
| 599 class ServerService extends Enum2<ServerService> { | 599 class ServerService extends Enum2<ServerService> { |
| 600 static const ServerService STATUS = const ServerService('STATUS', 0); | 600 static const ServerService STATUS = const ServerService('STATUS', 0); |
| 601 | 601 |
| 602 static const List<ServerService> VALUES = const [STATUS]; | 602 static const List<ServerService> VALUES = const [STATUS]; |
| 603 | 603 |
| 604 const ServerService(String name, int ordinal) : super(name, ordinal); | 604 const ServerService(String name, int ordinal) : super(name, ordinal); |
| 605 } | 605 } |
| OLD | NEW |