| 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 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 */ | 167 */ |
| 168 StreamController<PriorityChangeEvent> _onPriorityChangeController; | 168 StreamController<PriorityChangeEvent> _onPriorityChangeController; |
| 169 | 169 |
| 170 /** | 170 /** |
| 171 * True if any exceptions thrown by analysis should be propagated up the call | 171 * True if any exceptions thrown by analysis should be propagated up the call |
| 172 * stack. | 172 * stack. |
| 173 */ | 173 */ |
| 174 bool rethrowExceptions; | 174 bool rethrowExceptions; |
| 175 | 175 |
| 176 /** | 176 /** |
| 177 * The stream that is notified when contexts are added or removed. | |
| 178 */ | |
| 179 Stream<ContextsChangedEvent> onContextsChanged; | |
| 180 | |
| 181 /** | |
| 182 * Initialize a newly created server to receive requests from and send | 177 * Initialize a newly created server to receive requests from and send |
| 183 * responses to the given [channel]. | 178 * responses to the given [channel]. |
| 184 * | 179 * |
| 185 * If [rethrowExceptions] is true, then any exceptions thrown by analysis are | 180 * If [rethrowExceptions] is true, then any exceptions thrown by analysis are |
| 186 * propagated up the call stack. The default is true to allow analysis | 181 * propagated up the call stack. The default is true to allow analysis |
| 187 * exceptions to show up in unit tests, but it should be set to false when | 182 * exceptions to show up in unit tests, but it should be set to false when |
| 188 * running a full analysis server. | 183 * running a full analysis server. |
| 189 */ | 184 */ |
| 190 AnalysisServer(this.channel, this.resourceProvider, | 185 AnalysisServer(this.channel, this.resourceProvider, |
| 191 PackageMapProvider packageMapProvider, this.index, this.defaultSdk, | 186 PackageMapProvider packageMapProvider, this.index, this.defaultSdk, |
| 192 {this.rethrowExceptions: true}) { | 187 {this.rethrowExceptions: true}) { |
| 193 searchEngine = createSearchEngine(index); | 188 searchEngine = createSearchEngine(index); |
| 194 operationQueue = new ServerOperationQueue(this); | 189 operationQueue = new ServerOperationQueue(this); |
| 195 contextDirectoryManager = | 190 contextDirectoryManager = |
| 196 new ServerContextManager(this, resourceProvider, packageMapProvider); | 191 new ServerContextManager(this, resourceProvider, packageMapProvider); |
| 197 onContextsChanged = | |
| 198 contextDirectoryManager.onContextsChanged.asBroadcastStream(); | |
| 199 AnalysisEngine.instance.logger = new AnalysisLogger(); | 192 AnalysisEngine.instance.logger = new AnalysisLogger(); |
| 200 _onAnalysisStartedController = new StreamController.broadcast(); | 193 _onAnalysisStartedController = new StreamController.broadcast(); |
| 201 _onAnalysisCompleteController = new StreamController.broadcast(); | 194 _onAnalysisCompleteController = new StreamController.broadcast(); |
| 202 _onFileAnalyzedController = new StreamController.broadcast(); | 195 _onFileAnalyzedController = new StreamController.broadcast(); |
| 203 _onPriorityChangeController = | 196 _onPriorityChangeController = |
| 204 new StreamController<PriorityChangeEvent>.broadcast(); | 197 new StreamController<PriorityChangeEvent>.broadcast(); |
| 205 running = true; | 198 running = true; |
| 206 Notification notification = new ServerConnectedParams().toNotification(); | 199 Notification notification = new ServerConnectedParams().toNotification(); |
| 207 channel.sendNotification(notification); | 200 channel.sendNotification(notification); |
| 208 channel.listen(handleRequest, onDone: done, onError: error); | 201 channel.listen(handleRequest, onDone: done, onError: error); |
| 209 } | 202 } |
| 210 | 203 |
| 211 /** | 204 /** |
| 212 * The stream that is notified when analysis is complete. | 205 * The stream that is notified when analysis is complete. |
| 213 */ | 206 */ |
| 214 Stream get onAnalysisComplete => _onAnalysisCompleteController.stream; | 207 Stream get onAnalysisComplete => _onAnalysisCompleteController.stream; |
| 215 | 208 |
| 216 /** | 209 /** |
| 217 * The stream that is notified when analysis of a context is started. | 210 * The stream that is notified when analysis of a context is started. |
| 218 */ | 211 */ |
| 219 Stream<AnalysisContext> get onAnalysisStarted { | 212 Stream<AnalysisContext> get onAnalysisStarted { |
| 220 return _onAnalysisStartedController.stream; | 213 return _onAnalysisStartedController.stream; |
| 221 } | 214 } |
| 222 | 215 |
| 223 /** | 216 /** |
| 217 * The stream that is notified when contexts are added or removed. |
| 218 */ |
| 219 Stream<ContextsChangedEvent> get onContextsChanged => |
| 220 contextDirectoryManager.onContextsChanged; |
| 221 |
| 222 /** |
| 224 * The stream that is notified when a single file has been analyzed. | 223 * The stream that is notified when a single file has been analyzed. |
| 225 */ | 224 */ |
| 226 Stream get onFileAnalyzed => _onFileAnalyzedController.stream; | 225 Stream get onFileAnalyzed => _onFileAnalyzedController.stream; |
| 227 | 226 |
| 228 /** | 227 /** |
| 229 * The stream that is notified when priority sources change. | 228 * The stream that is notified when priority sources change. |
| 230 */ | 229 */ |
| 231 Stream<PriorityChangeEvent> get onPriorityChange => | 230 Stream<PriorityChangeEvent> get onPriorityChange => |
| 232 _onPriorityChangeController.stream; | 231 _onPriorityChangeController.stream; |
| 233 | 232 |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 for (CompilationUnit unit in units) { | 386 for (CompilationUnit unit in units) { |
| 388 AstNode node = new NodeLocator.con1(offset).searchWithin(unit); | 387 AstNode node = new NodeLocator.con1(offset).searchWithin(unit); |
| 389 if (node != null) { | 388 if (node != null) { |
| 390 nodes.add(node); | 389 nodes.add(node); |
| 391 } | 390 } |
| 392 } | 391 } |
| 393 return nodes; | 392 return nodes; |
| 394 } | 393 } |
| 395 | 394 |
| 396 /** | 395 /** |
| 396 * Returns resolved [CompilationUnit]s of the Dart file with the given [path]. |
| 397 * |
| 398 * May be empty, but not `null`. |
| 399 */ |
| 400 List<CompilationUnit> getResolvedCompilationUnits(String path) { |
| 401 List<CompilationUnit> units = <CompilationUnit>[]; |
| 402 // prepare AnalysisContext |
| 403 AnalysisContext context = getAnalysisContext(path); |
| 404 if (context == null) { |
| 405 return units; |
| 406 } |
| 407 // add a unit for each unit/library combination |
| 408 Source unitSource = getSource(path); |
| 409 List<Source> librarySources = context.getLibrariesContaining(unitSource); |
| 410 for (Source librarySource in librarySources) { |
| 411 CompilationUnit unit = |
| 412 context.resolveCompilationUnit2(unitSource, librarySource); |
| 413 if (unit != null) { |
| 414 units.add(unit); |
| 415 } |
| 416 } |
| 417 // done |
| 418 return units; |
| 419 } |
| 420 |
| 421 /** |
| 397 * Returns the [CompilationUnit] of the Dart file with the given [path] that | 422 * Returns the [CompilationUnit] of the Dart file with the given [path] that |
| 398 * should be used to resend notifications for already resolved unit. | 423 * should be used to resend notifications for already resolved unit. |
| 399 * Returns `null` if the file is not a part of any context, library has not | 424 * Returns `null` if the file is not a part of any context, library has not |
| 400 * been yet resolved, or any problem happened. | 425 * been yet resolved, or any problem happened. |
| 401 */ | 426 */ |
| 402 CompilationUnit getResolvedCompilationUnitToResendNotification(String path) { | 427 CompilationUnit getResolvedCompilationUnitToResendNotification(String path) { |
| 403 // prepare AnalysisContext | 428 // prepare AnalysisContext |
| 404 AnalysisContext context = getAnalysisContext(path); | 429 AnalysisContext context = getAnalysisContext(path); |
| 405 if (context == null) { | 430 if (context == null) { |
| 406 return null; | 431 return null; |
| 407 } | 432 } |
| 408 // prepare sources | 433 // prepare sources |
| 409 Source unitSource = getSource(path); | 434 Source unitSource = getSource(path); |
| 410 List<Source> librarySources = context.getLibrariesContaining(unitSource); | 435 List<Source> librarySources = context.getLibrariesContaining(unitSource); |
| 411 if (librarySources.isEmpty) { | 436 if (librarySources.isEmpty) { |
| 412 return null; | 437 return null; |
| 413 } | 438 } |
| 414 // if library has not been resolved yet, the unit will be resolved later | 439 // if library has not been resolved yet, the unit will be resolved later |
| 415 Source librarySource = librarySources[0]; | 440 Source librarySource = librarySources[0]; |
| 416 if (context.getLibraryElement(librarySource) == null) { | 441 if (context.getLibraryElement(librarySource) == null) { |
| 417 return null; | 442 return null; |
| 418 } | 443 } |
| 419 // if library has been already resolved, resolve unit | 444 // if library has been already resolved, resolve unit |
| 420 return context.resolveCompilationUnit2(unitSource, librarySource); | 445 return context.resolveCompilationUnit2(unitSource, librarySource); |
| 421 } | 446 } |
| 422 | 447 |
| 423 /** | 448 /** |
| 424 * Returns resolved [CompilationUnit]s of the Dart file with the given [path]. | |
| 425 * | |
| 426 * May be empty, but not `null`. | |
| 427 */ | |
| 428 List<CompilationUnit> getResolvedCompilationUnits(String path) { | |
| 429 List<CompilationUnit> units = <CompilationUnit>[]; | |
| 430 // prepare AnalysisContext | |
| 431 AnalysisContext context = getAnalysisContext(path); | |
| 432 if (context == null) { | |
| 433 return units; | |
| 434 } | |
| 435 // add a unit for each unit/library combination | |
| 436 Source unitSource = getSource(path); | |
| 437 List<Source> librarySources = context.getLibrariesContaining(unitSource); | |
| 438 for (Source librarySource in librarySources) { | |
| 439 CompilationUnit unit = | |
| 440 context.resolveCompilationUnit2(unitSource, librarySource); | |
| 441 if (unit != null) { | |
| 442 units.add(unit); | |
| 443 } | |
| 444 } | |
| 445 // done | |
| 446 return units; | |
| 447 } | |
| 448 | |
| 449 /** | |
| 450 * Return the [Source] of the Dart file with the given [path]. | 449 * Return the [Source] of the Dart file with the given [path]. |
| 451 */ | 450 */ |
| 452 Source getSource(String path) { | 451 Source getSource(String path) { |
| 453 // try SDK | 452 // try SDK |
| 454 { | 453 { |
| 455 Uri uri = resourceProvider.pathContext.toUri(path); | 454 Uri uri = resourceProvider.pathContext.toUri(path); |
| 456 Source sdkSource = defaultSdk.fromFileUri(uri); | 455 Source sdkSource = defaultSdk.fromFileUri(uri); |
| 457 if (sdkSource != null) { | 456 if (sdkSource != null) { |
| 458 return sdkSource; | 457 return sdkSource; |
| 459 } | 458 } |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 935 /** | 934 /** |
| 936 * The contexts that were removed from the server. | 935 * The contexts that were removed from the server. |
| 937 */ | 936 */ |
| 938 final List<AnalysisContext> removed; | 937 final List<AnalysisContext> removed; |
| 939 | 938 |
| 940 ContextsChangedEvent({this.added: AnalysisContext.EMPTY_LIST, this.changed: | 939 ContextsChangedEvent({this.added: AnalysisContext.EMPTY_LIST, this.changed: |
| 941 AnalysisContext.EMPTY_LIST, this.removed: AnalysisContext.EMPTY_LIST}); | 940 AnalysisContext.EMPTY_LIST, this.removed: AnalysisContext.EMPTY_LIST}); |
| 942 } | 941 } |
| 943 | 942 |
| 944 /** | 943 /** |
| 945 * A [PriorityChangeEvent] indicates which sources are currently prioritized | 944 * A [PriorityChangeEvent] indicates the set the priority files has changed. |
| 946 * and should be analyzed before other sources. | |
| 947 */ | 945 */ |
| 948 class PriorityChangeEvent { | 946 class PriorityChangeEvent { |
| 949 final Source firstSource; | 947 final Source firstSource; |
| 950 | 948 |
| 951 PriorityChangeEvent(this.firstSource); | 949 PriorityChangeEvent(this.firstSource); |
| 952 } | 950 } |
| 953 | 951 |
| 954 class ServerContextManager extends ContextManager { | 952 class ServerContextManager extends ContextManager { |
| 955 final AnalysisServer analysisServer; | 953 final AnalysisServer analysisServer; |
| 956 | 954 |
| 957 /** | 955 /** |
| 958 * The default options used to create new analysis contexts. | 956 * The default options used to create new analysis contexts. |
| 959 */ | 957 */ |
| 960 AnalysisOptionsImpl defaultOptions = new AnalysisOptionsImpl(); | 958 AnalysisOptionsImpl defaultOptions = new AnalysisOptionsImpl(); |
| 961 | 959 |
| 962 /** | 960 /** |
| 963 * The controller for sending [ContextsChangedEvent]s. | 961 * The controller for sending [ContextsChangedEvent]s. |
| 964 */ | 962 */ |
| 965 StreamController<ContextsChangedEvent> _onContextsChangedController; | 963 StreamController<ContextsChangedEvent> _onContextsChangedController; |
| 966 | 964 |
| 967 ServerContextManager(this.analysisServer, ResourceProvider resourceProvider, | 965 ServerContextManager(this.analysisServer, ResourceProvider resourceProvider, |
| 968 PackageMapProvider packageMapProvider) | 966 PackageMapProvider packageMapProvider) |
| 969 : super(resourceProvider, packageMapProvider) { | 967 : super(resourceProvider, packageMapProvider) { |
| 970 _onContextsChangedController = new StreamController<ContextsChangedEvent>(); | 968 _onContextsChangedController = |
| 969 new StreamController<ContextsChangedEvent>.broadcast(); |
| 971 } | 970 } |
| 972 | 971 |
| 973 /** | 972 /** |
| 974 * The stream that is notified when contexts are added or removed. | 973 * The stream that is notified when contexts are added or removed. |
| 975 */ | 974 */ |
| 976 Stream<ContextsChangedEvent> get onContextsChanged => | 975 Stream<ContextsChangedEvent> get onContextsChanged => |
| 977 _onContextsChangedController.stream; | 976 _onContextsChangedController.stream; |
| 978 | 977 |
| 979 @override | 978 @override |
| 980 void addContext(Folder folder, UriResolver packageUriResolver) { | 979 void addContext(Folder folder, UriResolver packageUriResolver) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1024 * [packageUriResolver]. | 1023 * [packageUriResolver]. |
| 1025 */ | 1024 */ |
| 1026 SourceFactory _createSourceFactory(UriResolver packageUriResolver) { | 1025 SourceFactory _createSourceFactory(UriResolver packageUriResolver) { |
| 1027 List<UriResolver> resolvers = <UriResolver>[ | 1026 List<UriResolver> resolvers = <UriResolver>[ |
| 1028 new DartUriResolver(analysisServer.defaultSdk), | 1027 new DartUriResolver(analysisServer.defaultSdk), |
| 1029 new ResourceUriResolver(resourceProvider), | 1028 new ResourceUriResolver(resourceProvider), |
| 1030 packageUriResolver]; | 1029 packageUriResolver]; |
| 1031 return new SourceFactory(resolvers); | 1030 return new SourceFactory(resolvers); |
| 1032 } | 1031 } |
| 1033 } | 1032 } |
| OLD | NEW |