| 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 library protocol.server; |
| 6 |
| 7 import 'package:analysis_server/src/computer/element.dart'; |
| 8 import 'package:analysis_server/src/protocol.dart'; |
| 9 import 'package:analysis_server/src/services/search/search_engine.dart' as |
| 10 engine; |
| 11 import 'package:analyzer/src/generated/ast.dart' as engine; |
| 12 import 'package:analyzer/src/generated/element.dart' as engine; |
| 13 import 'package:analyzer/src/generated/engine.dart' as engine; |
| 14 import 'package:analyzer/src/generated/error.dart' as engine; |
| 15 import 'package:analyzer/src/generated/source.dart' as engine; |
| 16 |
| 17 export 'package:analysis_server/src/protocol.dart'; |
| 18 |
| 19 |
| 20 /** |
| 21 * Returns a list of AnalysisErrors correponding to the given list of Engine |
| 22 * errors. |
| 23 */ |
| 24 List<AnalysisError> doAnalysisError_listFromEngine(engine.LineInfo lineInfo, |
| 25 List<engine.AnalysisError> errors) { |
| 26 return errors.map((engine.AnalysisError error) { |
| 27 return newAnalysisError_fromEngine(lineInfo, error); |
| 28 }).toList(); |
| 29 } |
| 30 |
| 31 |
| 32 /** |
| 33 * Adds [edit] to the [FileEdit] for the given [element]. |
| 34 */ |
| 35 void doSourceChange_addElementEdit(SourceChange change, engine.Element element, |
| 36 SourceEdit edit) { |
| 37 engine.AnalysisContext context = element.context; |
| 38 engine.Source source = element.source; |
| 39 doSourceChange_addSourceEdit(change, context, source, edit); |
| 40 } |
| 41 |
| 42 |
| 43 /** |
| 44 * Adds [edit] to the [FileEdit] for the given [source]. |
| 45 */ |
| 46 void doSourceChange_addSourceEdit(SourceChange change, |
| 47 engine.AnalysisContext context, engine.Source source, SourceEdit edit) { |
| 48 String file = source.fullName; |
| 49 int fileStamp = context.getModificationStamp(source); |
| 50 change.addEdit(file, fileStamp, edit); |
| 51 } |
| 52 |
| 53 |
| 54 /** |
| 55 * Construct based on error information from the analyzer engine. |
| 56 */ |
| 57 AnalysisError newAnalysisError_fromEngine(engine.LineInfo lineInfo, |
| 58 engine.AnalysisError error) { |
| 59 engine.ErrorCode errorCode = error.errorCode; |
| 60 // prepare location |
| 61 Location location; |
| 62 { |
| 63 String file = error.source.fullName; |
| 64 int offset = error.offset; |
| 65 int length = error.length; |
| 66 int startLine = -1; |
| 67 int startColumn = -1; |
| 68 if (lineInfo != null) { |
| 69 engine.LineInfo_Location lineLocation = lineInfo.getLocation(offset); |
| 70 if (lineLocation != null) { |
| 71 startLine = lineLocation.lineNumber; |
| 72 startColumn = lineLocation.columnNumber; |
| 73 } |
| 74 } |
| 75 location = new Location(file, offset, length, startLine, startColumn); |
| 76 } |
| 77 // done |
| 78 var severity = new AnalysisErrorSeverity(errorCode.errorSeverity.name); |
| 79 var type = new AnalysisErrorType(errorCode.type.name); |
| 80 String message = error.message; |
| 81 String correction = error.correction; |
| 82 return new AnalysisError( |
| 83 severity, |
| 84 type, |
| 85 location, |
| 86 message, |
| 87 correction: correction); |
| 88 } |
| 89 |
| 90 |
| 91 /** |
| 92 * Construct from an analyzer engine element kind. |
| 93 */ |
| 94 CompletionSuggestionKind |
| 95 newCompletionSuggestionKind_fromElementKind(engine.ElementKind kind) { |
| 96 // ElementKind.ANGULAR_FORMATTER, |
| 97 // ElementKind.ANGULAR_COMPONENT, |
| 98 // ElementKind.ANGULAR_CONTROLLER, |
| 99 // ElementKind.ANGULAR_DIRECTIVE, |
| 100 // ElementKind.ANGULAR_PROPERTY, |
| 101 // ElementKind.ANGULAR_SCOPE_PROPERTY, |
| 102 // ElementKind.ANGULAR_SELECTOR, |
| 103 // ElementKind.ANGULAR_VIEW, |
| 104 if (kind == engine.ElementKind.CLASS) return CompletionSuggestionKind.CLASS; |
| 105 // ElementKind.COMPILATION_UNIT, |
| 106 if (kind == |
| 107 engine.ElementKind.CONSTRUCTOR) return CompletionSuggestionKind.CONSTRUCTO
R; |
| 108 // ElementKind.DYNAMIC, |
| 109 // ElementKind.EMBEDDED_HTML_SCRIPT, |
| 110 // ElementKind.ERROR, |
| 111 // ElementKind.EXPORT, |
| 112 // ElementKind.EXTERNAL_HTML_SCRIPT, |
| 113 if (kind == engine.ElementKind.FIELD) return CompletionSuggestionKind.FIELD; |
| 114 if (kind == |
| 115 engine.ElementKind.FUNCTION) return CompletionSuggestionKind.FUNCTION; |
| 116 if (kind == |
| 117 engine.ElementKind.FUNCTION_TYPE_ALIAS) return |
| 118 CompletionSuggestionKind.FUNCTION_TYPE_ALIAS; |
| 119 if (kind == engine.ElementKind.GETTER) return CompletionSuggestionKind.GETTER; |
| 120 // ElementKind.HTML, |
| 121 if (kind == engine.ElementKind.IMPORT) return CompletionSuggestionKind.IMPORT; |
| 122 // ElementKind.LABEL, |
| 123 // ElementKind.LIBRARY, |
| 124 if (kind == |
| 125 engine.ElementKind.LOCAL_VARIABLE) return |
| 126 CompletionSuggestionKind.LOCAL_VARIABLE; |
| 127 if (kind == engine.ElementKind.METHOD) return CompletionSuggestionKind.METHOD; |
| 128 // ElementKind.NAME, |
| 129 if (kind == |
| 130 engine.ElementKind.PARAMETER) return CompletionSuggestionKind.PARAMETER; |
| 131 // ElementKind.POLYMER_ATTRIBUTE, |
| 132 // ElementKind.POLYMER_TAG_DART, |
| 133 // ElementKind.POLYMER_TAG_HTML, |
| 134 // ElementKind.PREFIX, |
| 135 if (kind == engine.ElementKind.SETTER) return CompletionSuggestionKind.SETTER; |
| 136 if (kind == |
| 137 engine.ElementKind.TOP_LEVEL_VARIABLE) return |
| 138 CompletionSuggestionKind.TOP_LEVEL_VARIABLE; |
| 139 // ElementKind.TYPE_PARAMETER, |
| 140 // ElementKind.UNIVERSE |
| 141 throw new ArgumentError('Unknown CompletionSuggestionKind for: $kind'); |
| 142 } |
| 143 |
| 144 |
| 145 |
| 146 /** |
| 147 * Construct based on a value from the analyzer engine. |
| 148 */ |
| 149 ElementKind newElementKind_fromEngine(engine.ElementKind kind) { |
| 150 if (kind == engine.ElementKind.CLASS) { |
| 151 return ElementKind.CLASS; |
| 152 } |
| 153 if (kind == engine.ElementKind.COMPILATION_UNIT) { |
| 154 return ElementKind.COMPILATION_UNIT; |
| 155 } |
| 156 if (kind == engine.ElementKind.CONSTRUCTOR) { |
| 157 return ElementKind.CONSTRUCTOR; |
| 158 } |
| 159 if (kind == engine.ElementKind.FIELD) { |
| 160 return ElementKind.FIELD; |
| 161 } |
| 162 if (kind == engine.ElementKind.FUNCTION) { |
| 163 return ElementKind.FUNCTION; |
| 164 } |
| 165 if (kind == engine.ElementKind.FUNCTION_TYPE_ALIAS) { |
| 166 return ElementKind.FUNCTION_TYPE_ALIAS; |
| 167 } |
| 168 if (kind == engine.ElementKind.GETTER) { |
| 169 return ElementKind.GETTER; |
| 170 } |
| 171 if (kind == engine.ElementKind.LABEL) { |
| 172 return ElementKind.LABEL; |
| 173 } |
| 174 if (kind == engine.ElementKind.LIBRARY) { |
| 175 return ElementKind.LIBRARY; |
| 176 } |
| 177 if (kind == engine.ElementKind.LOCAL_VARIABLE) { |
| 178 return ElementKind.LOCAL_VARIABLE; |
| 179 } |
| 180 if (kind == engine.ElementKind.METHOD) { |
| 181 return ElementKind.METHOD; |
| 182 } |
| 183 if (kind == engine.ElementKind.PARAMETER) { |
| 184 return ElementKind.PARAMETER; |
| 185 } |
| 186 if (kind == engine.ElementKind.PREFIX) { |
| 187 return ElementKind.PREFIX; |
| 188 } |
| 189 if (kind == engine.ElementKind.SETTER) { |
| 190 return ElementKind.SETTER; |
| 191 } |
| 192 if (kind == engine.ElementKind.TOP_LEVEL_VARIABLE) { |
| 193 return ElementKind.TOP_LEVEL_VARIABLE; |
| 194 } |
| 195 if (kind == engine.ElementKind.TYPE_PARAMETER) { |
| 196 return ElementKind.TYPE_PARAMETER; |
| 197 } |
| 198 return ElementKind.UNKNOWN; |
| 199 } |
| 200 |
| 201 |
| 202 /** |
| 203 * Construct based on a value from the analyzer engine. |
| 204 */ |
| 205 Element newElement_fromEngine(engine.Element element) { |
| 206 return elementFromEngine(element); |
| 207 } |
| 208 |
| 209 |
| 210 /** |
| 211 * Create a Location based on an [engine.Element]. |
| 212 */ |
| 213 Location newLocation_fromElement(engine.Element element) { |
| 214 engine.AnalysisContext context = element.context; |
| 215 engine.Source source = element.source; |
| 216 if (context == null || source == null) { |
| 217 return null; |
| 218 } |
| 219 String name = element.displayName; |
| 220 int offset = element.nameOffset; |
| 221 int length = name != null ? name.length : 0; |
| 222 if (element is engine.CompilationUnitElement) { |
| 223 offset = 0; |
| 224 length = 0; |
| 225 } |
| 226 engine.SourceRange range = new engine.SourceRange(offset, length); |
| 227 return _locationForArgs(context, source, range); |
| 228 } |
| 229 |
| 230 |
| 231 /** |
| 232 * Create a Location based on an [engine.SearchMatch]. |
| 233 */ |
| 234 Location newLocation_fromMatch(engine.SearchMatch match) { |
| 235 engine.Element enclosingElement = match.element; |
| 236 return _locationForArgs( |
| 237 enclosingElement.context, |
| 238 enclosingElement.source, |
| 239 match.sourceRange); |
| 240 } |
| 241 |
| 242 |
| 243 /** |
| 244 * Create a Location based on an [engine.AstNode]. |
| 245 */ |
| 246 Location newLocation_fromNode(engine.AstNode node) { |
| 247 engine.CompilationUnit unit = |
| 248 node.getAncestor((node) => node is engine.CompilationUnit); |
| 249 engine.CompilationUnitElement unitElement = unit.element; |
| 250 engine.AnalysisContext context = unitElement.context; |
| 251 engine.Source source = unitElement.source; |
| 252 engine.SourceRange range = new engine.SourceRange(node.offset, node.length); |
| 253 return _locationForArgs(context, source, range); |
| 254 } |
| 255 |
| 256 |
| 257 /** |
| 258 * Create a Location based on an [engine.CompilationUnit]. |
| 259 */ |
| 260 Location newLocation_fromUnit(engine.CompilationUnit unit, |
| 261 engine.SourceRange range) { |
| 262 engine.CompilationUnitElement unitElement = unit.element; |
| 263 engine.AnalysisContext context = unitElement.context; |
| 264 engine.Source source = unitElement.source; |
| 265 return _locationForArgs(context, source, range); |
| 266 } |
| 267 |
| 268 |
| 269 /** |
| 270 * Construct based on an element from the analyzer engine. |
| 271 */ |
| 272 OverriddenMember newOverriddenMember_fromEngine(engine.Element member) { |
| 273 Element element = elementFromEngine(member); |
| 274 String className = member.enclosingElement.displayName; |
| 275 return new OverriddenMember(element, className); |
| 276 } |
| 277 |
| 278 |
| 279 |
| 280 /** |
| 281 * Construct based on a value from the search engine. |
| 282 */ |
| 283 SearchResultKind newSearchResultKind_fromEngine(engine.MatchKind kind) { |
| 284 if (kind == engine.MatchKind.DECLARATION) { |
| 285 return SearchResultKind.DECLARATION; |
| 286 } |
| 287 if (kind == engine.MatchKind.READ) { |
| 288 return SearchResultKind.READ; |
| 289 } |
| 290 if (kind == engine.MatchKind.READ_WRITE) { |
| 291 return SearchResultKind.READ_WRITE; |
| 292 } |
| 293 if (kind == engine.MatchKind.WRITE) { |
| 294 return SearchResultKind.WRITE; |
| 295 } |
| 296 if (kind == engine.MatchKind.INVOCATION) { |
| 297 return SearchResultKind.INVOCATION; |
| 298 } |
| 299 if (kind == engine.MatchKind.REFERENCE) { |
| 300 return SearchResultKind.REFERENCE; |
| 301 } |
| 302 return SearchResultKind.UNKNOWN; |
| 303 } |
| 304 |
| 305 |
| 306 /** |
| 307 * Construct based on a value from the search engine. |
| 308 */ |
| 309 SearchResult newSearchResult_fromMatch(engine.SearchMatch match) { |
| 310 SearchResultKind kind = newSearchResultKind_fromEngine(match.kind); |
| 311 Location location = newLocation_fromMatch(match); |
| 312 List<Element> path = _computePath(match.element); |
| 313 return new SearchResult(location, kind, !match.isResolved, path); |
| 314 } |
| 315 |
| 316 |
| 317 /** |
| 318 * Construct based on a SourceRange. |
| 319 */ |
| 320 SourceEdit newSourceEdit_range(engine.SourceRange range, String replacement, |
| 321 {String id}) { |
| 322 return new SourceEdit(range.offset, range.length, replacement, id: id); |
| 323 } |
| 324 |
| 325 List<Element> _computePath(engine.Element element) { |
| 326 List<Element> path = <Element>[]; |
| 327 while (element != null) { |
| 328 path.add(newElement_fromEngine(element)); |
| 329 element = element.enclosingElement; |
| 330 } |
| 331 return path; |
| 332 } |
| 333 |
| 334 |
| 335 /** |
| 336 * Creates a new [Location]. |
| 337 */ |
| 338 Location _locationForArgs(engine.AnalysisContext context, engine.Source source, |
| 339 engine.SourceRange range) { |
| 340 int startLine = 0; |
| 341 int startColumn = 0; |
| 342 { |
| 343 engine.LineInfo lineInfo = context.getLineInfo(source); |
| 344 if (lineInfo != null) { |
| 345 engine.LineInfo_Location offsetLocation = |
| 346 lineInfo.getLocation(range.offset); |
| 347 startLine = offsetLocation.lineNumber; |
| 348 startColumn = offsetLocation.columnNumber; |
| 349 } |
| 350 } |
| 351 return new Location( |
| 352 source.fullName, |
| 353 range.offset, |
| 354 range.length, |
| 355 startLine, |
| 356 startColumn); |
| 357 } |
| OLD | NEW |