| 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 domain.completion; | 5 library domain.completion; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:analysis_server/plugin/protocol/protocol.dart'; | 9 import 'package:analysis_server/plugin/protocol/protocol.dart'; |
| 10 import 'package:analysis_server/src/analysis_server.dart'; | 10 import 'package:analysis_server/src/analysis_server.dart'; |
| 11 import 'package:analysis_server/src/constants.dart'; | 11 import 'package:analysis_server/src/constants.dart'; |
| 12 import 'package:analysis_server/src/provisional/completion/completion_core.dart'
; | 12 import 'package:analysis_server/src/provisional/completion/completion_core.dart'
; |
| 13 import 'package:analysis_server/src/services/completion/completion_core.dart'; | 13 import 'package:analysis_server/src/services/completion/completion_core.dart'; |
| 14 import 'package:analysis_server/src/services/completion/completion_performance.d
art'; | 14 import 'package:analysis_server/src/services/completion/completion_performance.d
art'; |
| 15 import 'package:analyzer/src/generated/engine.dart'; | 15 import 'package:analyzer/src/dart/analysis/driver.dart'; |
| 16 import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult; |
| 17 import 'package:analyzer/src/source/source_resource.dart'; |
| 16 import 'package:analyzer/src/generated/source.dart'; | 18 import 'package:analyzer/src/generated/source.dart'; |
| 17 | 19 |
| 18 /** | 20 /** |
| 19 * Instances of the class [CompletionDomainHandler] implement a [RequestHandler] | 21 * Instances of the class [CompletionDomainHandler] implement a [RequestHandler] |
| 20 * that handles requests in the search domain. | 22 * that handles requests in the search domain. |
| 21 */ | 23 */ |
| 22 class CompletionDomainHandler implements RequestHandler { | 24 class CompletionDomainHandler implements RequestHandler { |
| 23 /** | 25 /** |
| 24 * The maximum number of performance measurements to keep. | 26 * The maximum number of performance measurements to keep. |
| 25 */ | 27 */ |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 // TODO (danrubel) if request is obsolete | 97 // TODO (danrubel) if request is obsolete |
| 96 // (processAnalysisRequest returns false) | 98 // (processAnalysisRequest returns false) |
| 97 // then send empty results | 99 // then send empty results |
| 98 | 100 |
| 99 return new CompletionResult( | 101 return new CompletionResult( |
| 100 request.replacementOffset, request.replacementLength, suggestions); | 102 request.replacementOffset, request.replacementLength, suggestions); |
| 101 } | 103 } |
| 102 | 104 |
| 103 @override | 105 @override |
| 104 Response handleRequest(Request request) { | 106 Response handleRequest(Request request) { |
| 105 if (server.options.enableNewAnalysisDriver) { | |
| 106 // TODO(scheglov) implement for the new analysis driver | |
| 107 String completionId = (_nextCompletionId++).toString(); | |
| 108 new Future(() { | |
| 109 sendCompletionNotification(completionId, 0, 0, []); | |
| 110 }); | |
| 111 return new CompletionGetSuggestionsResult(completionId) | |
| 112 .toResponse(request.id); | |
| 113 } | |
| 114 if (server.searchEngine == null) { | 107 if (server.searchEngine == null) { |
| 115 return new Response.noIndexGenerated(request); | 108 return new Response.noIndexGenerated(request); |
| 116 } | 109 } |
| 117 return runZoned(() { | 110 runZoned(() { |
| 118 try { | 111 try { |
| 119 String requestName = request.method; | 112 String requestName = request.method; |
| 120 if (requestName == COMPLETION_GET_SUGGESTIONS) { | 113 if (requestName == COMPLETION_GET_SUGGESTIONS) { |
| 121 return processRequest(request); | 114 processRequest(request); |
| 122 } | 115 } |
| 123 } on RequestFailure catch (exception) { | 116 } on RequestFailure catch (exception) { |
| 124 return exception.response; | 117 return exception.response; |
| 125 } | 118 } |
| 126 return null; | 119 return null; |
| 127 }, onError: (exception, stackTrace) { | 120 }, onError: (exception, stackTrace) { |
| 128 server.sendServerErrorNotification( | 121 server.sendServerErrorNotification( |
| 129 'Failed to handle completion domain request: ${request.toJson()}', | 122 'Failed to handle completion domain request: ${request.toJson()}', |
| 130 exception, | 123 exception, |
| 131 stackTrace); | 124 stackTrace); |
| 132 }); | 125 }); |
| 126 return Response.DELAYED_RESPONSE; |
| 133 } | 127 } |
| 134 | 128 |
| 135 /** | 129 /** |
| 136 * Process a `completion.getSuggestions` request. | 130 * Process a `completion.getSuggestions` request. |
| 137 */ | 131 */ |
| 138 Response processRequest(Request request) { | 132 Future<Null> processRequest(Request request) async { |
| 139 performance = new CompletionPerformance(); | 133 performance = new CompletionPerformance(); |
| 140 | 134 |
| 141 // extract and validate params | 135 // extract and validate params |
| 142 CompletionGetSuggestionsParams params = | 136 CompletionGetSuggestionsParams params = |
| 143 new CompletionGetSuggestionsParams.fromRequest(request); | 137 new CompletionGetSuggestionsParams.fromRequest(request); |
| 144 ContextSourcePair contextSource = server.getContextSourcePair(params.file); | 138 |
| 145 AnalysisContext context = contextSource.context; | 139 AnalysisResult result; |
| 146 Source source = contextSource.source; | 140 AnalysisContext context; |
| 147 if (context == null || !context.exists(source)) { | 141 Source source; |
| 148 return new Response.unknownSource(request); | 142 if (server.options.enableNewAnalysisDriver) { |
| 149 } | 143 result = await server.getAnalysisResult(params.file); |
| 150 TimestampedData<String> contents = context.getContents(source); | 144 |
| 151 if (params.offset < 0 || params.offset > contents.data.length) { | 145 if (result == null) { |
| 152 return new Response.invalidParameter( | 146 server.sendResponse(new Response.unknownSource(request)); |
| 153 request, | 147 return; |
| 154 'params.offset', | 148 } |
| 155 'Expected offset between 0 and source length inclusive,' | 149 |
| 156 ' but found ${params.offset}'); | 150 if (params.offset < 0 || params.offset > result.content.length) { |
| 151 server.sendResponse(new Response.invalidParameter( |
| 152 request, |
| 153 'params.offset', |
| 154 'Expected offset between 0 and source length inclusive,' |
| 155 ' but found ${params.offset}')); |
| 156 return; |
| 157 } |
| 158 |
| 159 source = new FileSource( |
| 160 server.resourceProvider.getFile(result.path), result.uri); |
| 161 } else { |
| 162 ContextSourcePair contextSource = |
| 163 server.getContextSourcePair(params.file); |
| 164 |
| 165 context = contextSource.context; |
| 166 source = contextSource.source; |
| 167 if (context == null || !context.exists(source)) { |
| 168 server.sendResponse(new Response.unknownSource(request)); |
| 169 return; |
| 170 } |
| 171 |
| 172 TimestampedData<String> contents = context.getContents(source); |
| 173 if (params.offset < 0 || params.offset > contents.data.length) { |
| 174 server.sendResponse(new Response.invalidParameter( |
| 175 request, |
| 176 'params.offset', |
| 177 'Expected offset between 0 and source length inclusive,' |
| 178 ' but found ${params.offset}')); |
| 179 return; |
| 180 } |
| 157 } | 181 } |
| 158 | 182 |
| 159 recordRequest(performance, context, source, params.offset); | 183 recordRequest(performance, context, source, params.offset); |
| 160 | 184 |
| 161 CompletionRequestImpl completionRequest = new CompletionRequestImpl( | 185 CompletionRequestImpl completionRequest = new CompletionRequestImpl( |
| 186 result, |
| 162 context, | 187 context, |
| 163 server.resourceProvider, | 188 server.resourceProvider, |
| 164 server.searchEngine, | 189 server.searchEngine, |
| 165 source, | 190 source, |
| 166 params.offset, | 191 params.offset, |
| 167 performance); | 192 performance); |
| 168 String completionId = (_nextCompletionId++).toString(); | 193 String completionId = (_nextCompletionId++).toString(); |
| 169 | 194 |
| 170 _abortCurrentRequest(); | 195 _abortCurrentRequest(); |
| 171 _currentRequest = completionRequest; | 196 _currentRequest = completionRequest; |
| 172 | 197 |
| 198 // initial response without results |
| 199 server.sendResponse(new CompletionGetSuggestionsResult(completionId) |
| 200 .toResponse(request.id)); |
| 201 |
| 173 // Compute suggestions in the background | 202 // Compute suggestions in the background |
| 174 computeSuggestions(completionRequest).then((CompletionResult result) { | 203 computeSuggestions(completionRequest).then((CompletionResult result) { |
| 175 const SEND_NOTIFICATION_TAG = 'send notification'; | 204 const SEND_NOTIFICATION_TAG = 'send notification'; |
| 176 performance.logStartTime(SEND_NOTIFICATION_TAG); | 205 performance.logStartTime(SEND_NOTIFICATION_TAG); |
| 177 sendCompletionNotification(completionId, result.replacementOffset, | 206 sendCompletionNotification(completionId, result.replacementOffset, |
| 178 result.replacementLength, result.suggestions); | 207 result.replacementLength, result.suggestions); |
| 179 performance.logElapseTime(SEND_NOTIFICATION_TAG); | 208 performance.logElapseTime(SEND_NOTIFICATION_TAG); |
| 180 | 209 |
| 181 performance.notificationCount = 1; | 210 performance.notificationCount = 1; |
| 182 performance.logFirstNotificationComplete('notification 1 complete'); | 211 performance.logFirstNotificationComplete('notification 1 complete'); |
| 183 performance.suggestionCountFirst = result.suggestions.length; | 212 performance.suggestionCountFirst = result.suggestions.length; |
| 184 performance.suggestionCountLast = result.suggestions.length; | 213 performance.suggestionCountLast = result.suggestions.length; |
| 185 performance.complete(); | 214 performance.complete(); |
| 186 }).whenComplete(() { | 215 }).whenComplete(() { |
| 187 if (_currentRequest == completionRequest) { | 216 if (_currentRequest == completionRequest) { |
| 188 _currentRequest = null; | 217 _currentRequest = null; |
| 189 } | 218 } |
| 190 }); | 219 }); |
| 191 | |
| 192 // initial response without results | |
| 193 return new CompletionGetSuggestionsResult(completionId) | |
| 194 .toResponse(request.id); | |
| 195 } | 220 } |
| 196 | 221 |
| 197 /** | 222 /** |
| 198 * If tracking code completion performance over time, then | 223 * If tracking code completion performance over time, then |
| 199 * record addition information about the request in the performance record. | 224 * record addition information about the request in the performance record. |
| 200 */ | 225 */ |
| 201 void recordRequest(CompletionPerformance performance, AnalysisContext context, | 226 void recordRequest(CompletionPerformance performance, AnalysisContext context, |
| 202 Source source, int offset) { | 227 Source source, int offset) { |
| 203 performance.source = source; | 228 performance.source = source; |
| 204 if (performanceListMaxLength == 0 || context == null || source == null) { | 229 if (performanceListMaxLength == 0 || context == null || source == null) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 final int replacementOffset; | 281 final int replacementOffset; |
| 257 | 282 |
| 258 /** | 283 /** |
| 259 * The suggested completions. | 284 * The suggested completions. |
| 260 */ | 285 */ |
| 261 final List<CompletionSuggestion> suggestions; | 286 final List<CompletionSuggestion> suggestions; |
| 262 | 287 |
| 263 CompletionResult( | 288 CompletionResult( |
| 264 this.replacementOffset, this.replacementLength, this.suggestions); | 289 this.replacementOffset, this.replacementLength, this.suggestions); |
| 265 } | 290 } |
| OLD | NEW |