| 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 computer.hover; |
| 6 |
| 7 import 'dart:collection'; |
| 8 |
| 9 import 'package:analysis_server/src/constants.dart'; |
| 10 import 'package:analyzer/src/generated/ast.dart'; |
| 11 import 'package:analyzer/src/generated/element.dart'; |
| 12 |
| 13 |
| 14 /** |
| 15 * Converts [str] from a Dart Doc string with slashes and stars to a plain text |
| 16 * representation of the comment. |
| 17 */ |
| 18 String _removeDartDocDelimiters(String str) { |
| 19 if (str == null) { |
| 20 return null; |
| 21 } |
| 22 // remove /** */ |
| 23 if (str.startsWith('/**')) { |
| 24 str = str.substring(3); |
| 25 } |
| 26 if (str.endsWith("*/")) { |
| 27 str = str.substring(0, str.length - 2); |
| 28 } |
| 29 str = str.trim(); |
| 30 // remove leading '* ' |
| 31 List<String> lines = str.split('\n'); |
| 32 StringBuffer sb = new StringBuffer(); |
| 33 bool firstLine = true; |
| 34 for (String line in lines) { |
| 35 line = line.trim(); |
| 36 if (line.startsWith("*")) { |
| 37 line = line.substring(1); |
| 38 if (line.startsWith(" ")) { |
| 39 line = line.substring(1); |
| 40 } |
| 41 } else if (line.startsWith("///")) { |
| 42 line = line.substring(3); |
| 43 if (line.startsWith(" ")) { |
| 44 line = line.substring(1); |
| 45 } |
| 46 } |
| 47 if (!firstLine) { |
| 48 sb.write('\n'); |
| 49 } |
| 50 firstLine = false; |
| 51 sb.write(line); |
| 52 } |
| 53 str = sb.toString(); |
| 54 // done |
| 55 return str; |
| 56 } |
| 57 |
| 58 |
| 59 /** |
| 60 * A computer for the hover at the specified offset of a Dart [CompilationUnit]. |
| 61 */ |
| 62 class DartUnitHoverComputer { |
| 63 final CompilationUnit _unit; |
| 64 final int _offset; |
| 65 |
| 66 DartUnitHoverComputer(this._unit, this._offset); |
| 67 |
| 68 /** |
| 69 * Returns the computed hover, maybe `null`. |
| 70 */ |
| 71 Map<String, Object> compute() { |
| 72 AstNode node = new NodeLocator.con1(_offset).searchWithin(_unit); |
| 73 if (node is Expression) { |
| 74 Hover hover = new Hover(); |
| 75 // element |
| 76 Element element = ElementLocator.locateWithOffset(node, _offset); |
| 77 if (element != null) { |
| 78 // variable, if synthetic accessor |
| 79 if (element is PropertyAccessorElement) { |
| 80 PropertyAccessorElement accessor = element; |
| 81 if (accessor.isSynthetic) { |
| 82 element = accessor.variable; |
| 83 } |
| 84 } |
| 85 // description |
| 86 hover.elementDescription = element.toString(); |
| 87 // library |
| 88 LibraryElement library = element.library; |
| 89 if (library != null) { |
| 90 hover.containingLibraryName = library.name; |
| 91 hover.containingLibraryPath = library.source.fullName; |
| 92 } |
| 93 // documentation |
| 94 String dartDoc = element.computeDocumentationComment(); |
| 95 dartDoc = _removeDartDocDelimiters(dartDoc); |
| 96 hover.dartDoc = dartDoc; |
| 97 } |
| 98 // parameter |
| 99 hover.parameter = _safeToString(node.bestParameterElement); |
| 100 // types |
| 101 hover.staticType = _safeToString(node.staticType); |
| 102 hover.propagatedType = _safeToString(node.propagatedType); |
| 103 // done |
| 104 return hover.toJson(); |
| 105 } |
| 106 // not an expression |
| 107 return null; |
| 108 } |
| 109 |
| 110 static _safeToString(obj) => obj != null ? obj.toString() : null; |
| 111 } |
| 112 |
| 113 |
| 114 class Hover { |
| 115 String containingLibraryName; |
| 116 String containingLibraryPath; |
| 117 String dartDoc; |
| 118 String elementDescription; |
| 119 String parameter; |
| 120 String propagatedType; |
| 121 String staticType; |
| 122 |
| 123 Hover(); |
| 124 |
| 125 factory Hover.fromJson(Map<String, Object> map) { |
| 126 Hover hover = new Hover(); |
| 127 hover.containingLibraryName = map[CONTAINING_LIBRARY_NAME]; |
| 128 hover.containingLibraryPath = map[CONTAINING_LIBRARY_PATH]; |
| 129 hover.dartDoc = map[DART_DOC]; |
| 130 hover.elementDescription = map[ELEMENT_DESCRIPTION]; |
| 131 hover.parameter = map[PARAMETER]; |
| 132 hover.propagatedType = map[PROPAGATED_TYPE]; |
| 133 hover.staticType = map[STATIC_TYPE]; |
| 134 return hover; |
| 135 } |
| 136 |
| 137 Map<String, Object> toJson() { |
| 138 Map<String, Object> json = new HashMap<String, Object>(); |
| 139 if (containingLibraryName != null) { |
| 140 json[CONTAINING_LIBRARY_NAME] = containingLibraryName; |
| 141 } |
| 142 if (containingLibraryName != null) { |
| 143 json[CONTAINING_LIBRARY_PATH] = containingLibraryPath; |
| 144 } |
| 145 if (dartDoc != null) { |
| 146 json[DART_DOC] = dartDoc; |
| 147 } |
| 148 if (elementDescription != null) { |
| 149 json[ELEMENT_DESCRIPTION] = elementDescription; |
| 150 } |
| 151 if (parameter != null) { |
| 152 json[PARAMETER] = parameter; |
| 153 } |
| 154 if (propagatedType != null) { |
| 155 json[PROPAGATED_TYPE] = propagatedType; |
| 156 } |
| 157 if (staticType != null) { |
| 158 json[STATIC_TYPE] = staticType; |
| 159 } |
| 160 return json; |
| 161 } |
| 162 } |
| OLD | NEW |