| 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_server.dart' hide Element; | 9 import 'package:analysis_server/src/protocol_server.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'; |
| 11 import 'package:analysis_server/src/services/correction/status.dart'; | 11 import 'package:analysis_server/src/services/correction/status.dart'; |
| 12 import 'package:analysis_server/src/services/correction/strings.dart'; | 12 import 'package:analysis_server/src/services/correction/strings.dart'; |
| 13 import 'package:analysis_server/src/services/correction/util.dart'; | 13 import 'package:analysis_server/src/services/correction/util.dart'; |
| 14 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; | 14 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; |
| 15 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da
rt'; | 15 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da
rt'; |
| 16 import 'package:analysis_server/src/services/search/element_visitors.dart'; | 16 import 'package:analysis_server/src/services/search/element_visitors.dart'; |
| 17 import 'package:analysis_server/src/services/search/hierarchy.dart'; | 17 import 'package:analysis_server/src/services/search/hierarchy.dart'; |
| 18 import 'package:analysis_server/src/services/search/search_engine.dart'; | 18 import 'package:analysis_server/src/services/search/search_engine.dart'; |
| 19 import 'package:analyzer/src/generated/ast.dart'; | 19 import 'package:analyzer/src/generated/ast.dart'; |
| 20 import 'package:analyzer/src/generated/element.dart'; | 20 import 'package:analyzer/src/generated/element.dart'; |
| 21 import 'package:analyzer/src/generated/source.dart'; | 21 import 'package:analyzer/src/generated/source.dart'; |
| 22 import 'package:analyzer/src/generated/utilities_dart.dart'; |
| 22 | 23 |
| 23 | 24 |
| 24 /** | 25 /** |
| 25 * Returns the [SourceRange] to find conflicting locals in. | 26 * Returns the [SourceRange] to find conflicting locals in. |
| 26 */ | 27 */ |
| 27 SourceRange _getLocalsConflictingRange(AstNode node) { | 28 SourceRange _getLocalsConflictingRange(AstNode node) { |
| 28 // maybe Block | 29 // maybe Block |
| 29 Block block = node.getAncestor((node) => node is Block); | 30 Block block = node.getAncestor((node) => node is Block); |
| 30 if (block != null) { | 31 if (block != null) { |
| 31 int offset = node.offset; | 32 int offset = node.offset; |
| 32 int endOffset = block.end; | 33 int endOffset = block.end; |
| 33 return rangeStartEnd(offset, endOffset); | 34 return rangeStartEnd(offset, endOffset); |
| 34 } | 35 } |
| 35 // maybe whole executable | 36 // maybe whole executable |
| 36 AstNode executableNode = getEnclosingExecutableNode(node); | 37 AstNode executableNode = getEnclosingExecutableNode(node); |
| 37 if (executableNode != null) { | 38 if (executableNode != null) { |
| 38 return rangeNode(executableNode); | 39 return rangeNode(executableNode); |
| 39 } | 40 } |
| 40 // not a part of a declaration with locals | 41 // not a part of a declaration with locals |
| 41 return SourceRange.EMPTY; | 42 return SourceRange.EMPTY; |
| 42 } | 43 } |
| 43 | 44 |
| 44 | 45 |
| 45 /** | 46 /** |
| 46 * Returns the source which should replace given invocation with given | 47 * Returns the source which should replace given invocation with given |
| 47 * arguments. | 48 * arguments. |
| 48 */ | 49 */ |
| 49 String _getMethodSourceForInvocation(_SourcePart part, CorrectionUtils utils, | 50 String _getMethodSourceForInvocation(RefactoringStatus status, _SourcePart part, |
| 50 AstNode contextNode, Expression targetExpression, List<Expression> arguments
) { | 51 CorrectionUtils utils, AstNode contextNode, Expression targetExpression, |
| 52 List<Expression> arguments) { |
| 51 // prepare edits to replace parameters with arguments | 53 // prepare edits to replace parameters with arguments |
| 52 List<SourceEdit> edits = <SourceEdit>[]; | 54 List<SourceEdit> edits = <SourceEdit>[]; |
| 53 part._parameters.forEach( | 55 part._parameters.forEach( |
| 54 (ParameterElement parameter, List<_ParameterOccurrence> occurrences) { | 56 (ParameterElement parameter, List<_ParameterOccurrence> occurrences) { |
| 55 // prepare argument | 57 // prepare argument |
| 56 Expression argument = null; | 58 Expression argument = null; |
| 57 for (Expression arg in arguments) { | 59 for (Expression arg in arguments) { |
| 58 if (arg.bestParameterElement == parameter) { | 60 if (arg.bestParameterElement == parameter) { |
| 59 argument = arg; | 61 argument = arg; |
| 60 break; | 62 break; |
| 61 } | 63 } |
| 62 } | 64 } |
| 63 if (argument is NamedExpression) { | 65 if (argument is NamedExpression) { |
| 64 argument = (argument as NamedExpression).expression; | 66 argument = (argument as NamedExpression).expression; |
| 65 } | 67 } |
| 66 int argumentPrecedence = getExpressionPrecedence(argument); | 68 // prepare argument properties |
| 67 String argumentSource = utils.getNodeText(argument); | 69 int argumentPrecedence; |
| 70 String argumentSource; |
| 71 if (argument != null) { |
| 72 argumentPrecedence = getExpressionPrecedence(argument); |
| 73 argumentSource = utils.getNodeText(argument); |
| 74 } else { |
| 75 // report about a missing required parameter |
| 76 if (parameter.parameterKind == ParameterKind.REQUIRED) { |
| 77 status.addError( |
| 78 'No argument for the parameter "${parameter.name}".', |
| 79 newLocation_fromNode(contextNode)); |
| 80 return; |
| 81 } |
| 82 // an optional parameter |
| 83 argumentPrecedence = -1000; |
| 84 argumentSource = parameter.defaultValueCode; |
| 85 if (argumentSource == null) { |
| 86 argumentSource = 'null'; |
| 87 } |
| 88 } |
| 68 // replace all occurrences of this parameter | 89 // replace all occurrences of this parameter |
| 69 for (_ParameterOccurrence occurrence in occurrences) { | 90 for (_ParameterOccurrence occurrence in occurrences) { |
| 70 SourceRange range = occurrence.range; | 91 SourceRange range = occurrence.range; |
| 71 // prepare argument source to apply at this occurrence | 92 // prepare argument source to apply at this occurrence |
| 72 String occurrenceArgumentSource; | 93 String occurrenceArgumentSource; |
| 73 if (argumentPrecedence < occurrence.parentPrecedence) { | 94 if (argumentPrecedence < occurrence.parentPrecedence) { |
| 74 occurrenceArgumentSource = "(${argumentSource})"; | 95 occurrenceArgumentSource = "($argumentSource)"; |
| 75 } else { | 96 } else { |
| 76 occurrenceArgumentSource = argumentSource; | 97 occurrenceArgumentSource = argumentSource; |
| 77 } | 98 } |
| 78 // do replace | 99 // do replace |
| 79 edits.add(newSourceEdit_range(range, occurrenceArgumentSource)); | 100 edits.add(newSourceEdit_range(range, occurrenceArgumentSource)); |
| 80 } | 101 } |
| 81 }); | 102 }); |
| 82 // replace static field "qualifier" with invocation target | 103 // replace static field "qualifier" with invocation target |
| 83 part._staticFieldQualifiers.forEach( | 104 part._staticFieldQualifiers.forEach( |
| 84 (String className, List<SourceRange> ranges) { | 105 (String className, List<SourceRange> ranges) { |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 status.addError( | 502 status.addError( |
| 482 'Cannot inline cascade invocation.', | 503 'Cannot inline cascade invocation.', |
| 483 newLocation_fromNode(usage)); | 504 newLocation_fromNode(usage)); |
| 484 } | 505 } |
| 485 // can we inline method body into "methodUsage" block? | 506 // can we inline method body into "methodUsage" block? |
| 486 if (_canInlineBody(usage)) { | 507 if (_canInlineBody(usage)) { |
| 487 // insert non-return statements | 508 // insert non-return statements |
| 488 if (ref._methodStatementsPart != null) { | 509 if (ref._methodStatementsPart != null) { |
| 489 // prepare statements source for invocation | 510 // prepare statements source for invocation |
| 490 String source = _getMethodSourceForInvocation( | 511 String source = _getMethodSourceForInvocation( |
| 512 status, |
| 491 ref._methodStatementsPart, | 513 ref._methodStatementsPart, |
| 492 _refUtils, | 514 _refUtils, |
| 493 usage, | 515 usage, |
| 494 target, | 516 target, |
| 495 arguments); | 517 arguments); |
| 496 source = _refUtils.replaceSourceIndent( | 518 source = _refUtils.replaceSourceIndent( |
| 497 source, | 519 source, |
| 498 ref._methodStatementsPart._prefix, | 520 ref._methodStatementsPart._prefix, |
| 499 _refPrefix); | 521 _refPrefix); |
| 500 // do insert | 522 // do insert |
| 501 SourceRange range = rangeStartLength(_refLineRange, 0); | 523 SourceRange range = rangeStartLength(_refLineRange, 0); |
| 502 SourceEdit edit = newSourceEdit_range(range, source); | 524 SourceEdit edit = newSourceEdit_range(range, source); |
| 503 _addRefEdit(edit); | 525 _addRefEdit(edit); |
| 504 } | 526 } |
| 505 // replace invocation with return expression | 527 // replace invocation with return expression |
| 506 if (ref._methodExpressionPart != null) { | 528 if (ref._methodExpressionPart != null) { |
| 507 // prepare expression source for invocation | 529 // prepare expression source for invocation |
| 508 String source = _getMethodSourceForInvocation( | 530 String source = _getMethodSourceForInvocation( |
| 531 status, |
| 509 ref._methodExpressionPart, | 532 ref._methodExpressionPart, |
| 510 _refUtils, | 533 _refUtils, |
| 511 usage, | 534 usage, |
| 512 target, | 535 target, |
| 513 arguments); | 536 arguments); |
| 514 if (getExpressionPrecedence(ref._methodExpression) < | 537 if (getExpressionPrecedence(ref._methodExpression) < |
| 515 getExpressionParentPrecedence(usage)) { | 538 getExpressionParentPrecedence(usage)) { |
| 516 source = "(${source})"; | 539 source = "(${source})"; |
| 517 } | 540 } |
| 518 // do replace | 541 // do replace |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 803 } | 826 } |
| 804 | 827 |
| 805 void _addVariable(SimpleIdentifier node) { | 828 void _addVariable(SimpleIdentifier node) { |
| 806 VariableElement variableElement = getLocalVariableElement(node); | 829 VariableElement variableElement = getLocalVariableElement(node); |
| 807 if (variableElement != null) { | 830 if (variableElement != null) { |
| 808 SourceRange nodeRange = rangeNode(node); | 831 SourceRange nodeRange = rangeNode(node); |
| 809 result.addVariable(variableElement, nodeRange); | 832 result.addVariable(variableElement, nodeRange); |
| 810 } | 833 } |
| 811 } | 834 } |
| 812 } | 835 } |
| OLD | NEW |