| 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 services.src.refactoring.inline_method; | 5 library services.src.refactoring.inline_method; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:analysis_server/src/protocol.dart' hide Element; | 9 import 'package:analysis_server/src/protocol.dart' hide Element; |
| 10 import 'package:analysis_server/src/services/correction/source_range.dart'; | 10 import 'package:analysis_server/src/services/correction/source_range.dart'; |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 | 163 |
| 164 | 164 |
| 165 /** | 165 /** |
| 166 * [InlineMethodRefactoring] implementation. | 166 * [InlineMethodRefactoring] implementation. |
| 167 */ | 167 */ |
| 168 class InlineMethodRefactoringImpl extends RefactoringImpl implements | 168 class InlineMethodRefactoringImpl extends RefactoringImpl implements |
| 169 InlineMethodRefactoring { | 169 InlineMethodRefactoring { |
| 170 final SearchEngine searchEngine; | 170 final SearchEngine searchEngine; |
| 171 final CompilationUnit unit; | 171 final CompilationUnit unit; |
| 172 final int offset; | 172 final int offset; |
| 173 String file; | |
| 174 CorrectionUtils utils; | 173 CorrectionUtils utils; |
| 175 SourceChange change; | 174 SourceChange change; |
| 176 | 175 |
| 177 bool isDeclaration = false; | 176 bool isDeclaration = false; |
| 178 bool deleteSource = false; | 177 bool deleteSource = false; |
| 179 bool inlineAll = true; | 178 bool inlineAll = true; |
| 180 | 179 |
| 181 ExecutableElement _methodElement; | 180 ExecutableElement _methodElement; |
| 182 bool _isAccessor; | 181 bool _isAccessor; |
| 183 String _methodFile; | 182 String _methodFile; |
| 184 CompilationUnit _methodUnit; | 183 CompilationUnit _methodUnit; |
| 185 CorrectionUtils _methodUtils; | 184 CorrectionUtils _methodUtils; |
| 186 AstNode _methodNode; | 185 AstNode _methodNode; |
| 187 FormalParameterList _methodParameters; | 186 FormalParameterList _methodParameters; |
| 188 FunctionBody _methodBody; | 187 FunctionBody _methodBody; |
| 189 Expression _methodExpression; | 188 Expression _methodExpression; |
| 190 _SourcePart _methodExpressionPart; | 189 _SourcePart _methodExpressionPart; |
| 191 _SourcePart _methodStatementsPart; | 190 _SourcePart _methodStatementsPart; |
| 192 List<_ReferenceProcessor> _referenceProcessors = []; | 191 List<_ReferenceProcessor> _referenceProcessors = []; |
| 193 | 192 |
| 194 InlineMethodRefactoringImpl(this.searchEngine, this.unit, this.offset) { | 193 InlineMethodRefactoringImpl(this.searchEngine, this.unit, this.offset) { |
| 195 file = unit.element.source.fullName; | |
| 196 utils = new CorrectionUtils(unit); | 194 utils = new CorrectionUtils(unit); |
| 197 } | 195 } |
| 198 | 196 |
| 199 @override | 197 @override |
| 200 String get className { | 198 String get className { |
| 201 if (_methodElement == null) { | 199 if (_methodElement == null) { |
| 202 return null; | 200 return null; |
| 203 } | 201 } |
| 204 Element classElement = _methodElement.enclosingElement; | 202 Element classElement = _methodElement.enclosingElement; |
| 205 if (classElement is ClassElement) { | 203 if (classElement is ClassElement) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 234 result.addError('All references must be inlined to remove the source.'); | 232 result.addError('All references must be inlined to remove the source.'); |
| 235 } | 233 } |
| 236 // prepare changes | 234 // prepare changes |
| 237 for (_ReferenceProcessor processor in _referenceProcessors) { | 235 for (_ReferenceProcessor processor in _referenceProcessors) { |
| 238 processor._process(result); | 236 processor._process(result); |
| 239 } | 237 } |
| 240 // delete method | 238 // delete method |
| 241 if (deleteSource && inlineAll) { | 239 if (deleteSource && inlineAll) { |
| 242 SourceRange methodRange = rangeNode(_methodNode); | 240 SourceRange methodRange = rangeNode(_methodNode); |
| 243 SourceRange linesRange = _methodUtils.getLinesRange(methodRange); | 241 SourceRange linesRange = _methodUtils.getLinesRange(methodRange); |
| 244 change.addEdit(_methodFile, new SourceEdit.range(linesRange, "")); | 242 addElementSourceChange( |
| 243 change, |
| 244 _methodElement, |
| 245 new SourceEdit.range(linesRange, '')); |
| 245 } | 246 } |
| 246 // done | 247 // done |
| 247 return new Future.value(result); | 248 return new Future.value(result); |
| 248 } | 249 } |
| 249 | 250 |
| 250 @override | 251 @override |
| 251 Future<RefactoringStatus> checkInitialConditions() { | 252 Future<RefactoringStatus> checkInitialConditions() { |
| 252 RefactoringStatus result = new RefactoringStatus(); | 253 RefactoringStatus result = new RefactoringStatus(); |
| 253 // prepare method information | 254 // prepare method information |
| 254 result.addStatus(_prepareMethod()); | 255 result.addStatus(_prepareMethod()); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 _ParameterOccurrence(this.parentPrecedence, this.range); | 399 _ParameterOccurrence(this.parentPrecedence, this.range); |
| 399 } | 400 } |
| 400 | 401 |
| 401 | 402 |
| 402 /** | 403 /** |
| 403 * Processor for single [SearchMatch] reference to [methodElement]. | 404 * Processor for single [SearchMatch] reference to [methodElement]. |
| 404 */ | 405 */ |
| 405 class _ReferenceProcessor { | 406 class _ReferenceProcessor { |
| 406 final InlineMethodRefactoringImpl ref; | 407 final InlineMethodRefactoringImpl ref; |
| 407 | 408 |
| 408 String _refFile; | 409 Element refElement; |
| 409 CorrectionUtils _refUtils; | 410 CorrectionUtils _refUtils; |
| 410 SimpleIdentifier _node; | 411 SimpleIdentifier _node; |
| 411 SourceRange _refLineRange; | 412 SourceRange _refLineRange; |
| 412 String _refPrefix; | 413 String _refPrefix; |
| 413 | 414 |
| 414 _ReferenceProcessor(this.ref, SearchMatch reference) { | 415 _ReferenceProcessor(this.ref, SearchMatch reference) { |
| 415 // prepare SourceChange to update | 416 refElement = reference.element; |
| 416 Element refElement = reference.element; | |
| 417 _refFile = refElement.source.fullName; | |
| 418 // prepare CorrectionUtils | 417 // prepare CorrectionUtils |
| 419 CompilationUnit refUnit = refElement.unit; | 418 CompilationUnit refUnit = refElement.unit; |
| 420 _refUtils = new CorrectionUtils(refUnit); | 419 _refUtils = new CorrectionUtils(refUnit); |
| 421 // prepare node and environment | 420 // prepare node and environment |
| 422 _node = _refUtils.findNode(reference.sourceRange.offset); | 421 _node = _refUtils.findNode(reference.sourceRange.offset); |
| 423 Statement refStatement = _node.getAncestor((node) => node is Statement); | 422 Statement refStatement = _node.getAncestor((node) => node is Statement); |
| 424 if (refStatement != null) { | 423 if (refStatement != null) { |
| 425 _refLineRange = _refUtils.getLinesRangeStatements([refStatement]); | 424 _refLineRange = _refUtils.getLinesRangeStatements([refStatement]); |
| 426 _refPrefix = _refUtils.getNodePrefix(refStatement); | 425 _refPrefix = _refUtils.getNodePrefix(refStatement); |
| 427 } else { | 426 } else { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 usage, | 489 usage, |
| 491 target, | 490 target, |
| 492 arguments); | 491 arguments); |
| 493 source = _refUtils.replaceSourceIndent( | 492 source = _refUtils.replaceSourceIndent( |
| 494 source, | 493 source, |
| 495 ref._methodStatementsPart._prefix, | 494 ref._methodStatementsPart._prefix, |
| 496 _refPrefix); | 495 _refPrefix); |
| 497 // do insert | 496 // do insert |
| 498 SourceRange range = rangeStartLength(_refLineRange, 0); | 497 SourceRange range = rangeStartLength(_refLineRange, 0); |
| 499 SourceEdit edit = new SourceEdit.range(range, source); | 498 SourceEdit edit = new SourceEdit.range(range, source); |
| 500 ref.change.addEdit(_refFile, edit); | 499 _addRefEdit(edit); |
| 501 } | 500 } |
| 502 // replace invocation with return expression | 501 // replace invocation with return expression |
| 503 if (ref._methodExpressionPart != null) { | 502 if (ref._methodExpressionPart != null) { |
| 504 // prepare expression source for invocation | 503 // prepare expression source for invocation |
| 505 String source = _getMethodSourceForInvocation( | 504 String source = _getMethodSourceForInvocation( |
| 506 ref._methodExpressionPart, | 505 ref._methodExpressionPart, |
| 507 _refUtils, | 506 _refUtils, |
| 508 usage, | 507 usage, |
| 509 target, | 508 target, |
| 510 arguments); | 509 arguments); |
| 511 if (getExpressionPrecedence(ref._methodExpression) < | 510 if (getExpressionPrecedence(ref._methodExpression) < |
| 512 getExpressionParentPrecedence(usage)) { | 511 getExpressionParentPrecedence(usage)) { |
| 513 source = "(${source})"; | 512 source = "(${source})"; |
| 514 } | 513 } |
| 515 // do replace | 514 // do replace |
| 516 SourceRange methodUsageRange = rangeNode(usage); | 515 SourceRange methodUsageRange = rangeNode(usage); |
| 517 SourceEdit edit = new SourceEdit.range(methodUsageRange, source); | 516 SourceEdit edit = new SourceEdit.range(methodUsageRange, source); |
| 518 ref.change.addEdit(_refFile, edit); | 517 _addRefEdit(edit); |
| 519 } else { | 518 } else { |
| 520 SourceEdit edit = new SourceEdit.range(_refLineRange, ""); | 519 SourceEdit edit = new SourceEdit.range(_refLineRange, ""); |
| 521 ref.change.addEdit(_refFile, edit); | 520 _addRefEdit(edit); |
| 522 } | 521 } |
| 523 return; | 522 return; |
| 524 } | 523 } |
| 525 // inline as closure invocation | 524 // inline as closure invocation |
| 526 String source; | 525 String source; |
| 527 { | 526 { |
| 528 source = ref._methodUtils.getRangeText( | 527 source = ref._methodUtils.getRangeText( |
| 529 rangeStartEnd(ref._methodParameters.leftParenthesis, ref._methodNode))
; | 528 rangeStartEnd(ref._methodParameters.leftParenthesis, ref._methodNode))
; |
| 530 String methodPrefix = | 529 String methodPrefix = |
| 531 ref._methodUtils.getLinePrefix(ref._methodNode.offset); | 530 ref._methodUtils.getLinePrefix(ref._methodNode.offset); |
| 532 source = _refUtils.replaceSourceIndent(source, methodPrefix, _refPrefix); | 531 source = _refUtils.replaceSourceIndent(source, methodPrefix, _refPrefix); |
| 533 source = source.trim(); | 532 source = source.trim(); |
| 534 } | 533 } |
| 535 // do insert | 534 // do insert |
| 536 SourceRange range = rangeNode(_node); | 535 SourceRange range = rangeNode(_node); |
| 537 SourceEdit edit = new SourceEdit.range(range, source); | 536 SourceEdit edit = new SourceEdit.range(range, source); |
| 538 ref.change.addEdit(_refFile, edit); | 537 _addRefEdit(edit); |
| 539 } | 538 } |
| 540 | 539 |
| 541 void _process(RefactoringStatus status) { | 540 void _process(RefactoringStatus status) { |
| 542 AstNode nodeParent = _node.parent; | 541 AstNode nodeParent = _node.parent; |
| 543 // may be only single place should be inlined | 542 // may be only single place should be inlined |
| 544 if (!_shouldProcess()) { | 543 if (!_shouldProcess()) { |
| 545 return; | 544 return; |
| 546 } | 545 } |
| 547 // may be invocation of inline method | 546 // may be invocation of inline method |
| 548 if (nodeParent is MethodInvocation) { | 547 if (nodeParent is MethodInvocation) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 String methodPrefix = | 598 String methodPrefix = |
| 600 ref._methodUtils.getLinePrefix(ref._methodNode.offset); | 599 ref._methodUtils.getLinePrefix(ref._methodNode.offset); |
| 601 source = | 600 source = |
| 602 _refUtils.replaceSourceIndent(source, methodPrefix, _refPrefix); | 601 _refUtils.replaceSourceIndent(source, methodPrefix, _refPrefix); |
| 603 source = source.trim(); | 602 source = source.trim(); |
| 604 source = removeEnd(source, ';'); | 603 source = removeEnd(source, ';'); |
| 605 } | 604 } |
| 606 // do insert | 605 // do insert |
| 607 SourceRange range = rangeNode(_node); | 606 SourceRange range = rangeNode(_node); |
| 608 SourceEdit edit = new SourceEdit.range(range, source); | 607 SourceEdit edit = new SourceEdit.range(range, source); |
| 609 ref.change.addEdit(_refFile, edit); | 608 _addRefEdit(edit); |
| 610 } | 609 } |
| 611 } | 610 } |
| 612 | 611 |
| 612 void _addRefEdit(SourceEdit edit) { |
| 613 addElementSourceChange(ref.change, refElement, edit); |
| 614 } |
| 615 |
| 613 bool _shouldProcess() { | 616 bool _shouldProcess() { |
| 614 if (!ref.inlineAll) { | 617 if (!ref.inlineAll) { |
| 615 SourceRange parentRange = rangeNode(_node); | 618 SourceRange parentRange = rangeNode(_node); |
| 616 return parentRange.contains(ref.offset); | 619 return parentRange.contains(ref.offset); |
| 617 } | 620 } |
| 618 return true; | 621 return true; |
| 619 } | 622 } |
| 620 } | 623 } |
| 621 | 624 |
| 622 class _ReturnsValidatorVisitor extends RecursiveAstVisitor { | 625 class _ReturnsValidatorVisitor extends RecursiveAstVisitor { |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 800 } | 803 } |
| 801 | 804 |
| 802 void _addVariable(SimpleIdentifier node) { | 805 void _addVariable(SimpleIdentifier node) { |
| 803 VariableElement variableElement = getLocalVariableElement(node); | 806 VariableElement variableElement = getLocalVariableElement(node); |
| 804 if (variableElement != null) { | 807 if (variableElement != null) { |
| 805 SourceRange nodeRange = rangeNode(node); | 808 SourceRange nodeRange = rangeNode(node); |
| 806 result.addVariable(variableElement, nodeRange); | 809 result.addVariable(variableElement, nodeRange); |
| 807 } | 810 } |
| 808 } | 811 } |
| 809 } | 812 } |
| OLD | NEW |