Chromium Code Reviews| 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 bool _cancelled = false; |
| 290 Request request; | |
| 274 EditGetRefactoringResult result; | 291 EditGetRefactoringResult result; |
| 275 | 292 |
| 276 _RefactoringManager(this.server, this.searchEngine) { | 293 _RefactoringManager(this.server, this.searchEngine) { |
| 277 server.onAnalysisStarted.listen(_reset); | 294 onAnalysisStartedSubscription = server.onAnalysisStarted.listen(_reset); |
| 278 _reset(); | 295 _reset(); |
| 279 } | 296 } |
| 280 | 297 |
| 298 /** | |
| 299 * Returns `true` if a response for the current request has not yet been sent. | |
| 300 */ | |
| 301 bool get hasPendingRequest => request != null; | |
| 302 | |
| 281 bool get _hasFatalError { | 303 bool get _hasFatalError { |
| 282 return initStatus.hasFatalError || | 304 return initStatus.hasFatalError || |
| 283 optionsStatus.hasFatalError || | 305 optionsStatus.hasFatalError || |
| 284 finalStatus.hasFatalError; | 306 finalStatus.hasFatalError; |
| 285 } | 307 } |
| 286 | 308 |
| 287 /** | 309 /** |
| 288 * Checks if [refactoring] requires options. | 310 * Checks if [refactoring] requires options. |
| 289 */ | 311 */ |
| 290 bool get _requiresOptions { | 312 bool get _requiresOptions { |
| 291 return refactoring is ExtractLocalRefactoring || | 313 return refactoring is ExtractLocalRefactoring || |
| 292 refactoring is ExtractMethodRefactoring || | 314 refactoring is ExtractMethodRefactoring || |
| 293 refactoring is InlineMethodRefactoring || | 315 refactoring is InlineMethodRefactoring || |
| 294 refactoring is MoveFileRefactoring || | 316 refactoring is MoveFileRefactoring || |
| 295 refactoring is RenameRefactoring; | 317 refactoring is RenameRefactoring; |
| 296 } | 318 } |
| 297 | 319 |
| 298 void getRefactoring(Request request) { | 320 /** |
| 321 * Marks the current request as cancelled and clean ups. | |
|
Paul Berry
2015/01/27 17:50:28
s/and clean ups/and cleans up/
scheglov
2015/01/27 19:23:55
Done.
| |
| 322 */ | |
| 323 void cancel() { | |
| 324 _cancelled = true; | |
| 325 onAnalysisStartedSubscription.cancel(); | |
| 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 return _sendResultResponse(); | 341 return _sendResultResponse(); |
| 312 } | 342 } |
| 313 // set options | 343 // set options |
| 314 if (_requiresOptions) { | 344 if (_requiresOptions) { |
| 315 if (params.options == null) { | 345 if (params.options == null) { |
| 316 optionsStatus = new RefactoringStatus(); | 346 optionsStatus = new RefactoringStatus(); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 339 if (test_simulateRefactoringException_change) { | 369 if (test_simulateRefactoringException_change) { |
| 340 throw 'A simulated refactoring exception - change.'; | 370 throw 'A simulated refactoring exception - change.'; |
| 341 } | 371 } |
| 342 // create change | 372 // create change |
| 343 result.change = await refactoring.createChange(); | 373 result.change = await refactoring.createChange(); |
| 344 result.potentialEdits = nullIfEmpty(refactoring.potentialEditIds); | 374 result.potentialEdits = nullIfEmpty(refactoring.potentialEditIds); |
| 345 _sendResultResponse(); | 375 _sendResultResponse(); |
| 346 }, onError: (exception, stackTrace) { | 376 }, onError: (exception, stackTrace) { |
| 347 server.instrumentationService.logException(exception, stackTrace); | 377 server.instrumentationService.logException(exception, stackTrace); |
| 348 server.sendResponse( | 378 server.sendResponse( |
| 349 new Response.serverError(request, exception, stackTrace)); | 379 new Response.serverError(_request, exception, stackTrace)); |
| 350 _reset(); | 380 _reset(); |
| 351 }); | 381 }); |
| 352 } | 382 } |
| 353 | 383 |
| 354 /** | 384 /** |
| 355 * Initializes this context to perform a refactoring with the specified | 385 * Initializes this context to perform a refactoring with the specified |
| 356 * parameters. The existing [Refactoring] is reused or created as needed. | 386 * parameters. The existing [Refactoring] is reused or created as needed. |
| 357 */ | 387 */ |
| 358 _init(RefactoringKind kind, String file, | 388 _init(RefactoringKind kind, String file, |
| 359 int offset, int length) async { | 389 int offset, int length) async { |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 511 offset = null; | 541 offset = null; |
| 512 length = null; | 542 length = null; |
| 513 refactoring = null; | 543 refactoring = null; |
| 514 feedback = null; | 544 feedback = null; |
| 515 initStatus = new RefactoringStatus(); | 545 initStatus = new RefactoringStatus(); |
| 516 optionsStatus = new RefactoringStatus(); | 546 optionsStatus = new RefactoringStatus(); |
| 517 finalStatus = new RefactoringStatus(); | 547 finalStatus = new RefactoringStatus(); |
| 518 } | 548 } |
| 519 | 549 |
| 520 void _sendResultResponse() { | 550 void _sendResultResponse() { |
| 551 if (_cancelled) { | |
| 552 server.sendResponse(new Response.refactoringRequestCancelled(request)); | |
|
Paul Berry
2015/01/27 17:50:28
Why wait until here to send the response? Why not
scheglov
2015/01/27 19:23:55
Good idea!
Done.
| |
| 553 return; | |
| 554 } | |
| 521 result.feedback = feedback; | 555 result.feedback = feedback; |
| 522 // set problems | 556 // set problems |
| 523 result.initialProblems = initStatus.problems; | 557 result.initialProblems = initStatus.problems; |
| 524 result.optionsProblems = optionsStatus.problems; | 558 result.optionsProblems = optionsStatus.problems; |
| 525 result.finalProblems = finalStatus.problems; | 559 result.finalProblems = finalStatus.problems; |
| 526 // send the response | 560 // send the response |
| 527 server.sendResponse(result.toResponse(requestId)); | 561 server.sendResponse(result.toResponse(request.id)); |
| 528 // done with this request | 562 // done with this request |
| 529 requestId = null; | 563 request = null; |
| 530 result = null; | 564 result = null; |
| 531 } | 565 } |
| 532 | 566 |
| 533 RefactoringStatus _setOptions(EditGetRefactoringParams params) { | 567 RefactoringStatus _setOptions(EditGetRefactoringParams params) { |
| 534 if (refactoring is ExtractLocalRefactoring) { | 568 if (refactoring is ExtractLocalRefactoring) { |
| 535 ExtractLocalRefactoring extractRefactoring = refactoring; | 569 ExtractLocalRefactoring extractRefactoring = refactoring; |
| 536 ExtractLocalVariableOptions extractOptions = params.options; | 570 ExtractLocalVariableOptions extractOptions = params.options; |
| 537 extractRefactoring.name = extractOptions.name; | 571 extractRefactoring.name = extractOptions.name; |
| 538 extractRefactoring.extractAll = extractOptions.extractAll; | 572 extractRefactoring.extractAll = extractOptions.extractAll; |
| 539 return extractRefactoring.checkName(); | 573 return extractRefactoring.checkName(); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 565 } | 599 } |
| 566 if (refactoring is RenameRefactoring) { | 600 if (refactoring is RenameRefactoring) { |
| 567 RenameRefactoring renameRefactoring = refactoring; | 601 RenameRefactoring renameRefactoring = refactoring; |
| 568 RenameOptions renameOptions = params.options; | 602 RenameOptions renameOptions = params.options; |
| 569 renameRefactoring.newName = renameOptions.newName; | 603 renameRefactoring.newName = renameOptions.newName; |
| 570 return renameRefactoring.checkNewName(); | 604 return renameRefactoring.checkNewName(); |
| 571 } | 605 } |
| 572 return new RefactoringStatus(); | 606 return new RefactoringStatus(); |
| 573 } | 607 } |
| 574 } | 608 } |
| OLD | NEW |