| 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_local; | 5 library services.src.refactoring.inline_local; |
| 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/status.dart'; | 11 import 'package:analysis_server/src/services/correction/status.dart'; |
| 11 import 'package:analysis_server/src/services/correction/util.dart'; | 12 import 'package:analysis_server/src/services/correction/util.dart'; |
| 12 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; | 13 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; |
| 13 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da
rt'; | 14 import 'package:analysis_server/src/services/refactoring/refactoring_internal.da
rt'; |
| 14 import 'package:analysis_server/src/services/search/search_engine.dart'; | 15 import 'package:analysis_server/src/services/search/search_engine.dart'; |
| 15 import 'package:analyzer/src/generated/ast.dart'; | 16 import 'package:analyzer/src/generated/ast.dart'; |
| 16 import 'package:analyzer/src/generated/element.dart'; | 17 import 'package:analyzer/src/generated/element.dart'; |
| 17 import 'package:analyzer/src/generated/java_core.dart'; | 18 import 'package:analyzer/src/generated/java_core.dart'; |
| 18 import 'package:analyzer/src/generated/scanner.dart'; | 19 import 'package:analyzer/src/generated/scanner.dart'; |
| 19 import 'package:analyzer/src/generated/source.dart'; | 20 import 'package:analyzer/src/generated/source.dart'; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 Statement declarationStatement = | 129 Statement declarationStatement = |
| 129 _variableNode.getAncestor((node) => node is VariableDeclarationStateme
nt); | 130 _variableNode.getAncestor((node) => node is VariableDeclarationStateme
nt); |
| 130 SourceRange range = utils.getLinesRangeStatements([declarationStatement]); | 131 SourceRange range = utils.getLinesRangeStatements([declarationStatement]); |
| 131 doSourceChange_addElementEdit( | 132 doSourceChange_addElementEdit( |
| 132 change, | 133 change, |
| 133 unitElement, | 134 unitElement, |
| 134 newSourceEdit_range(range, '')); | 135 newSourceEdit_range(range, '')); |
| 135 } | 136 } |
| 136 // prepare initializer | 137 // prepare initializer |
| 137 Expression initializer = _variableNode.initializer; | 138 Expression initializer = _variableNode.initializer; |
| 138 String initializerSource = utils.getNodeText(initializer); | 139 String initializerCode = utils.getNodeText(initializer); |
| 139 int initializerPrecedence = getExpressionPrecedence(initializer); | 140 int initializerPrecedence = getExpressionPrecedence(initializer); |
| 140 // replace references | 141 // replace references |
| 141 for (SearchMatch reference in _references) { | 142 for (SearchMatch reference in _references) { |
| 142 SourceRange range = reference.sourceRange; | 143 SourceRange range = reference.sourceRange; |
| 143 String sourceForReference = | 144 // prepare context |
| 144 _getSourceForReference(range, initializerSource, initializerPrecedence
); | 145 int offset = range.offset; |
| 146 AstNode node = utils.findNode(offset); |
| 147 AstNode parent = node.parent; |
| 148 // prepare code |
| 149 String codeForReference; |
| 150 if (parent is InterpolationExpression) { |
| 151 StringInterpolation target = parent.parent; |
| 152 if (initializer is SingleStringLiteral && |
| 153 !initializer.isRaw && |
| 154 initializer.isSingleQuoted == target.isSingleQuoted && |
| 155 (!initializer.isMultiline || target.isMultiline)) { |
| 156 range = rangeNode(parent); |
| 157 // unwrap the literal being inlined |
| 158 int initOffset = initializer.contentsOffset; |
| 159 int initLength = initializer.contentsEnd - initOffset; |
| 160 codeForReference = utils.getText(initOffset, initLength); |
| 161 // drop leading multiline EOL |
| 162 if (initializer.isMultiline) { |
| 163 if (codeForReference.startsWith('\n')) { |
| 164 codeForReference = codeForReference.substring(1); |
| 165 } else if (codeForReference.startsWith('\r\n')) { |
| 166 codeForReference = codeForReference.substring(2); |
| 167 } |
| 168 } |
| 169 } else if (_shouldBeExpressionInterpolation(parent, initializer)) { |
| 170 codeForReference = '{$initializerCode}'; |
| 171 } else { |
| 172 codeForReference = initializerCode; |
| 173 } |
| 174 } else if (initializerPrecedence < getExpressionParentPrecedence(node)) { |
| 175 codeForReference = '($initializerCode)'; |
| 176 } else { |
| 177 codeForReference = initializerCode; |
| 178 } |
| 179 // do replace |
| 145 doSourceChange_addElementEdit( | 180 doSourceChange_addElementEdit( |
| 146 change, | 181 change, |
| 147 unitElement, | 182 unitElement, |
| 148 newSourceEdit_range(range, sourceForReference)); | 183 newSourceEdit_range(range, codeForReference)); |
| 149 } | 184 } |
| 150 // done | 185 // done |
| 151 return new Future.value(change); | 186 return new Future.value(change); |
| 152 } | 187 } |
| 153 | 188 |
| 154 @override | 189 @override |
| 155 bool requiresPreview() => false; | 190 bool requiresPreview() => false; |
| 156 | 191 |
| 157 /** | 192 static bool _shouldBeExpressionInterpolation(InterpolationExpression target, |
| 158 * Returns the source which should be used to replace the reference with the | 193 Expression expression) { |
| 159 * given [SourceRange]. | 194 TokenType targetType = target.beginToken.type; |
| 160 * | 195 return targetType == TokenType.STRING_INTERPOLATION_IDENTIFIER && |
| 161 * [range] - the [SourceRange] of the reference. | 196 expression is! SimpleIdentifier; |
| 162 * [source] - the source of the initializer, to be inserted at [range]. | |
| 163 * [precedence] - the precedence of the initializer [source]. | |
| 164 */ | |
| 165 String _getSourceForReference(SourceRange range, String source, | |
| 166 int precedence) { | |
| 167 int offset = range.offset; | |
| 168 AstNode node = utils.findNode(offset); | |
| 169 AstNode parent = node.parent; | |
| 170 if (_isIdentifierStringInterpolation(parent)) { | |
| 171 return '{${source}}'; | |
| 172 } | |
| 173 if (precedence < getExpressionParentPrecedence(node)) { | |
| 174 return '(${source})'; | |
| 175 } | |
| 176 return source; | |
| 177 } | |
| 178 | |
| 179 /** | |
| 180 * Checks if the given node is a string interpolation in form `$name`. | |
| 181 */ | |
| 182 bool _isIdentifierStringInterpolation(AstNode parent) { | |
| 183 if (parent is InterpolationExpression) { | |
| 184 InterpolationExpression element = parent; | |
| 185 return element.beginToken.type == | |
| 186 TokenType.STRING_INTERPOLATION_IDENTIFIER; | |
| 187 } | |
| 188 return false; | |
| 189 } | 197 } |
| 190 } | 198 } |
| OLD | NEW |