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 computer.element; | 5 library computer.element; |
6 | 6 |
7 import 'package:analysis_server/src/constants.dart'; | |
8 import 'package:analysis_server/src/protocol2.dart'; | 7 import 'package:analysis_server/src/protocol2.dart'; |
9 import 'package:analyzer/src/generated/element.dart' as engine; | 8 import 'package:analyzer/src/generated/element.dart' as engine; |
10 import 'package:analyzer/src/generated/source.dart'; | |
11 import 'package:analyzer/src/generated/utilities_dart.dart' as engine; | 9 import 'package:analyzer/src/generated/utilities_dart.dart' as engine; |
12 | 10 |
13 | 11 |
14 /** | 12 /** |
15 * Returns a JSON correponding to the given Engine element. | 13 * Returns a JSON correponding to the given Engine element. |
16 */ | 14 */ |
17 Map<String, Object> engineElementToJson(engine.Element element) { | 15 Map<String, Object> engineElementToJson(engine.Element element) { |
18 return new Element.fromEngine(element).toJson(); | 16 return new Element.fromEngine(element).toJson(); |
19 } | 17 } |
20 | 18 |
21 | 19 |
22 /** | 20 Element elementFromEngine(engine.Element element) { |
23 * Information about an element. | 21 String name = element.displayName; |
24 */ | 22 String elementParameters = _getParametersString(element); |
25 class Element { | 23 String elementReturnType = _getReturnTypeString(element); |
26 static const List<Element> EMPTY_ARRAY = const <Element>[]; | 24 return new Element( |
27 | 25 new ElementKind.fromEngine(element.kind), |
28 static const int FLAG_ABSTRACT = 0x01; | 26 name, |
29 static const int FLAG_CONST = 0x02; | 27 Element.makeFlags(isPrivate: element.isPrivate, |
30 static const int FLAG_FINAL = 0x04; | 28 isDeprecated: element.isDeprecated, |
31 static const int FLAG_STATIC = 0x08; | |
32 static const int FLAG_PRIVATE = 0x10; | |
33 static const int FLAG_DEPRECATED = 0x20; | |
34 | |
35 /** | |
36 * The kind of the element. | |
37 */ | |
38 final ElementKind kind; | |
39 | |
40 /** | |
41 * The name of the element. This is typically used as the label in the outline
. | |
42 */ | |
43 final String name; | |
44 | |
45 /** | |
46 * The location of the element. | |
47 */ | |
48 final Location location; | |
49 | |
50 /** | |
51 * The parameter list for the element. | |
52 * If the element is not a method or function then `null`. | |
53 * If the element has zero parameters, then `()`. | |
54 */ | |
55 final String parameters; | |
56 | |
57 /** | |
58 * The return type of the element. | |
59 * If the element is not a method or function then `null`. | |
60 * If the element does not have a declared return type, then an empty string. | |
61 */ | |
62 final String returnType; | |
63 | |
64 final bool isAbstract; | |
65 final bool isConst; | |
66 final bool isFinal; | |
67 final bool isStatic; | |
68 final bool isPrivate; | |
69 final bool isDeprecated; | |
70 | |
71 Element(this.kind, this.name, this.location, this.isPrivate, | |
72 this.isDeprecated, {this.parameters, this.returnType, this.isAbstract: fal
se, | |
73 this.isConst: false, this.isFinal: false, this.isStatic: false}); | |
74 | |
75 factory Element.fromEngine(engine.Element element) { | |
76 String name = element.displayName; | |
77 String elementParameters = _getParametersString(element); | |
78 String elementReturnType = _getReturnTypeString(element); | |
79 return new Element( | |
80 new ElementKind.fromEngine(element.kind), | |
81 name, | |
82 new Location.fromElement(element), | |
83 element.isPrivate, | |
84 element.isDeprecated, | |
85 parameters: elementParameters, | |
86 returnType: elementReturnType, | |
87 isAbstract: _isAbstract(element), | 29 isAbstract: _isAbstract(element), |
88 isConst: _isConst(element), | 30 isConst: _isConst(element), |
89 isFinal: _isFinal(element), | 31 isFinal: _isFinal(element), |
90 isStatic: _isStatic(element)); | 32 isStatic: _isStatic(element)), |
91 } | 33 location: new Location.fromElement(element), |
| 34 parameters: elementParameters, |
| 35 returnType: elementReturnType); |
| 36 } |
92 | 37 |
93 factory Element.fromJson(Map<String, Object> map) { | 38 String _getParametersString(engine.Element element) { |
94 ElementKind kind = new ElementKind(map[KIND]); | 39 // TODO(scheglov) expose the corresponding feature from ExecutableElement |
95 int flags = map[FLAGS]; | 40 if (element is engine.ExecutableElement) { |
96 return new Element( | 41 var sb = new StringBuffer(); |
97 kind, | 42 String closeOptionalString = ''; |
98 map[NAME], | 43 for (var parameter in element.parameters) { |
99 new Location.fromJson(map[LOCATION]), | 44 if (sb.isNotEmpty) { |
100 _hasFlag(flags, FLAG_PRIVATE), | 45 sb.write(', '); |
101 _hasFlag(flags, FLAG_DEPRECATED), | 46 } |
102 parameters: map[PARAMETERS], | 47 if (closeOptionalString.isEmpty) { |
103 returnType: map[RETURN_TYPE], | 48 if (parameter.kind == engine.ParameterKind.NAMED) { |
104 isAbstract: _hasFlag(flags, FLAG_ABSTRACT), | 49 sb.write('{'); |
105 isConst: _hasFlag(flags, FLAG_CONST), | 50 closeOptionalString = '}'; |
106 isFinal: _hasFlag(flags, FLAG_FINAL), | 51 } |
107 isStatic: _hasFlag(flags, FLAG_STATIC)); | 52 if (parameter.kind == engine.ParameterKind.POSITIONAL) { |
108 } | 53 sb.write('['); |
109 | 54 closeOptionalString = ']'; |
110 int get flags { | 55 } |
111 int flags = 0; | 56 } |
112 if (isAbstract) flags |= FLAG_ABSTRACT; | 57 sb.write(parameter.toString()); |
113 if (isConst) flags |= FLAG_CONST; | |
114 if (isFinal) flags |= FLAG_FINAL; | |
115 if (isStatic) flags |= FLAG_STATIC; | |
116 if (isPrivate) flags |= FLAG_PRIVATE; | |
117 if (isDeprecated) flags |= FLAG_DEPRECATED; | |
118 return flags; | |
119 } | |
120 | |
121 Map<String, Object> toJson() { | |
122 Map<String, Object> json = { | |
123 KIND: kind.name, | |
124 NAME: name, | |
125 LOCATION: location.toJson(), | |
126 FLAGS: flags | |
127 }; | |
128 if (parameters != null) { | |
129 json[PARAMETERS] = parameters; | |
130 } | 58 } |
131 if (returnType != null) { | 59 sb.write(closeOptionalString); |
132 json[RETURN_TYPE] = returnType; | 60 return '(' + sb.toString() + ')'; |
133 } | 61 } else { |
134 return json; | 62 return null; |
135 } | |
136 | |
137 @override | |
138 String toString() => toJson().toString(); | |
139 | |
140 static Map<String, Object> asJson(Element element) { | |
141 return element.toJson(); | |
142 } | |
143 | |
144 static String _getParametersString(engine.Element element) { | |
145 // TODO(scheglov) expose the corresponding feature from ExecutableElement | |
146 if (element is engine.ExecutableElement) { | |
147 var sb = new StringBuffer(); | |
148 String closeOptionalString = ''; | |
149 for (var parameter in element.parameters) { | |
150 if (sb.isNotEmpty) { | |
151 sb.write(', '); | |
152 } | |
153 if (closeOptionalString.isEmpty) { | |
154 if (parameter.kind == engine.ParameterKind.NAMED) { | |
155 sb.write('{'); | |
156 closeOptionalString = '}'; | |
157 } | |
158 if (parameter.kind == engine.ParameterKind.POSITIONAL) { | |
159 sb.write('['); | |
160 closeOptionalString = ']'; | |
161 } | |
162 } | |
163 sb.write(parameter.toString()); | |
164 } | |
165 sb.write(closeOptionalString); | |
166 return '(' + sb.toString() + ')'; | |
167 } else { | |
168 return null; | |
169 } | |
170 } | |
171 | |
172 static String _getReturnTypeString(engine.Element element) { | |
173 if ((element is engine.ExecutableElement)) { | |
174 return element.returnType.toString(); | |
175 } else { | |
176 return null; | |
177 } | |
178 } | |
179 | |
180 static bool _hasFlag(int flags, int flag) => (flags & flag) != 0; | |
181 | |
182 static bool _isAbstract(engine.Element element) { | |
183 // TODO(scheglov) add isAbstract to Element API | |
184 if (element is engine.ClassElement) { | |
185 return element.isAbstract; | |
186 } | |
187 if (element is engine.MethodElement) { | |
188 return element.isAbstract; | |
189 } | |
190 if (element is engine.PropertyAccessorElement) { | |
191 return element.isAbstract; | |
192 } | |
193 return false; | |
194 } | |
195 | |
196 static bool _isConst(engine.Element element) { | |
197 // TODO(scheglov) add isConst to Element API | |
198 if (element is engine.ConstructorElement) { | |
199 return element.isConst; | |
200 } | |
201 if (element is engine.VariableElement) { | |
202 return element.isConst; | |
203 } | |
204 return false; | |
205 } | |
206 | |
207 static bool _isFinal(engine.Element element) { | |
208 // TODO(scheglov) add isFinal to Element API | |
209 if (element is engine.VariableElement) { | |
210 return element.isFinal; | |
211 } | |
212 return false; | |
213 } | |
214 | |
215 static bool _isStatic(engine.Element element) { | |
216 // TODO(scheglov) add isStatic to Element API | |
217 if (element is engine.ExecutableElement) { | |
218 return element.isStatic; | |
219 } | |
220 if (element is engine.PropertyInducingElement) { | |
221 return element.isStatic; | |
222 } | |
223 return false; | |
224 } | 63 } |
225 } | 64 } |
226 | 65 |
227 | 66 String _getReturnTypeString(engine.Element element) { |
228 /** | 67 if ((element is engine.ExecutableElement)) { |
229 * Information about a location. | 68 return element.returnType.toString(); |
230 */ | 69 } else { |
231 class Location { | 70 return null; |
232 final String file; | |
233 final int offset; | |
234 final int length; | |
235 final int startLine; | |
236 final int startColumn; | |
237 | |
238 Location(this.file, this.offset, this.length, this.startLine, | |
239 this.startColumn); | |
240 | |
241 factory Location.fromElement(engine.Element element) { | |
242 Source source = element.source; | |
243 LineInfo lineInfo = element.context.getLineInfo(source); | |
244 String name = element.displayName; | |
245 // prepare location | |
246 int offset = element.nameOffset; | |
247 int length = name != null ? name.length : 0; | |
248 LineInfo_Location lineLocation = lineInfo.getLocation(offset); | |
249 int startLine = lineLocation.lineNumber; | |
250 int startColumn = lineLocation.columnNumber; | |
251 if (element is engine.CompilationUnitElement) { | |
252 offset = 0; | |
253 length = 0; | |
254 startLine = 1; | |
255 startColumn = 1; | |
256 } | |
257 // done | |
258 return new Location( | |
259 source.fullName, | |
260 offset, | |
261 length, | |
262 startLine, | |
263 startColumn); | |
264 } | |
265 | |
266 factory Location.fromJson(Map<String, Object> map) { | |
267 return new Location( | |
268 map[FILE], | |
269 map[OFFSET], | |
270 map[LENGTH], | |
271 map[START_LINE], | |
272 map[START_COLUMN]); | |
273 } | |
274 | |
275 factory Location.fromOffset(engine.Element element, int offset, int length) { | |
276 Source source = element.source; | |
277 LineInfo lineInfo = element.context.getLineInfo(source); | |
278 // prepare location | |
279 LineInfo_Location lineLocation = lineInfo.getLocation(offset); | |
280 int startLine = lineLocation.lineNumber; | |
281 int startColumn = lineLocation.columnNumber; | |
282 // done | |
283 return new Location( | |
284 source.fullName, | |
285 offset, | |
286 length, | |
287 startLine, | |
288 startColumn); | |
289 } | |
290 | |
291 Map<String, Object> toJson() { | |
292 return { | |
293 FILE: file, | |
294 OFFSET: offset, | |
295 LENGTH: length, | |
296 START_LINE: startLine, | |
297 START_COLUMN: startColumn | |
298 }; | |
299 } | |
300 | |
301 @override | |
302 String toString() { | |
303 return 'Location(file=$file; offset=$offset; length=$length; ' | |
304 'startLine=$startLine; startColumn=$startColumn)'; | |
305 } | 71 } |
306 } | 72 } |
| 73 |
| 74 bool _isAbstract(engine.Element element) { |
| 75 // TODO(scheglov) add isAbstract to Element API |
| 76 if (element is engine.ClassElement) { |
| 77 return element.isAbstract; |
| 78 } |
| 79 if (element is engine.MethodElement) { |
| 80 return element.isAbstract; |
| 81 } |
| 82 if (element is engine.PropertyAccessorElement) { |
| 83 return element.isAbstract; |
| 84 } |
| 85 return false; |
| 86 } |
| 87 |
| 88 bool _isConst(engine.Element element) { |
| 89 // TODO(scheglov) add isConst to Element API |
| 90 if (element is engine.ConstructorElement) { |
| 91 return element.isConst; |
| 92 } |
| 93 if (element is engine.VariableElement) { |
| 94 return element.isConst; |
| 95 } |
| 96 return false; |
| 97 } |
| 98 |
| 99 bool _isFinal(engine.Element element) { |
| 100 // TODO(scheglov) add isFinal to Element API |
| 101 if (element is engine.VariableElement) { |
| 102 return element.isFinal; |
| 103 } |
| 104 return false; |
| 105 } |
| 106 |
| 107 bool _isStatic(engine.Element element) { |
| 108 // TODO(scheglov) add isStatic to Element API |
| 109 if (element is engine.ExecutableElement) { |
| 110 return element.isStatic; |
| 111 } |
| 112 if (element is engine.PropertyInducingElement) { |
| 113 return element.isStatic; |
| 114 } |
| 115 return false; |
| 116 } |
OLD | NEW |