| 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 edit.domain; | 5 library edit.domain; |
| 6 | 6 |
| 7 import 'dart:async'; |
| 8 |
| 7 import 'package:analysis_server/src/analysis_server.dart'; | 9 import 'package:analysis_server/src/analysis_server.dart'; |
| 8 import 'package:analysis_server/src/constants.dart'; | 10 import 'package:analysis_server/src/constants.dart'; |
| 9 import 'package:analysis_server/src/edit/fix.dart'; | 11 import 'package:analysis_server/src/edit/fix.dart'; |
| 10 import 'package:analysis_server/src/protocol.dart'; | 12 import 'package:analysis_server/src/protocol.dart'; |
| 13 import 'package:analysis_server/src/protocol2.dart' as protocol show |
| 14 LinkedEditGroup; |
| 11 import 'package:analysis_server/src/protocol2.dart' show AnalysisError, | 15 import 'package:analysis_server/src/protocol2.dart' show AnalysisError, |
| 12 EditGetAssistsParams, EditGetAvailableRefactoringsParams, | 16 EditGetAssistsParams, EditGetAvailableRefactoringsParams, |
| 13 EditGetAvailableRefactoringsResult, EditGetFixesParams, RefactoringKind; | 17 EditGetAvailableRefactoringsResult, EditGetFixesParams, |
| 18 EditGetRefactoringParams, EditGetRefactoringResult, LinkedEditGroup, Locatio
n, |
| 19 RefactoringKind, RefactoringProblem, RefactoringProblemSeverity, RenameOptio
ns, |
| 20 SourceChange; |
| 14 import 'package:analysis_server/src/services/correction/assist.dart'; | 21 import 'package:analysis_server/src/services/correction/assist.dart'; |
| 15 import 'package:analysis_server/src/services/correction/change.dart'; | 22 import 'package:analysis_server/src/services/correction/change.dart'; |
| 16 import 'package:analysis_server/src/services/correction/fix.dart'; | 23 import 'package:analysis_server/src/services/correction/fix.dart'; |
| 24 import 'package:analysis_server/src/services/correction/status.dart'; |
| 17 import 'package:analysis_server/src/services/json.dart'; | 25 import 'package:analysis_server/src/services/json.dart'; |
| 18 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; | 26 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; |
| 19 import 'package:analysis_server/src/services/search/search_engine.dart'; | 27 import 'package:analysis_server/src/services/search/search_engine.dart'; |
| 20 import 'package:analyzer/src/generated/ast.dart'; | 28 import 'package:analyzer/src/generated/ast.dart'; |
| 21 import 'package:analyzer/src/generated/element.dart'; | 29 import 'package:analyzer/src/generated/element.dart'; |
| 22 import 'package:analyzer/src/generated/engine.dart' as engine; | 30 import 'package:analyzer/src/generated/engine.dart' as engine; |
| 23 import 'package:analyzer/src/generated/error.dart' as engine; | 31 import 'package:analyzer/src/generated/error.dart' as engine; |
| 24 import 'package:analyzer/src/generated/source.dart'; | 32 import 'package:analyzer/src/generated/source.dart'; |
| 25 | 33 |
| 26 | 34 |
| 27 /** | 35 /** |
| 28 * Instances of the class [EditDomainHandler] implement a [RequestHandler] | 36 * Instances of the class [EditDomainHandler] implement a [RequestHandler] |
| 29 * that handles requests in the edit domain. | 37 * that handles requests in the edit domain. |
| 30 */ | 38 */ |
| 31 class EditDomainHandler implements RequestHandler { | 39 class EditDomainHandler implements RequestHandler { |
| 32 /** | 40 /** |
| 33 * The analysis server that is using this handler to process requests. | 41 * The analysis server that is using this handler to process requests. |
| 34 */ | 42 */ |
| 35 final AnalysisServer server; | 43 final AnalysisServer server; |
| 36 | 44 |
| 37 /** | 45 /** |
| 38 * The [SearchEngine] for this server. | 46 * The [SearchEngine] for this server. |
| 39 */ | 47 */ |
| 40 SearchEngine searchEngine; | 48 SearchEngine searchEngine; |
| 41 | 49 |
| 50 _RefactoringManager refactoringManager; |
| 51 |
| 42 /** | 52 /** |
| 43 * Initialize a newly created handler to handle requests for the given [server
]. | 53 * Initialize a newly created handler to handle requests for the given [server
]. |
| 44 */ | 54 */ |
| 45 EditDomainHandler(this.server) { | 55 EditDomainHandler(this.server) { |
| 46 searchEngine = server.searchEngine; | 56 searchEngine = server.searchEngine; |
| 57 refactoringManager = new _RefactoringManager(server, searchEngine); |
| 47 } | 58 } |
| 48 | 59 |
| 49 Response getAssists(Request request) { | 60 Response getAssists(Request request) { |
| 50 var params = new EditGetAssistsParams.fromRequest(request); | 61 var params = new EditGetAssistsParams.fromRequest(request); |
| 51 List<Change> changes = <Change>[]; | 62 List<Change> changes = <Change>[]; |
| 52 List<CompilationUnit> units = | 63 List<CompilationUnit> units = |
| 53 server.getResolvedCompilationUnits(params.file); | 64 server.getResolvedCompilationUnits(params.file); |
| 54 if (units.isNotEmpty) { | 65 if (units.isNotEmpty) { |
| 55 CompilationUnit unit = units[0]; | 66 CompilationUnit unit = units[0]; |
| 56 List<Assist> assists = | 67 List<Assist> assists = |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 } | 134 } |
| 124 } | 135 } |
| 125 // respond | 136 // respond |
| 126 return new Response(request.id)..setResult(FIXES, errorFixesList); | 137 return new Response(request.id)..setResult(FIXES, errorFixesList); |
| 127 } | 138 } |
| 128 | 139 |
| 129 @override | 140 @override |
| 130 Response handleRequest(Request request) { | 141 Response handleRequest(Request request) { |
| 131 try { | 142 try { |
| 132 String requestName = request.method; | 143 String requestName = request.method; |
| 133 if (requestName == EDIT_GET_AVAILABLE_REFACTORINGS) { | 144 if (requestName == EDIT_GET_ASSISTS) { |
| 145 return getAssists(request); |
| 146 } else if (requestName == EDIT_GET_AVAILABLE_REFACTORINGS) { |
| 134 return getAvailableRefactorings(request); | 147 return getAvailableRefactorings(request); |
| 135 } else if (requestName == EDIT_GET_ASSISTS) { | |
| 136 return getAssists(request); | |
| 137 } else if (requestName == EDIT_GET_FIXES) { | 148 } else if (requestName == EDIT_GET_FIXES) { |
| 138 return getFixes(request); | 149 return getFixes(request); |
| 150 } else if (requestName == EDIT_GET_REFACTORING) { |
| 151 refactoringManager.getRefactoring(request); |
| 152 return Response.DELAYED_RESPONSE; |
| 139 } | 153 } |
| 140 } on RequestFailure catch (exception) { | 154 } on RequestFailure catch (exception) { |
| 141 return exception.response; | 155 return exception.response; |
| 142 } | 156 } |
| 143 return null; | 157 return null; |
| 144 } | 158 } |
| 145 } | 159 } |
| 160 |
| 161 |
| 162 /** |
| 163 * An object managing a single [Refactoring] instance. |
| 164 * |
| 165 * The instance is identified by its kind, file, offset and length. |
| 166 * It is initialized when the a set of parameters is given for the first time. |
| 167 * All subsequent requests are performed on this [Refactoring] instance. |
| 168 * |
| 169 * Once new set of parameters is received, the previous [Refactoring] instance |
| 170 * is invalidated and a new one is created and initialized. |
| 171 */ |
| 172 class _RefactoringManager { |
| 173 final AnalysisServer server; |
| 174 final SearchEngine searchEngine; |
| 175 |
| 176 RefactoringKind kind; |
| 177 String file; |
| 178 int offset; |
| 179 int length; |
| 180 Refactoring refactoring; |
| 181 RefactoringStatus initStatus; |
| 182 RefactoringStatus optionsStatus; |
| 183 RefactoringStatus finalStatus; |
| 184 |
| 185 String requestId; |
| 186 EditGetRefactoringResult result; |
| 187 |
| 188 _RefactoringManager(this.server, this.searchEngine) { |
| 189 _reset(); |
| 190 } |
| 191 |
| 192 bool get _hasFatalError { |
| 193 return initStatus.hasFatalError || |
| 194 optionsStatus.hasFatalError || |
| 195 finalStatus.hasFatalError; |
| 196 } |
| 197 |
| 198 void getRefactoring(Request request) { |
| 199 // prepare for processing the request |
| 200 requestId = request.id; |
| 201 result = new EditGetRefactoringResult(<RefactoringProblem>[]); |
| 202 // process the request |
| 203 var params = new EditGetRefactoringParams.fromRequest(request); |
| 204 _init(params.kind, params.file, params.offset, params.length).then((_) { |
| 205 if (_hasFatalError) { |
| 206 return _sendResultResponse(); |
| 207 } |
| 208 // set options |
| 209 if (params.options == null) { |
| 210 return _sendResultResponse(); |
| 211 } |
| 212 optionsStatus = _setOptions(params.options); |
| 213 if (_hasFatalError) { |
| 214 return _sendResultResponse(); |
| 215 } |
| 216 // done if just validation |
| 217 if (params.validateOnly) { |
| 218 return _sendResultResponse(); |
| 219 } |
| 220 // validation and create change |
| 221 refactoring.checkFinalConditions().then((_finalStatus) { |
| 222 finalStatus = _finalStatus; |
| 223 if (_hasFatalError) { |
| 224 return _sendResultResponse(); |
| 225 } |
| 226 return refactoring.createChange().then((change) { |
| 227 result.change = new SourceChange( |
| 228 change.message, |
| 229 change.fileEdits, |
| 230 <protocol.LinkedEditGroup>[]); |
| 231 return _sendResultResponse(); |
| 232 }); |
| 233 }); |
| 234 }); |
| 235 } |
| 236 |
| 237 /** |
| 238 * Initializes this context to perform a refactoring with the specified |
| 239 * parameters. The existing [Refactoring] is reused or created as needed. |
| 240 */ |
| 241 Future<RefactoringStatus> _init(RefactoringKind kind, String file, int offset, |
| 242 int length) { |
| 243 List<RefactoringProblem> problems = <RefactoringProblem>[]; |
| 244 // check if we can continue with the existing Refactoring instance |
| 245 if (this.kind == kind && |
| 246 this.file == file && |
| 247 this.offset == offset && |
| 248 this.length == length) { |
| 249 return new Future.value(initStatus); |
| 250 } |
| 251 _reset(); |
| 252 this.kind = kind; |
| 253 this.file = file; |
| 254 this.offset = offset; |
| 255 this.length = length; |
| 256 // create a new Refactoring instance |
| 257 if (kind == RefactoringKind.RENAME) { |
| 258 List<Element> elements = server.getElementsAtOffset(file, offset); |
| 259 if (elements.isNotEmpty) { |
| 260 Element element = elements[0]; |
| 261 refactoring = new RenameRefactoring(searchEngine, element); |
| 262 } |
| 263 } |
| 264 if (refactoring == null) { |
| 265 initStatus = |
| 266 new RefactoringStatus.fatal('Unable to create a refactoring'); |
| 267 return new Future.value(initStatus); |
| 268 } |
| 269 // check initial conditions |
| 270 return refactoring.checkInitialConditions().then((status) { |
| 271 initStatus = status; |
| 272 return initStatus; |
| 273 }); |
| 274 } |
| 275 |
| 276 void _reset() { |
| 277 refactoring = null; |
| 278 initStatus = new RefactoringStatus(); |
| 279 optionsStatus = new RefactoringStatus(); |
| 280 finalStatus = new RefactoringStatus(); |
| 281 } |
| 282 |
| 283 void _sendResultResponse() { |
| 284 // set problems |
| 285 { |
| 286 RefactoringStatus status = new RefactoringStatus(); |
| 287 status.addStatus(initStatus); |
| 288 status.addStatus(optionsStatus); |
| 289 status.addStatus(finalStatus); |
| 290 result.problems = status.problems; |
| 291 } |
| 292 // send the response |
| 293 server.sendResponse(result.toResponse(requestId)); |
| 294 // done with this request |
| 295 requestId = null; |
| 296 result = null; |
| 297 } |
| 298 |
| 299 RefactoringStatus _setOptions(Object options) { |
| 300 if (refactoring is RenameRefactoring) { |
| 301 RenameRefactoring renameRefactoring = refactoring; |
| 302 RenameOptions renameOptions = options; |
| 303 String newName = renameOptions.newName; |
| 304 renameRefactoring.newName = newName; |
| 305 return renameRefactoring.checkNewName(); |
| 306 } |
| 307 return new RefactoringStatus(); |
| 308 } |
| 309 } |
| OLD | NEW |