Chromium Code Reviews| Index: pkg/analysis_server/lib/src/edit/edit_domain.dart |
| diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart |
| index 2507981e742151e06e7914102034a36c88097531..d05fd77569e28da189d246dc1d725bd3447d6a33 100644 |
| --- a/pkg/analysis_server/lib/src/edit/edit_domain.dart |
| +++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart |
| @@ -4,16 +4,24 @@ |
| library edit.domain; |
| +import 'dart:async'; |
| + |
| import 'package:analysis_server/src/analysis_server.dart'; |
| import 'package:analysis_server/src/constants.dart'; |
| import 'package:analysis_server/src/edit/fix.dart'; |
| import 'package:analysis_server/src/protocol.dart'; |
| +import 'package:analysis_server/src/protocol2.dart' as protocol show |
| + LinkedEditGroup; |
| import 'package:analysis_server/src/protocol2.dart' show AnalysisError, |
| EditGetAssistsParams, EditGetAvailableRefactoringsParams, |
| - EditGetAvailableRefactoringsResult, EditGetFixesParams, RefactoringKind; |
| + EditGetAvailableRefactoringsResult, EditGetFixesParams, |
| + EditGetRefactoringParams, EditGetRefactoringResult, LinkedEditGroup, Location, |
| + RefactoringKind, RefactoringProblem, RefactoringProblemSeverity, RenameOptions, |
| + SourceChange; |
| import 'package:analysis_server/src/services/correction/assist.dart'; |
| import 'package:analysis_server/src/services/correction/change.dart'; |
| import 'package:analysis_server/src/services/correction/fix.dart'; |
| +import 'package:analysis_server/src/services/correction/status.dart'; |
| import 'package:analysis_server/src/services/json.dart'; |
| import 'package:analysis_server/src/services/refactoring/refactoring.dart'; |
| import 'package:analysis_server/src/services/search/search_engine.dart'; |
| @@ -39,11 +47,14 @@ class EditDomainHandler implements RequestHandler { |
| */ |
| SearchEngine searchEngine; |
| + _RefactoringManager refactoringManager; |
| + |
| /** |
| * Initialize a newly created handler to handle requests for the given [server]. |
| */ |
| EditDomainHandler(this.server) { |
| searchEngine = server.searchEngine; |
| + refactoringManager = new _RefactoringManager(server, searchEngine); |
| } |
| Response getAssists(Request request) { |
| @@ -130,12 +141,15 @@ class EditDomainHandler implements RequestHandler { |
| Response handleRequest(Request request) { |
| try { |
| String requestName = request.method; |
| - if (requestName == EDIT_GET_AVAILABLE_REFACTORINGS) { |
| - return getAvailableRefactorings(request); |
| - } else if (requestName == EDIT_GET_ASSISTS) { |
| + if (requestName == EDIT_GET_ASSISTS) { |
| return getAssists(request); |
| + } else if (requestName == EDIT_GET_AVAILABLE_REFACTORINGS) { |
| + return getAvailableRefactorings(request); |
| } else if (requestName == EDIT_GET_FIXES) { |
| return getFixes(request); |
| + } else if (requestName == EDIT_GET_REFACTORING) { |
| + refactoringManager.getRefactoring(request); |
| + return Response.DELAYED_RESPONSE; |
| } |
| } on RequestFailure catch (exception) { |
| return exception.response; |
| @@ -143,3 +157,146 @@ class EditDomainHandler implements RequestHandler { |
| return null; |
| } |
| } |
| + |
| + |
| +/** |
| + * An object managing [Refactoring] instances. |
|
Brian Wilkerson
2014/08/23 17:53:16
I think this class is assuming that we only need t
scheglov
2014/08/23 21:14:07
Done.
|
| + */ |
| +class _RefactoringManager { |
| + final AnalysisServer server; |
| + final SearchEngine searchEngine; |
| + |
| + RefactoringKind kind; |
| + String file; |
| + int offset; |
| + int length; |
| + Refactoring refactoring; |
| + RefactoringStatus initStatus; |
| + RefactoringStatus optionsStatus; |
| + RefactoringStatus finalStatus; |
| + |
| + String requestId; |
| + EditGetRefactoringResult result; |
| + |
| + _RefactoringManager(this.server, this.searchEngine) { |
| + _reset(); |
| + } |
| + |
| + bool get _hasFatalError { |
| + return initStatus.hasFatalError || |
| + optionsStatus.hasFatalError || |
| + finalStatus.hasFatalError; |
| + } |
| + |
| + void getRefactoring(Request request) { |
| + // prepare for processing the request |
| + requestId = request.id; |
| + result = new EditGetRefactoringResult(<RefactoringProblem>[]); |
| + // process the request |
| + var params = new EditGetRefactoringParams.fromRequest(request); |
| + _init(params.kind, params.file, params.offset, params.length).then((_) { |
| + if (_hasFatalError) { |
| + return _sendResultResponse(); |
| + } |
| + // set options |
| + if (params.options == null) { |
| + return _sendResultResponse(); |
| + } |
| + optionsStatus = _setOptions(params.options); |
| + if (_hasFatalError) { |
| + return _sendResultResponse(); |
| + } |
| + // done if just validation |
| + if (params.validateOnly) { |
| + return _sendResultResponse(); |
| + } |
| + // validation and create change |
| + refactoring.checkFinalConditions().then((_finalStatus) { |
| + finalStatus = _finalStatus; |
| + if (_hasFatalError) { |
| + return _sendResultResponse(); |
| + } |
| + return refactoring.createChange().then((change) { |
| + result.change = new SourceChange( |
| + change.message, |
| + change.fileEdits, |
| + <protocol.LinkedEditGroup>[]); |
| + return _sendResultResponse(); |
| + }); |
| + }); |
| + }); |
| + } |
| + |
| + /** |
| + * Initializes this context to perform a refactoring with the specified |
| + * parameters. The existing [Refactoring] is reused or created as needed. |
| + */ |
| + Future<RefactoringStatus> _init(RefactoringKind kind, String file, int offset, |
| + int length) { |
| + List<RefactoringProblem> problems = <RefactoringProblem>[]; |
| + // check if we can continue with the existing Refactoring instance |
| + if (this.kind == kind && |
| + this.file == file && |
| + this.offset == offset && |
| + this.length == length) { |
| + return new Future.value(initStatus); |
| + } |
| + _reset(); |
| + this.kind = kind; |
| + this.file = file; |
| + this.offset = offset; |
| + this.length = length; |
| + // create a new Refactoring instance |
| + if (kind == RefactoringKind.RENAME) { |
| + List<Element> elements = server.getElementsAtOffset(file, offset); |
| + if (elements.isNotEmpty) { |
| + Element element = elements[0]; |
| + refactoring = new RenameRefactoring(searchEngine, element); |
| + } |
| + } |
| + if (refactoring == null) { |
| + initStatus = |
| + new RefactoringStatus.fatal('Unable to create a refactoring'); |
| + return new Future.value(initStatus); |
| + } |
| + // check initial conditions |
| + return refactoring.checkInitialConditions().then((status) { |
| + initStatus = status; |
| + return initStatus; |
| + }); |
| + } |
| + |
| + void _reset() { |
| + refactoring = null; |
| + initStatus = new RefactoringStatus(); |
| + optionsStatus = new RefactoringStatus(); |
| + finalStatus = new RefactoringStatus(); |
| + } |
| + |
| + void _sendResultResponse() { |
| + // set problems |
| + { |
| + RefactoringStatus status = new RefactoringStatus(); |
| + status.addStatus(initStatus); |
| + status.addStatus(optionsStatus); |
| + status.addStatus(finalStatus); |
| + result.problems = status.problems; |
| + } |
| + // send the response |
| + server.sendResponse(result.toResponse(requestId)); |
| + // done with this request |
| + requestId = null; |
| + result = null; |
| + } |
| + |
| + RefactoringStatus _setOptions(Object options) { |
| + if (refactoring is RenameRefactoring) { |
| + RenameRefactoring renameRefactoring = refactoring; |
| + RenameOptions renameOptions = options; |
| + String newName = renameOptions.newName; |
| + renameRefactoring.newName = newName; |
| + return renameRefactoring.checkNewName(); |
| + } |
| + return new RefactoringStatus(); |
| + } |
| +} |