| 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.correction.util; | 5 library services.src.correction.util; |
| 6 | 6 |
| 7 import 'dart:math'; | 7 import 'dart:math'; |
| 8 | 8 |
| 9 import 'package:analysis_server/plugin/protocol/protocol.dart' | 9 import 'package:analysis_server/plugin/protocol/protocol.dart' |
| 10 show SourceChange, SourceEdit; | 10 show SourceChange, SourceEdit; |
| (...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 Expression stepUpNamedExpression(Expression expression) { | 656 Expression stepUpNamedExpression(Expression expression) { |
| 657 if (expression != null) { | 657 if (expression != null) { |
| 658 AstNode parent = expression.parent; | 658 AstNode parent = expression.parent; |
| 659 if (parent is NamedExpression && parent.expression == expression) { | 659 if (parent is NamedExpression && parent.expression == expression) { |
| 660 return parent; | 660 return parent; |
| 661 } | 661 } |
| 662 } | 662 } |
| 663 return expression; | 663 return expression; |
| 664 } | 664 } |
| 665 | 665 |
| 666 /** |
| 667 * Describes the location for a newly created [ClassMember]. |
| 668 */ |
| 669 class ClassMemberLocation { |
| 670 final String prefix; |
| 671 final int offset; |
| 672 final String suffix; |
| 673 |
| 674 ClassMemberLocation(this.prefix, this.offset, this.suffix); |
| 675 } |
| 676 |
| 666 class CorrectionUtils { | 677 class CorrectionUtils { |
| 667 final CompilationUnit unit; | 678 final CompilationUnit unit; |
| 668 | 679 |
| 669 /** | 680 /** |
| 670 * The [ClassElement] the generated code is inserted to, so we can decide if | 681 * The [ClassElement] the generated code is inserted to, so we can decide if |
| 671 * a type parameter may or may not be used. | 682 * a type parameter may or may not be used. |
| 672 */ | 683 */ |
| 673 ClassElement targetClassElement; | 684 ClassElement targetClassElement; |
| 674 | 685 |
| 675 LibraryElement _library; | 686 LibraryElement _library; |
| (...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1207 return sb.toString(); | 1218 return sb.toString(); |
| 1208 } | 1219 } |
| 1209 | 1220 |
| 1210 /** | 1221 /** |
| 1211 * @return the source of the inverted condition for the given logical expressi
on. | 1222 * @return the source of the inverted condition for the given logical expressi
on. |
| 1212 */ | 1223 */ |
| 1213 String invertCondition(Expression expression) => | 1224 String invertCondition(Expression expression) => |
| 1214 _invertCondition0(expression)._source; | 1225 _invertCondition0(expression)._source; |
| 1215 | 1226 |
| 1216 /** | 1227 /** |
| 1228 * Return `true` if the given [classDeclaration] has open '{' and close '}' |
| 1229 * at the same line, e.g. `class X {}`. |
| 1230 */ |
| 1231 bool isClassWithEmptyBody(ClassDeclaration classDeclaration) { |
| 1232 return getLineThis(classDeclaration.leftBracket.offset) == |
| 1233 getLineThis(classDeclaration.rightBracket.offset); |
| 1234 } |
| 1235 |
| 1236 /** |
| 1217 * @return <code>true</code> if selection range contains only whitespace or co
mments | 1237 * @return <code>true</code> if selection range contains only whitespace or co
mments |
| 1218 */ | 1238 */ |
| 1219 bool isJustWhitespaceOrComment(SourceRange range) { | 1239 bool isJustWhitespaceOrComment(SourceRange range) { |
| 1220 String trimmedText = getRangeText(range).trim(); | 1240 String trimmedText = getRangeText(range).trim(); |
| 1221 // may be whitespace | 1241 // may be whitespace |
| 1222 if (trimmedText.isEmpty) { | 1242 if (trimmedText.isEmpty) { |
| 1223 return true; | 1243 return true; |
| 1224 } | 1244 } |
| 1225 // may be comment | 1245 // may be comment |
| 1226 return TokenUtils.getTokens(trimmedText).isEmpty; | 1246 return TokenUtils.getTokens(trimmedText).isEmpty; |
| 1227 } | 1247 } |
| 1228 | 1248 |
| 1249 ClassMemberLocation prepareNewClassMemberLocation( |
| 1250 ClassDeclaration classDeclaration, |
| 1251 bool shouldSkip(ClassMember existingMember)) { |
| 1252 String indent = getIndent(1); |
| 1253 // Find the last target member. |
| 1254 ClassMember targetMember = null; |
| 1255 List<ClassMember> members = classDeclaration.members; |
| 1256 for (ClassMember member in members) { |
| 1257 if (shouldSkip(member)) { |
| 1258 targetMember = member; |
| 1259 } else { |
| 1260 break; |
| 1261 } |
| 1262 } |
| 1263 // After the last target member. |
| 1264 if (targetMember != null) { |
| 1265 return new ClassMemberLocation( |
| 1266 endOfLine + endOfLine + indent, targetMember.end, ''); |
| 1267 } |
| 1268 // At the beginning of the class. |
| 1269 String suffix = members.isNotEmpty || isClassWithEmptyBody(classDeclaration) |
| 1270 ? endOfLine |
| 1271 : ''; |
| 1272 return new ClassMemberLocation( |
| 1273 endOfLine + indent, classDeclaration.leftBracket.end, suffix); |
| 1274 } |
| 1275 |
| 1276 ClassMemberLocation prepareNewConstructorLocation( |
| 1277 ClassDeclaration classDeclaration) { |
| 1278 return prepareNewClassMemberLocation( |
| 1279 classDeclaration, |
| 1280 (member) => |
| 1281 member is FieldDeclaration || member is ConstructorDeclaration); |
| 1282 } |
| 1283 |
| 1284 ClassMemberLocation prepareNewFieldLocation( |
| 1285 ClassDeclaration classDeclaration) { |
| 1286 return prepareNewClassMemberLocation( |
| 1287 classDeclaration, (member) => member is FieldDeclaration); |
| 1288 } |
| 1289 |
| 1290 ClassMemberLocation prepareNewGetterLocation( |
| 1291 ClassDeclaration classDeclaration) { |
| 1292 return prepareNewClassMemberLocation( |
| 1293 classDeclaration, |
| 1294 (member) => |
| 1295 member is FieldDeclaration || |
| 1296 member is ConstructorDeclaration || |
| 1297 member is MethodDeclaration && member.isGetter); |
| 1298 } |
| 1299 |
| 1229 /** | 1300 /** |
| 1230 * Returns the source with indentation changed from [oldIndent] to | 1301 * Returns the source with indentation changed from [oldIndent] to |
| 1231 * [newIndent], keeping indentation of lines relative to each other. | 1302 * [newIndent], keeping indentation of lines relative to each other. |
| 1232 */ | 1303 */ |
| 1233 String replaceSourceIndent( | 1304 String replaceSourceIndent( |
| 1234 String source, String oldIndent, String newIndent) { | 1305 String source, String oldIndent, String newIndent) { |
| 1235 // prepare STRING token ranges | 1306 // prepare STRING token ranges |
| 1236 List<SourceRange> lineRanges = []; | 1307 List<SourceRange> lineRanges = []; |
| 1237 { | 1308 { |
| 1238 List<Token> tokens = TokenUtils.getTokens(source); | 1309 List<Token> tokens = TokenUtils.getTokens(source); |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1560 _InvertedCondition expr, int newOperatorPrecedence) { | 1631 _InvertedCondition expr, int newOperatorPrecedence) { |
| 1561 if (expr._precedence < newOperatorPrecedence) { | 1632 if (expr._precedence < newOperatorPrecedence) { |
| 1562 return "(${expr._source})"; | 1633 return "(${expr._source})"; |
| 1563 } | 1634 } |
| 1564 return expr._source; | 1635 return expr._source; |
| 1565 } | 1636 } |
| 1566 | 1637 |
| 1567 static _InvertedCondition _simple(String source) => | 1638 static _InvertedCondition _simple(String source) => |
| 1568 new _InvertedCondition(2147483647, source); | 1639 new _InvertedCondition(2147483647, source); |
| 1569 } | 1640 } |
| OLD | NEW |