| 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/src/protocol.dart' show SourceChange, | 9 import 'package:analysis_server/src/protocol.dart' show SourceChange, |
| 10 SourceEdit; | 10 SourceEdit; |
| 11 import 'package:analysis_server/src/protocol_server.dart' show |
| 12 doSourceChange_addElementEdit; |
| 11 import 'package:analysis_server/src/services/correction/source_range.dart'; | 13 import 'package:analysis_server/src/services/correction/source_range.dart'; |
| 12 import 'package:analysis_server/src/services/correction/strings.dart'; | 14 import 'package:analysis_server/src/services/correction/strings.dart'; |
| 13 import 'package:analyzer/src/generated/ast.dart'; | 15 import 'package:analyzer/src/generated/ast.dart'; |
| 14 import 'package:analyzer/src/generated/element.dart'; | 16 import 'package:analyzer/src/generated/element.dart'; |
| 15 import 'package:analyzer/src/generated/engine.dart'; | 17 import 'package:analyzer/src/generated/engine.dart'; |
| 16 import 'package:analyzer/src/generated/resolver.dart'; | 18 import 'package:analyzer/src/generated/resolver.dart'; |
| 17 import 'package:analyzer/src/generated/scanner.dart'; | 19 import 'package:analyzer/src/generated/scanner.dart'; |
| 18 import 'package:analyzer/src/generated/source.dart'; | 20 import 'package:analyzer/src/generated/source.dart'; |
| 19 import 'package:path/path.dart'; | 21 import 'package:path/path.dart'; |
| 20 | 22 |
| 21 | 23 |
| 22 /** | 24 /** |
| 25 * Adds edits to the given [change] that ensure that all the [libraries] are |
| 26 * imported into the given [targetLibrary]. |
| 27 */ |
| 28 void addLibraryImports(SourceChange change, LibraryElement targetLibrary, |
| 29 Set<LibraryElement> libraries) { |
| 30 CompilationUnit libUnit = targetLibrary.definingCompilationUnit.node; |
| 31 // prepare new import location |
| 32 int offset = 0; |
| 33 String prefix; |
| 34 String suffix; |
| 35 { |
| 36 // if no directives |
| 37 prefix = ''; |
| 38 CorrectionUtils libraryUtils = new CorrectionUtils(libUnit); |
| 39 String eol = libraryUtils.endOfLine; |
| 40 suffix = eol; |
| 41 // after last directive in library |
| 42 for (Directive directive in libUnit.directives) { |
| 43 if (directive is LibraryDirective || directive is ImportDirective) { |
| 44 offset = directive.end; |
| 45 prefix = eol; |
| 46 suffix = ''; |
| 47 } |
| 48 } |
| 49 // if still at the beginning of the file, skip shebang and line comments |
| 50 if (offset == 0) { |
| 51 CorrectionUtils_InsertDesc desc = libraryUtils.getInsertDescTop(); |
| 52 offset = desc.offset; |
| 53 prefix = desc.prefix; |
| 54 suffix = desc.suffix + eol; |
| 55 } |
| 56 } |
| 57 // insert imports |
| 58 for (LibraryElement library in libraries) { |
| 59 String importPath = getLibrarySourceUri(targetLibrary, library.source); |
| 60 String importCode = "${prefix}import '$importPath';$suffix"; |
| 61 doSourceChange_addElementEdit( |
| 62 change, |
| 63 targetLibrary, |
| 64 new SourceEdit(offset, 0, importCode)); |
| 65 } |
| 66 } |
| 67 |
| 68 |
| 69 /** |
| 23 * @return <code>true</code> if given [List]s are identical at given position. | 70 * @return <code>true</code> if given [List]s are identical at given position. |
| 24 */ | 71 */ |
| 25 bool allListsIdentical(List<List> lists, int position) { | 72 bool allListsIdentical(List<List> lists, int position) { |
| 26 Object element = lists[0][position]; | 73 Object element = lists[0][position]; |
| 27 for (List list in lists) { | 74 for (List list in lists) { |
| 28 if (list[position] != element) { | 75 if (list[position] != element) { |
| 29 return false; | 76 return false; |
| 30 } | 77 } |
| 31 } | 78 } |
| 32 return true; | 79 return true; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 while (commentToken != null) { | 131 while (commentToken != null) { |
| 85 ranges.add(rangeToken(commentToken)); | 132 ranges.add(rangeToken(commentToken)); |
| 86 commentToken = commentToken.next; | 133 commentToken = commentToken.next; |
| 87 } | 134 } |
| 88 token = token.next; | 135 token = token.next; |
| 89 } | 136 } |
| 90 return ranges; | 137 return ranges; |
| 91 } | 138 } |
| 92 | 139 |
| 93 | 140 |
| 141 |
| 94 String getDefaultValueCode(DartType type) { | 142 String getDefaultValueCode(DartType type) { |
| 95 if (type != null) { | 143 if (type != null) { |
| 96 String typeName = type.displayName; | 144 String typeName = type.displayName; |
| 97 if (typeName == "bool") { | 145 if (typeName == "bool") { |
| 98 return "false"; | 146 return "false"; |
| 99 } | 147 } |
| 100 if (typeName == "int") { | 148 if (typeName == "int") { |
| 101 return "0"; | 149 return "0"; |
| 102 } | 150 } |
| 103 if (typeName == "double") { | 151 if (typeName == "double") { |
| 104 return "0.0"; | 152 return "0.0"; |
| 105 } | 153 } |
| 106 if (typeName == "String") { | 154 if (typeName == "String") { |
| 107 return "''"; | 155 return "''"; |
| 108 } | 156 } |
| 109 } | 157 } |
| 110 // no better guess | 158 // no better guess |
| 111 return "null"; | 159 return "null"; |
| 112 } | 160 } |
| 113 | 161 |
| 114 | |
| 115 | |
| 116 /** | 162 /** |
| 117 * Return the name of the [Element] kind. | 163 * Return the name of the [Element] kind. |
| 118 */ | 164 */ |
| 119 String getElementKindName(Element element) { | 165 String getElementKindName(Element element) { |
| 120 return element.kind.displayName; | 166 return element.kind.displayName; |
| 121 } | 167 } |
| 122 | 168 |
| 169 |
| 123 /** | 170 /** |
| 124 * Returns the name to display in the UI for the given [Element]. | 171 * Returns the name to display in the UI for the given [Element]. |
| 125 */ | 172 */ |
| 126 String getElementQualifiedName(Element element) { | 173 String getElementQualifiedName(Element element) { |
| 127 ElementKind kind = element.kind; | 174 ElementKind kind = element.kind; |
| 128 if (kind == ElementKind.FIELD || kind == ElementKind.METHOD) { | 175 if (kind == ElementKind.FIELD || kind == ElementKind.METHOD) { |
| 129 return '${element.enclosingElement.displayName}.${element.displayName}'; | 176 return '${element.enclosingElement.displayName}.${element.displayName}'; |
| 130 } else { | 177 } else { |
| 131 return element.displayName; | 178 return element.displayName; |
| 132 } | 179 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 } | 226 } |
| 180 if (node is MethodDeclaration) { | 227 if (node is MethodDeclaration) { |
| 181 return node.element; | 228 return node.element; |
| 182 } | 229 } |
| 183 node = node.parent; | 230 node = node.parent; |
| 184 } | 231 } |
| 185 return null; | 232 return null; |
| 186 } | 233 } |
| 187 | 234 |
| 188 | 235 |
| 236 |
| 189 /** | 237 /** |
| 190 * @return the enclosing executable [AstNode]. | 238 * @return the enclosing executable [AstNode]. |
| 191 */ | 239 */ |
| 192 AstNode getEnclosingExecutableNode(AstNode node) { | 240 AstNode getEnclosingExecutableNode(AstNode node) { |
| 193 while (node != null) { | 241 while (node != null) { |
| 194 if (node is FunctionDeclaration) { | 242 if (node is FunctionDeclaration) { |
| 195 return node; | 243 return node; |
| 196 } | 244 } |
| 197 if (node is ConstructorDeclaration) { | 245 if (node is ConstructorDeclaration) { |
| 198 return node; | 246 return node; |
| (...skipping 751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 950 } | 998 } |
| 951 // prepare element | 999 // prepare element |
| 952 Element element = type.element; | 1000 Element element = type.element; |
| 953 if (element == null) { | 1001 if (element == null) { |
| 954 String source = type.toString(); | 1002 String source = type.toString(); |
| 955 source = source.replaceAll('<dynamic>', ''); | 1003 source = source.replaceAll('<dynamic>', ''); |
| 956 source = source.replaceAll('<dynamic, dynamic>', ''); | 1004 source = source.replaceAll('<dynamic, dynamic>', ''); |
| 957 return source; | 1005 return source; |
| 958 } | 1006 } |
| 959 // check if imported | 1007 // check if imported |
| 960 if (element.library != _library) { | 1008 LibraryElement library = element.library; |
| 1009 if (library != null && library != _library) { |
| 961 ImportElement importElement = _getImportElement(element); | 1010 ImportElement importElement = _getImportElement(element); |
| 962 if (importElement != null) { | 1011 if (importElement != null) { |
| 963 if (importElement.prefix != null) { | 1012 if (importElement.prefix != null) { |
| 964 sb.write(importElement.prefix.displayName); | 1013 sb.write(importElement.prefix.displayName); |
| 965 sb.write("."); | 1014 sb.write("."); |
| 966 } | 1015 } |
| 967 } else { | 1016 } else { |
| 968 librariesToImport.add(element.library); | 1017 librariesToImport.add(library); |
| 969 } | 1018 } |
| 970 } | 1019 } |
| 971 // append simple name | 1020 // append simple name |
| 972 String name = element.displayName; | 1021 String name = element.displayName; |
| 973 sb.write(name); | 1022 sb.write(name); |
| 974 // may be type arguments | 1023 // may be type arguments |
| 975 if (type is ParameterizedType) { | 1024 if (type is ParameterizedType) { |
| 976 List<DartType> arguments = type.typeArguments; | 1025 List<DartType> arguments = type.typeArguments; |
| 977 // check if has arguments | 1026 // check if has arguments |
| 978 bool hasArguments = false; | 1027 bool hasArguments = false; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 993 sb.write(argumentSrc); | 1042 sb.write(argumentSrc); |
| 994 } | 1043 } |
| 995 sb.write(">"); | 1044 sb.write(">"); |
| 996 } | 1045 } |
| 997 } | 1046 } |
| 998 // done | 1047 // done |
| 999 return sb.toString(); | 1048 return sb.toString(); |
| 1000 } | 1049 } |
| 1001 | 1050 |
| 1002 /** | 1051 /** |
| 1003 * Checks if [type] is visible at [targetOffset]. | |
| 1004 */ | |
| 1005 bool _isTypeVisible(DartType type) { | |
| 1006 if (type is TypeParameterType) { | |
| 1007 TypeParameterElement parameterElement = type.element; | |
| 1008 Element parameterClassElement = parameterElement.enclosingElement; | |
| 1009 return identical(parameterClassElement, targetClassElement); | |
| 1010 } | |
| 1011 return true; | |
| 1012 } | |
| 1013 | |
| 1014 /** | |
| 1015 * Indents given source left or right. | 1052 * Indents given source left or right. |
| 1016 */ | 1053 */ |
| 1017 String indentSourceLeftRight(String source, bool right) { | 1054 String indentSourceLeftRight(String source, bool right) { |
| 1018 StringBuffer sb = new StringBuffer(); | 1055 StringBuffer sb = new StringBuffer(); |
| 1019 String indent = getIndent(1); | 1056 String indent = getIndent(1); |
| 1020 String eol = endOfLine; | 1057 String eol = endOfLine; |
| 1021 List<String> lines = source.split(eol); | 1058 List<String> lines = source.split(eol); |
| 1022 for (int i = 0; i < lines.length; i++) { | 1059 for (int i = 0; i < lines.length; i++) { |
| 1023 String line = lines[i]; | 1060 String line = lines[i]; |
| 1024 // last line, stop if empty | 1061 // last line, stop if empty |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1251 } | 1288 } |
| 1252 return _invertCondition0(innerExpresion); | 1289 return _invertCondition0(innerExpresion); |
| 1253 } | 1290 } |
| 1254 DartType type = expression.bestType; | 1291 DartType type = expression.bestType; |
| 1255 if (type.displayName == "bool") { | 1292 if (type.displayName == "bool") { |
| 1256 return _InvertedCondition._simple("!${getNodeText(expression)}"); | 1293 return _InvertedCondition._simple("!${getNodeText(expression)}"); |
| 1257 } | 1294 } |
| 1258 return _InvertedCondition._simple(getNodeText(expression)); | 1295 return _InvertedCondition._simple(getNodeText(expression)); |
| 1259 } | 1296 } |
| 1260 | 1297 |
| 1298 /** |
| 1299 * Checks if [type] is visible at [targetOffset]. |
| 1300 */ |
| 1301 bool _isTypeVisible(DartType type) { |
| 1302 if (type is TypeParameterType) { |
| 1303 TypeParameterElement parameterElement = type.element; |
| 1304 Element parameterClassElement = parameterElement.enclosingElement; |
| 1305 return identical(parameterClassElement, targetClassElement); |
| 1306 } |
| 1307 return true; |
| 1308 } |
| 1309 |
| 1261 bool _selectionIncludesNonWhitespaceOutsideOperands(SourceRange selection, | 1310 bool _selectionIncludesNonWhitespaceOutsideOperands(SourceRange selection, |
| 1262 List<Expression> operands) { | 1311 List<Expression> operands) { |
| 1263 return _selectionIncludesNonWhitespaceOutsideRange( | 1312 return _selectionIncludesNonWhitespaceOutsideRange( |
| 1264 selection, | 1313 selection, |
| 1265 rangeNodes(operands)); | 1314 rangeNodes(operands)); |
| 1266 } | 1315 } |
| 1267 | 1316 |
| 1268 /** | 1317 /** |
| 1269 * @return <code>true</code> if "selection" covers "range" and there are any n
on-whitespace tokens | 1318 * @return <code>true</code> if "selection" covers "range" and there are any n
on-whitespace tokens |
| 1270 * between "selection" and "range" start/end. | 1319 * between "selection" and "range" start/end. |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1472 | 1521 |
| 1473 @override | 1522 @override |
| 1474 Object visitExpression(Expression node) { | 1523 Object visitExpression(Expression node) { |
| 1475 if (node is BinaryExpression && node.operator.type == groupOperatorType) { | 1524 if (node is BinaryExpression && node.operator.type == groupOperatorType) { |
| 1476 return super.visitNode(node); | 1525 return super.visitNode(node); |
| 1477 } | 1526 } |
| 1478 operands.add(node); | 1527 operands.add(node); |
| 1479 return null; | 1528 return null; |
| 1480 } | 1529 } |
| 1481 } | 1530 } |
| OLD | NEW |