| 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'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:analysis_server/src/analysis_server.dart'; | 9 import 'package:analysis_server/src/analysis_server.dart'; |
| 10 import 'package:analysis_server/src/collections.dart'; | 10 import 'package:analysis_server/src/collections.dart'; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 */ | 46 */ |
| 47 SearchEngine searchEngine; | 47 SearchEngine searchEngine; |
| 48 | 48 |
| 49 _RefactoringManager refactoringManager; | 49 _RefactoringManager refactoringManager; |
| 50 | 50 |
| 51 /** | 51 /** |
| 52 * Initialize a newly created handler to handle requests for the given [server
]. | 52 * Initialize a newly created handler to handle requests for the given [server
]. |
| 53 */ | 53 */ |
| 54 EditDomainHandler(this.server) { | 54 EditDomainHandler(this.server) { |
| 55 searchEngine = server.searchEngine; | 55 searchEngine = server.searchEngine; |
| 56 refactoringManager = new _RefactoringManager(server, searchEngine); | 56 _newRefactoringManager(); |
| 57 } | 57 } |
| 58 | 58 |
| 59 Response format(Request request) { | 59 Response format(Request request) { |
| 60 | 60 |
| 61 EditFormatParams params = new EditFormatParams.fromRequest(request); | 61 EditFormatParams params = new EditFormatParams.fromRequest(request); |
| 62 String file = params.file; | 62 String file = params.file; |
| 63 | 63 |
| 64 engine.AnalysisContext context = server.getAnalysisContext(file); | 64 engine.AnalysisContext context = server.getAnalysisContext(file); |
| 65 if (context == null) { | 65 if (context == null) { |
| 66 return new Response.formatInvalidFile(request); | 66 return new Response.formatInvalidFile(request); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 String requestName = request.method; | 185 String requestName = request.method; |
| 186 if (requestName == EDIT_FORMAT) { | 186 if (requestName == EDIT_FORMAT) { |
| 187 return format(request); | 187 return format(request); |
| 188 } else if (requestName == EDIT_GET_ASSISTS) { | 188 } else if (requestName == EDIT_GET_ASSISTS) { |
| 189 return getAssists(request); | 189 return getAssists(request); |
| 190 } else if (requestName == EDIT_GET_AVAILABLE_REFACTORINGS) { | 190 } else if (requestName == EDIT_GET_AVAILABLE_REFACTORINGS) { |
| 191 return getAvailableRefactorings(request); | 191 return getAvailableRefactorings(request); |
| 192 } else if (requestName == EDIT_GET_FIXES) { | 192 } else if (requestName == EDIT_GET_FIXES) { |
| 193 return getFixes(request); | 193 return getFixes(request); |
| 194 } else if (requestName == EDIT_GET_REFACTORING) { | 194 } else if (requestName == EDIT_GET_REFACTORING) { |
| 195 refactoringManager.getRefactoring(request); | 195 return _getRefactoring(request); |
| 196 return Response.DELAYED_RESPONSE; | |
| 197 } else if (requestName == EDIT_SORT_MEMBERS) { | 196 } else if (requestName == EDIT_SORT_MEMBERS) { |
| 198 return sortMembers(request); | 197 return sortMembers(request); |
| 199 } | 198 } |
| 200 } on RequestFailure catch (exception) { | 199 } on RequestFailure catch (exception) { |
| 201 return exception.response; | 200 return exception.response; |
| 202 } | 201 } |
| 203 return null; | 202 return null; |
| 204 } | 203 } |
| 205 | 204 |
| 206 Response sortMembers(Request request) { | 205 Response sortMembers(Request request) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 232 return new Response.sortMembersParseErrors(request, numScanParseErrors); | 231 return new Response.sortMembersParseErrors(request, numScanParseErrors); |
| 233 } | 232 } |
| 234 // do sort | 233 // do sort |
| 235 int fileStamp = context.getModificationStamp(source); | 234 int fileStamp = context.getModificationStamp(source); |
| 236 String code = context.getContents(source).data; | 235 String code = context.getContents(source).data; |
| 237 MemberSorter sorter = new MemberSorter(code, unit); | 236 MemberSorter sorter = new MemberSorter(code, unit); |
| 238 List<SourceEdit> edits = sorter.sort(); | 237 List<SourceEdit> edits = sorter.sort(); |
| 239 SourceFileEdit fileEdit = new SourceFileEdit(file, fileStamp, edits: edits); | 238 SourceFileEdit fileEdit = new SourceFileEdit(file, fileStamp, edits: edits); |
| 240 return new EditSortMembersResult(fileEdit).toResponse(request.id); | 239 return new EditSortMembersResult(fileEdit).toResponse(request.id); |
| 241 } | 240 } |
| 241 |
| 242 Response _getRefactoring(Request request) { |
| 243 if (refactoringManager.hasPendingRequest) { |
| 244 refactoringManager.cancel(); |
| 245 _newRefactoringManager(); |
| 246 } |
| 247 refactoringManager.getRefactoring(request); |
| 248 return Response.DELAYED_RESPONSE; |
| 249 } |
| 250 |
| 251 /** |
| 252 * Initializes [refactoringManager] with a new instance. |
| 253 */ |
| 254 void _newRefactoringManager() { |
| 255 refactoringManager = new _RefactoringManager(server, searchEngine); |
| 256 } |
| 242 } | 257 } |
| 243 | 258 |
| 244 | 259 |
| 245 /** | 260 /** |
| 246 * An object managing a single [Refactoring] instance. | 261 * An object managing a single [Refactoring] instance. |
| 247 * | 262 * |
| 248 * The instance is identified by its kind, file, offset and length. | 263 * The instance is identified by its kind, file, offset and length. |
| 249 * It is initialized when the a set of parameters is given for the first time. | 264 * It is initialized when the a set of parameters is given for the first time. |
| 250 * All subsequent requests are performed on this [Refactoring] instance. | 265 * All subsequent requests are performed on this [Refactoring] instance. |
| 251 * | 266 * |
| 252 * Once new set of parameters is received, the previous [Refactoring] instance | 267 * Once new set of parameters is received, the previous [Refactoring] instance |
| 253 * is invalidated and a new one is created and initialized. | 268 * is invalidated and a new one is created and initialized. |
| 254 */ | 269 */ |
| 255 class _RefactoringManager { | 270 class _RefactoringManager { |
| 256 static const List<RefactoringProblem> EMPTY_PROBLEM_LIST = const | 271 static const List<RefactoringProblem> EMPTY_PROBLEM_LIST = const |
| 257 <RefactoringProblem>[ | 272 <RefactoringProblem>[ |
| 258 ]; | 273 ]; |
| 259 | 274 |
| 260 final AnalysisServer server; | 275 final AnalysisServer server; |
| 261 final SearchEngine searchEngine; | 276 final SearchEngine searchEngine; |
| 277 StreamSubscription onAnalysisStartedSubscription; |
| 262 | 278 |
| 263 RefactoringKind kind; | 279 RefactoringKind kind; |
| 264 String file; | 280 String file; |
| 265 int offset; | 281 int offset; |
| 266 int length; | 282 int length; |
| 267 Refactoring refactoring; | 283 Refactoring refactoring; |
| 268 RefactoringFeedback feedback; | 284 RefactoringFeedback feedback; |
| 269 RefactoringStatus initStatus; | 285 RefactoringStatus initStatus; |
| 270 RefactoringStatus optionsStatus; | 286 RefactoringStatus optionsStatus; |
| 271 RefactoringStatus finalStatus; | 287 RefactoringStatus finalStatus; |
| 272 | 288 |
| 273 String requestId; | 289 Request request; |
| 274 EditGetRefactoringResult result; | 290 EditGetRefactoringResult result; |
| 275 | 291 |
| 276 _RefactoringManager(this.server, this.searchEngine) { | 292 _RefactoringManager(this.server, this.searchEngine) { |
| 277 server.onAnalysisStarted.listen(_reset); | 293 onAnalysisStartedSubscription = server.onAnalysisStarted.listen(_reset); |
| 278 _reset(); | 294 _reset(); |
| 279 } | 295 } |
| 280 | 296 |
| 297 /** |
| 298 * Returns `true` if a response for the current request has not yet been sent. |
| 299 */ |
| 300 bool get hasPendingRequest => request != null; |
| 301 |
| 281 bool get _hasFatalError { | 302 bool get _hasFatalError { |
| 282 return initStatus.hasFatalError || | 303 return initStatus.hasFatalError || |
| 283 optionsStatus.hasFatalError || | 304 optionsStatus.hasFatalError || |
| 284 finalStatus.hasFatalError; | 305 finalStatus.hasFatalError; |
| 285 } | 306 } |
| 286 | 307 |
| 287 /** | 308 /** |
| 288 * Checks if [refactoring] requires options. | 309 * Checks if [refactoring] requires options. |
| 289 */ | 310 */ |
| 290 bool get _requiresOptions { | 311 bool get _requiresOptions { |
| 291 return refactoring is ExtractLocalRefactoring || | 312 return refactoring is ExtractLocalRefactoring || |
| 292 refactoring is ExtractMethodRefactoring || | 313 refactoring is ExtractMethodRefactoring || |
| 293 refactoring is InlineMethodRefactoring || | 314 refactoring is InlineMethodRefactoring || |
| 294 refactoring is MoveFileRefactoring || | 315 refactoring is MoveFileRefactoring || |
| 295 refactoring is RenameRefactoring; | 316 refactoring is RenameRefactoring; |
| 296 } | 317 } |
| 297 | 318 |
| 298 void getRefactoring(Request request) { | 319 /** |
| 320 * Cancels processing of the current request and cleans up. |
| 321 */ |
| 322 void cancel() { |
| 323 onAnalysisStartedSubscription.cancel(); |
| 324 server.sendResponse(new Response.refactoringRequestCancelled(request)); |
| 325 request = null; |
| 326 } |
| 327 |
| 328 void getRefactoring(Request _request) { |
| 299 // prepare for processing the request | 329 // prepare for processing the request |
| 300 requestId = request.id; | 330 request = _request; |
| 301 result = new EditGetRefactoringResult( | 331 result = new EditGetRefactoringResult( |
| 302 EMPTY_PROBLEM_LIST, | 332 EMPTY_PROBLEM_LIST, |
| 303 EMPTY_PROBLEM_LIST, | 333 EMPTY_PROBLEM_LIST, |
| 304 EMPTY_PROBLEM_LIST); | 334 EMPTY_PROBLEM_LIST); |
| 305 // process the request | 335 // process the request |
| 306 var params = new EditGetRefactoringParams.fromRequest(request); | 336 var params = new EditGetRefactoringParams.fromRequest(_request); |
| 307 runZoned(() async { | 337 runZoned(() async { |
| 308 await _init(params.kind, params.file, params.offset, params.length); | 338 await _init(params.kind, params.file, params.offset, params.length); |
| 309 if (initStatus.hasFatalError) { | 339 if (initStatus.hasFatalError) { |
| 310 feedback = null; | 340 feedback = null; |
| 311 _sendResultResponse(); | 341 _sendResultResponse(); |
| 312 return; | 342 return; |
| 313 } | 343 } |
| 314 // set options | 344 // set options |
| 315 if (_requiresOptions) { | 345 if (_requiresOptions) { |
| 316 if (params.options == null) { | 346 if (params.options == null) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 344 if (test_simulateRefactoringException_change) { | 374 if (test_simulateRefactoringException_change) { |
| 345 throw 'A simulated refactoring exception - change.'; | 375 throw 'A simulated refactoring exception - change.'; |
| 346 } | 376 } |
| 347 // create change | 377 // create change |
| 348 result.change = await refactoring.createChange(); | 378 result.change = await refactoring.createChange(); |
| 349 result.potentialEdits = nullIfEmpty(refactoring.potentialEditIds); | 379 result.potentialEdits = nullIfEmpty(refactoring.potentialEditIds); |
| 350 _sendResultResponse(); | 380 _sendResultResponse(); |
| 351 }, onError: (exception, stackTrace) { | 381 }, onError: (exception, stackTrace) { |
| 352 server.instrumentationService.logException(exception, stackTrace); | 382 server.instrumentationService.logException(exception, stackTrace); |
| 353 server.sendResponse( | 383 server.sendResponse( |
| 354 new Response.serverError(request, exception, stackTrace)); | 384 new Response.serverError(_request, exception, stackTrace)); |
| 355 _reset(); | 385 _reset(); |
| 356 }); | 386 }); |
| 357 } | 387 } |
| 358 | 388 |
| 359 /** | 389 /** |
| 360 * Initializes this context to perform a refactoring with the specified | 390 * Initializes this context to perform a refactoring with the specified |
| 361 * parameters. The existing [Refactoring] is reused or created as needed. | 391 * parameters. The existing [Refactoring] is reused or created as needed. |
| 362 */ | 392 */ |
| 363 Future _init(RefactoringKind kind, String file, | 393 Future _init(RefactoringKind kind, String file, |
| 364 int offset, int length) async { | 394 int offset, int length) async { |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 offset = null; | 547 offset = null; |
| 518 length = null; | 548 length = null; |
| 519 refactoring = null; | 549 refactoring = null; |
| 520 feedback = null; | 550 feedback = null; |
| 521 initStatus = new RefactoringStatus(); | 551 initStatus = new RefactoringStatus(); |
| 522 optionsStatus = new RefactoringStatus(); | 552 optionsStatus = new RefactoringStatus(); |
| 523 finalStatus = new RefactoringStatus(); | 553 finalStatus = new RefactoringStatus(); |
| 524 } | 554 } |
| 525 | 555 |
| 526 void _sendResultResponse() { | 556 void _sendResultResponse() { |
| 557 // ignore if was cancelled |
| 558 if (request == null) { |
| 559 return; |
| 560 } |
| 561 // set feedback |
| 527 result.feedback = feedback; | 562 result.feedback = feedback; |
| 528 // set problems | 563 // set problems |
| 529 result.initialProblems = initStatus.problems; | 564 result.initialProblems = initStatus.problems; |
| 530 result.optionsProblems = optionsStatus.problems; | 565 result.optionsProblems = optionsStatus.problems; |
| 531 result.finalProblems = finalStatus.problems; | 566 result.finalProblems = finalStatus.problems; |
| 532 // send the response | 567 // send the response |
| 533 server.sendResponse(result.toResponse(requestId)); | 568 server.sendResponse(result.toResponse(request.id)); |
| 534 // done with this request | 569 // done with this request |
| 535 requestId = null; | 570 request = null; |
| 536 result = null; | 571 result = null; |
| 537 } | 572 } |
| 538 | 573 |
| 539 RefactoringStatus _setOptions(EditGetRefactoringParams params) { | 574 RefactoringStatus _setOptions(EditGetRefactoringParams params) { |
| 540 if (refactoring is ExtractLocalRefactoring) { | 575 if (refactoring is ExtractLocalRefactoring) { |
| 541 ExtractLocalRefactoring extractRefactoring = refactoring; | 576 ExtractLocalRefactoring extractRefactoring = refactoring; |
| 542 ExtractLocalVariableOptions extractOptions = params.options; | 577 ExtractLocalVariableOptions extractOptions = params.options; |
| 543 extractRefactoring.name = extractOptions.name; | 578 extractRefactoring.name = extractOptions.name; |
| 544 extractRefactoring.extractAll = extractOptions.extractAll; | 579 extractRefactoring.extractAll = extractOptions.extractAll; |
| 545 return extractRefactoring.checkName(); | 580 return extractRefactoring.checkName(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 571 } | 606 } |
| 572 if (refactoring is RenameRefactoring) { | 607 if (refactoring is RenameRefactoring) { |
| 573 RenameRefactoring renameRefactoring = refactoring; | 608 RenameRefactoring renameRefactoring = refactoring; |
| 574 RenameOptions renameOptions = params.options; | 609 RenameOptions renameOptions = params.options; |
| 575 renameRefactoring.newName = renameOptions.newName; | 610 renameRefactoring.newName = renameOptions.newName; |
| 576 return renameRefactoring.checkNewName(); | 611 return renameRefactoring.checkNewName(); |
| 577 } | 612 } |
| 578 return new RefactoringStatus(); | 613 return new RefactoringStatus(); |
| 579 } | 614 } |
| 580 } | 615 } |
| OLD | NEW |