Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 // This code was auto-generated, is not intended to be edited, and is subject to | |
| 6 // significant change. Please see the README file for more information. | |
| 7 | |
| 8 library services.src.correction.util; | |
| 9 | |
| 10 import 'package:analysis_services/src/correction/source_range.dart'; | |
| 11 import 'package:analysis_services/src/correction/strings.dart'; | |
| 12 import 'package:analyzer/src/generated/ast.dart'; | |
| 13 import 'package:analyzer/src/generated/element.dart'; | |
| 14 import 'package:analyzer/src/generated/resolver.dart'; | |
| 15 import 'package:analyzer/src/generated/source.dart'; | |
| 16 | |
| 17 | |
| 18 String getDefaultValueCode(DartType type) { | |
| 19 if (type != null) { | |
| 20 String typeName = type.displayName; | |
| 21 if (typeName == "bool") { | |
| 22 return "false"; | |
| 23 } | |
| 24 if (typeName == "int") { | |
| 25 return "0"; | |
| 26 } | |
| 27 if (typeName == "double") { | |
| 28 return "0.0"; | |
| 29 } | |
| 30 if (typeName == "String") { | |
| 31 return "''"; | |
| 32 } | |
| 33 } | |
| 34 // no better guess | |
| 35 return "null"; | |
| 36 } | |
| 37 | |
| 38 | |
| 39 /** | |
| 40 * Returns [getExpressionPrecedence] for the parent of [node], | |
| 41 * or `0` if the parent node is [ParenthesizedExpression]. | |
| 42 * | |
| 43 * The reason is that `(expr)` is always executed after `expr`. | |
| 44 */ | |
| 45 int getExpressionParentPrecedence(AstNode node) { | |
| 46 AstNode parent = node.parent; | |
| 47 if (parent is ParenthesizedExpression) { | |
| 48 return 0; | |
| 49 } | |
| 50 return getExpressionPrecedence(parent); | |
| 51 } | |
| 52 | |
| 53 | |
| 54 /** | |
| 55 * Returns the precedence of [node] it is an [Expression], negative otherwise. | |
| 56 */ | |
| 57 int getExpressionPrecedence(AstNode node) { | |
| 58 if (node is Expression) { | |
| 59 return node.precedence; | |
| 60 } | |
| 61 return -1000; | |
| 62 } | |
| 63 | |
| 64 | |
| 65 /** | |
| 66 * Returns the namespace of the given [ImportElement]. | |
| 67 */ | |
| 68 Map<String, Element> getImportNamespace(ImportElement imp) { | |
| 69 NamespaceBuilder builder = new NamespaceBuilder(); | |
| 70 Namespace namespace = builder.createImportNamespaceForDirective(imp); | |
| 71 return namespace.definedNames; | |
| 72 } | |
| 73 | |
| 74 | |
| 75 class CorrectionUtils { | |
| 76 final CompilationUnit unit; | |
| 77 | |
| 78 LibraryElement _library; | |
| 79 String _buffer; | |
| 80 String _endOfLine; | |
| 81 | |
| 82 CorrectionUtils(this.unit) { | |
| 83 CompilationUnitElement element = unit.element; | |
| 84 this._library = element.library; | |
| 85 this._buffer = element.context.getContents(element.source).data; | |
| 86 } | |
| 87 | |
| 88 /** | |
| 89 * Returns the EOL to use for this [CompilationUnit]. | |
| 90 */ | |
| 91 String get endOfLine { | |
| 92 if (_endOfLine == null) { | |
| 93 if (_buffer.contains("\r\n")) { | |
| 94 _endOfLine = "\r\n"; | |
| 95 } else { | |
| 96 _endOfLine = "\n"; | |
| 97 } | |
| 98 } | |
| 99 return _endOfLine; | |
| 100 } | |
| 101 | |
| 102 /** | |
| 103 * Skips whitespace characters and single EOL on the right from [index]. | |
| 104 * | |
| 105 * If [index] the end of a statement or method, then in the most cases it is | |
| 106 * a start of the next line. | |
| 107 */ | |
| 108 int getLineContentEnd(int index) { | |
| 109 int length = _buffer.length; | |
| 110 // skip whitespace characters | |
| 111 while (index < length) { | |
| 112 int c = _buffer.codeUnitAt(index); | |
| 113 if (!isWhitespace(c) || c == 0x0D || c == 0x0A) { | |
| 114 break; | |
| 115 } | |
| 116 index++; | |
| 117 } | |
| 118 // skip single \r | |
| 119 if (index < length && _buffer.codeUnitAt(index) == 0x0D) { | |
| 120 index++; | |
| 121 } | |
| 122 // skip single \n | |
| 123 if (index < length && _buffer.codeUnitAt(index) == 0x0A) { | |
| 124 index++; | |
| 125 } | |
| 126 // done | |
| 127 return index; | |
| 128 } | |
| 129 | |
| 130 /** | |
| 131 * Skips spaces and tabs on the left from [index]. | |
| 132 * | |
| 133 * If [index] is the start or a statement, then in the most cases it is a | |
| 134 * start on its line. | |
| 135 */ | |
| 136 int getLineContentStart(int index) { | |
| 137 while (index > 0) { | |
| 138 int c = _buffer.codeUnitAt(index - 1); | |
| 139 if (!isSpace(c)) { | |
| 140 break; | |
| 141 } | |
| 142 index--; | |
| 143 } | |
| 144 return index; | |
| 145 } | |
| 146 | |
| 147 /** | |
| 148 * Returns a [SourceRange] that covers [range] and extends (if possible) to | |
| 149 * cover whole lines. | |
| 150 */ | |
| 151 SourceRange getLinesRange(SourceRange range) { | |
| 152 // start | |
| 153 int startOffset = range.offset; | |
| 154 int startLineOffset = getLineContentStart(startOffset); | |
| 155 // end | |
| 156 int endOffset = range.end; | |
| 157 int afterEndLineOffset = getLineContentEnd(endOffset); | |
| 158 // range | |
| 159 return rangeStartEnd(startLineOffset, afterEndLineOffset); | |
| 160 } | |
| 161 | |
| 162 /** | |
| 163 * @return the source for the parameter with the given type and name. | |
| 164 */ | |
| 165 String getParameterSource(DartType type, String name) { | |
| 166 // no type | |
| 167 if (type == null || type.isDynamic) { | |
| 168 return name; | |
| 169 } | |
| 170 // function type | |
| 171 if (type is FunctionType) { | |
| 172 FunctionType functionType = type; | |
| 173 StringBuffer sb = new StringBuffer(); | |
| 174 // return type | |
| 175 DartType returnType = functionType.returnType; | |
| 176 if (returnType != null && !returnType.isDynamic) { | |
| 177 sb.write(getTypeSource2(returnType)); | |
| 178 sb.write(' '); | |
| 179 } | |
| 180 // parameter name | |
| 181 sb.write(name); | |
| 182 // parameters | |
| 183 sb.write('('); | |
| 184 List<ParameterElement> fParameters = functionType.parameters; | |
| 185 for (int i = 0; i < fParameters.length; i++) { | |
| 186 ParameterElement fParameter = fParameters[i]; | |
| 187 if (i != 0) { | |
| 188 sb.write(", "); | |
| 189 } | |
| 190 sb.write(getParameterSource(fParameter.type, fParameter.name)); | |
| 191 } | |
| 192 sb.write(')'); | |
| 193 // done | |
| 194 return sb.toString(); | |
| 195 } | |
| 196 // simple type | |
| 197 return "${getTypeSource2(type)} ${name}"; | |
| 198 } | |
| 199 | |
| 200 /** | |
| 201 * Returns the actual type source of the given [Expression], may be `null` | |
| 202 * if can not be resolved, should be treated as the `dynamic` type. | |
| 203 */ | |
| 204 String getTypeSource(Expression expression) { | |
| 205 if (expression == null) { | |
| 206 return null; | |
| 207 } | |
| 208 DartType type = expression.bestType; | |
| 209 String typeSource = getTypeSource2(type); | |
| 210 if ("dynamic" == typeSource) { | |
| 211 return null; | |
| 212 } | |
| 213 return typeSource; | |
| 214 } | |
| 215 | |
| 216 /** | |
| 217 * Returns the source to reference the given [Type] in this [CompilationUnit]. | |
| 218 */ | |
| 219 String getTypeSource2(DartType type) { | |
|
Brian Wilkerson
2014/07/18 13:21:35
I assume we'll rename this.
| |
| 220 StringBuffer sb = new StringBuffer(); | |
| 221 // prepare element | |
| 222 Element element = type.element; | |
| 223 if (element == null) { | |
| 224 String source = type.toString(); | |
| 225 source = source.replaceAll('<dynamic>', ''); | |
| 226 source = source.replaceAll('<dynamic, dynamic>', ''); | |
| 227 return source; | |
| 228 } | |
| 229 // append prefix | |
| 230 { | |
| 231 ImportElement imp = _getImportElement(element); | |
| 232 if (imp != null && imp.prefix != null) { | |
| 233 sb.write(imp.prefix.displayName); | |
| 234 sb.write("."); | |
| 235 } | |
| 236 } | |
| 237 // append simple name | |
| 238 String name = element.displayName; | |
| 239 sb.write(name); | |
| 240 // may be type arguments | |
| 241 if (type is InterfaceType) { | |
| 242 InterfaceType interfaceType = type; | |
| 243 List<DartType> arguments = interfaceType.typeArguments; | |
| 244 // check if has arguments | |
| 245 bool hasArguments = false; | |
| 246 for (DartType argument in arguments) { | |
| 247 if (!argument.isDynamic) { | |
| 248 hasArguments = true; | |
| 249 break; | |
| 250 } | |
| 251 } | |
| 252 // append type arguments | |
| 253 if (hasArguments) { | |
| 254 sb.write("<"); | |
| 255 for (int i = 0; i < arguments.length; i++) { | |
| 256 DartType argument = arguments[i]; | |
| 257 if (i != 0) { | |
| 258 sb.write(", "); | |
| 259 } | |
| 260 sb.write(getTypeSource2(argument)); | |
| 261 } | |
| 262 sb.write(">"); | |
| 263 } | |
| 264 } | |
| 265 // done | |
| 266 return sb.toString(); | |
| 267 } | |
| 268 | |
| 269 /** | |
| 270 * @return the [ImportElement] used to import given [Element] into [library]. | |
| 271 * May be `null` if was not imported, i.e. declared in the same librar y. | |
| 272 */ | |
| 273 ImportElement _getImportElement(Element element) { | |
| 274 for (ImportElement imp in _library.imports) { | |
| 275 Map<String, Element> definedNames = getImportNamespace(imp); | |
| 276 if (definedNames.containsValue(element)) { | |
| 277 return imp; | |
| 278 } | |
| 279 } | |
| 280 return null; | |
| 281 } | |
| 282 } | |
| OLD | NEW |