Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: pkg/analysis_server/lib/src/computer/computer_outline.dart

Issue 319523004: Outline notification implementation in server. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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.outline;
6
7 import 'package:analysis_server/src/constants.dart';
8 import 'package:analyzer/src/generated/ast.dart';
9
10
11 /**
12 * A computer for [Outline]s in a Dart [CompilationUnit].
13 */
14 class DartUnitOutlineComputer {
15 static String _UNITTEST_LIBRARY = "unittest";
16
17 final CompilationUnit _unit;
18
19 List<Map<String, Object>> _regions = <Map<String, Object>>[];
20
21 DartUnitOutlineComputer(this._unit);
22
23 /**
24 * Returns the computed outlines, not `null`.
25 */
26 Map<String, Object> compute() {
27 _Outline unitOutline = _newUnitOutline();
28 for (CompilationUnitMember unitMember in _unit.declarations) {
29 if (unitMember is ClassDeclaration) {
30 ClassDeclaration classDeclartion = unitMember;
31 _Outline classOutline = _newClassOutline(unitOutline, classDeclartion);
32 for (ClassMember classMember in classDeclartion.members) {
33 if (classMember is ConstructorDeclaration) {
34 ConstructorDeclaration constructorDeclaration = classMember;
35 _newConstructorOutline(classOutline, constructorDeclaration);
36 }
37 if (classMember is FieldDeclaration) {
38 FieldDeclaration fieldDeclaration = classMember;
39 VariableDeclarationList fields = fieldDeclaration.fields;
40 if (fields != null) {
41 TypeName fieldType = fields.type;
42 String fieldTypeName = fieldType != null ? fieldType.toSource() : "";
43 for (VariableDeclaration field in fields.variables) {
44 _newVariableOutline(classOutline, fieldTypeName, _OutlineKind.FI ELD, field, fieldDeclaration.isStatic);
45 }
46 }
47 }
48 if (classMember is MethodDeclaration) {
49 MethodDeclaration methodDeclaration = classMember;
50 _newMethodOutline(classOutline, methodDeclaration);
51 }
52 }
53 }
54 if (unitMember is TopLevelVariableDeclaration) {
55 TopLevelVariableDeclaration fieldDeclaration = unitMember;
56 VariableDeclarationList fields = fieldDeclaration.variables;
57 if (fields != null) {
58 TypeName fieldType = fields.type;
59 String fieldTypeName = fieldType != null ? fieldType.toSource() : "";
60 for (VariableDeclaration field in fields.variables) {
61 _newVariableOutline(unitOutline, fieldTypeName, _OutlineKind.TOP_LEV EL_VARIABLE, field, false);
62 }
63 }
64 }
65 if (unitMember is FunctionDeclaration) {
66 FunctionDeclaration functionDeclaration = unitMember;
67 _newFunctionOutline(unitOutline, functionDeclaration);
68 }
69 if (unitMember is ClassTypeAlias) {
70 ClassTypeAlias alias = unitMember;
71 _newClassTypeAlias(unitOutline, alias);
72 }
73 if (unitMember is FunctionTypeAlias) {
74 FunctionTypeAlias alias = unitMember;
75 _newFunctionTypeAliasOutline(unitOutline, alias);
76 }
77 }
78 return unitOutline.toJson();
79 }
80
81 void _addLocalFunctionOutlines(_Outline parent, FunctionBody body) {
82 body.accept(new _LocalFunctionOutlinesVisitor(this, parent));
83 }
84
85 /**
86 * Returns the [AstNode]'s source region.
87 */
88 _SourceRegion _getSourceRegion(AstNode node) {
89 int endOffset = node.end;
90 // prepare position of the node among its siblings
91 int firstOffset;
92 List<AstNode> siblings;
93 AstNode parent = node.parent;
94 // field
95 if (parent is VariableDeclarationList) {
96 VariableDeclarationList variableList = parent as VariableDeclarationList;
97 List<VariableDeclaration> variables = variableList.variables;
98 int variableIndex = variables.indexOf(node);
99 if (variableIndex == variables.length - 1) {
100 endOffset = variableList.parent.end;
101 }
102 if (variableIndex == 0) {
103 node = parent.parent;
104 parent = node.parent;
105 } else if (variableIndex >= 1) {
106 firstOffset = variables[variableIndex - 1].end;
107 return new _SourceRegion(firstOffset, endOffset - firstOffset);
108 }
109 }
110 // unit or class member
111 if (parent is CompilationUnit) {
112 firstOffset = 0;
113 siblings = (parent as CompilationUnit).declarations;
114 } else if (parent is ClassDeclaration) {
115 ClassDeclaration classDeclaration = parent as ClassDeclaration;
116 firstOffset = classDeclaration.leftBracket.end;
117 siblings = classDeclaration.members;
118 } else {
119 int offset = node.offset;
120 return new _SourceRegion(offset, endOffset - offset);
121 }
122 // first child: [endOfParent, endOfNode]
123 int index = siblings.indexOf(node);
124 if (index == 0) {
125 return new _SourceRegion(firstOffset, endOffset - firstOffset);
126 }
127 // not first child: [endOfPreviousSibling, endOfNode]
128 int prevSiblingEnd = siblings[index - 1].end;
129 return new _SourceRegion(prevSiblingEnd, endOffset - prevSiblingEnd);
130 }
131
132 _Outline _newClassOutline(_Outline parent, ClassDeclaration classDeclaration) {
133 SimpleIdentifier nameNode = classDeclaration.name;
134 String name = nameNode.name;
135 _SourceRegion sourceRegion = _getSourceRegion(classDeclaration);
136 _Outline outline = new _Outline(
137 _OutlineKind.CLASS, name,
138 nameNode.offset, nameNode.length,
139 sourceRegion.offset, sourceRegion.length,
140 classDeclaration.isAbstract, false,
141 null, null);
142 parent.children.add(outline);
143 return outline;
144 }
145
146 void _newClassTypeAlias(_Outline parent, ClassTypeAlias alias) {
147 SimpleIdentifier nameNode = alias.name;
148 String name = nameNode.name;
149 _SourceRegion sourceRegion = _getSourceRegion(alias);
150 _Outline outline = new _Outline(
151 _OutlineKind.CLASS_TYPE_ALIAS, name,
152 nameNode.offset, nameNode.length,
153 sourceRegion.offset, sourceRegion.length,
154 alias.isAbstract, false,
155 null, null);
156 parent.children.add(outline);
157 }
158
159 void _newConstructorOutline(_Outline parent, ConstructorDeclaration constructo r) {
160 Identifier returnType = constructor.returnType;
161 String name = returnType.name;
162 int offset = returnType.offset;
163 int length = returnType.length;
164 SimpleIdentifier constructorNameNode = constructor.name;
165 if (constructorNameNode != null) {
166 String constructorName = constructorNameNode.name;
167 name += ".${constructorName}";
168 offset = constructorNameNode.offset;
169 length = constructorNameNode.length;
170 }
171 _SourceRegion sourceRegion = _getSourceRegion(constructor);
172 FormalParameterList parameters = constructor.parameters;
173 String parametersStr = parameters != null ? parameters.toSource() : "";
174 _Outline outline = new _Outline(
175 _OutlineKind.CONSTRUCTOR, name,
176 offset, length,
177 sourceRegion.offset, sourceRegion.length,
178 false, false,
179 parametersStr, null);
180 parent.children.add(outline);
181 _addLocalFunctionOutlines(outline, constructor.body);
182 }
183
184 void _newFunctionOutline(_Outline parent, FunctionDeclaration function) {
185 TypeName returnType = function.returnType;
186 SimpleIdentifier nameNode = function.name;
187 String name = nameNode.name;
188 FunctionExpression functionExpression = function.functionExpression;
189 FormalParameterList parameters = functionExpression.parameters;
190 _OutlineKind kind;
191 if (function.isGetter) {
192 kind = _OutlineKind.GETTER;
193 } else if (function.isSetter) {
194 kind = _OutlineKind.SETTER;
195 } else {
196 kind = _OutlineKind.FUNCTION;
197 }
198 _SourceRegion sourceRegion = _getSourceRegion(function);
199 String parametersStr = parameters != null ? parameters.toSource() : "";
200 String returnTypeStr = returnType != null ? returnType.toSource() : "";
201 _Outline outline = new _Outline(
202 kind, name,
203 nameNode.offset, nameNode.length,
204 sourceRegion.offset, sourceRegion.length,
205 false, false,
206 parametersStr, returnTypeStr);
207 parent.children.add(outline);
208 _addLocalFunctionOutlines(outline, functionExpression.body);
209 }
210
211 void _newFunctionTypeAliasOutline(_Outline parent, FunctionTypeAlias alias) {
212 TypeName returnType = alias.returnType;
213 SimpleIdentifier nameNode = alias.name;
214 String name = nameNode.name;
215 _SourceRegion sourceRegion = _getSourceRegion(alias);
216 FormalParameterList parameters = alias.parameters;
217 String parametersStr = parameters != null ? parameters.toSource() : "";
218 String returnTypeStr = returnType != null ? returnType.toSource() : "";
219 _Outline outline = new _Outline(
220 _OutlineKind.FUNCTION_TYPE_ALIAS, name,
221 nameNode.offset, nameNode.length,
222 sourceRegion.offset, sourceRegion.length,
223 false, false,
224 parametersStr, returnTypeStr);
225 parent.children.add(outline);
226 }
227
228 void _newMethodOutline(_Outline parent, MethodDeclaration method) {
229 TypeName returnType = method.returnType;
230 SimpleIdentifier nameNode = method.name;
231 String name = nameNode.name;
232 FormalParameterList parameters = method.parameters;
233 _OutlineKind kind;
234 if (method.isGetter) {
235 kind = _OutlineKind.GETTER;
236 } else if (method.isSetter) {
237 kind = _OutlineKind.SETTER;
238 } else {
239 kind = _OutlineKind.METHOD;
240 }
241 _SourceRegion sourceRegion = _getSourceRegion(method);
242 String parametersStr = parameters != null ? parameters.toSource() : "";
243 String returnTypeStr = returnType != null ? returnType.toSource() : "";
244 _Outline outline = new _Outline(
245 kind, name,
246 nameNode.offset, nameNode.length,
247 sourceRegion.offset, sourceRegion.length,
248 method.isAbstract, method.isStatic,
249 parametersStr, returnTypeStr);
250 parent.children.add(outline);
251 _addLocalFunctionOutlines(outline, method.body);
252 }
253
254 _Outline _newUnitOutline() {
255 return new _Outline(
256 _OutlineKind.COMPILATION_UNIT, null,
257 _unit.offset, _unit.length,
258 _unit.offset, _unit.length,
259 false, false,
260 null, null);
261 }
262
263 void _newVariableOutline(_Outline parent, String typeName, _OutlineKind kind, VariableDeclaration variable, bool isStatic) {
264 SimpleIdentifier nameNode = variable.name;
265 String name = nameNode.name;
266 _SourceRegion sourceRegion = _getSourceRegion(variable);
267 _Outline outline = new _Outline(
268 kind, name,
269 nameNode.offset, nameNode.length,
270 sourceRegion.offset, sourceRegion.length,
271 false, isStatic,
272 null, typeName);
273 parent.children.add(outline);
274 }
275 }
276
277
278 class _LocalFunctionOutlinesVisitor extends RecursiveAstVisitor {
279 final DartUnitOutlineComputer outlineComputer;
280
281 _Outline parent;
282
283 _LocalFunctionOutlinesVisitor(this.outlineComputer, this.parent);
284
285 @override
286 visitFunctionDeclaration(FunctionDeclaration node) {
287 outlineComputer._newFunctionOutline(parent, node);
288 }
289 }
290
291
292
293 /**
294 * A range of characters.
295 */
296 class _SourceRegion {
297 final int offset;
298 final int length;
299 _SourceRegion(this.offset, this.length);
300 }
301
302
303 /**
304 * Element outline kinds.
305 */
306 class _OutlineKind {
307 static const _OutlineKind CLASS = const _OutlineKind('CLASS');
308 static const _OutlineKind CLASS_TYPE_ALIAS = const _OutlineKind('CLASS_TYPE_AL IAS');
309 static const _OutlineKind COMPILATION_UNIT = const _OutlineKind('COMPILATION_U NIT');
310 static const _OutlineKind CONSTRUCTOR = const _OutlineKind('CONSTRUCTOR');
311 static const _OutlineKind GETTER = const _OutlineKind('GETTER');
312 static const _OutlineKind FIELD = const _OutlineKind('FIELD');
313 static const _OutlineKind FUNCTION = const _OutlineKind('FUNCTION');
314 static const _OutlineKind FUNCTION_TYPE_ALIAS = const _OutlineKind('FUNCTION_T YPE_ALIAS');
315 static const _OutlineKind LIBRARY = const _OutlineKind('LIBRARY');
316 static const _OutlineKind METHOD = const _OutlineKind('METHOD');
317 static const _OutlineKind SETTER = const _OutlineKind('SETTER');
318 static const _OutlineKind TOP_LEVEL_VARIABLE = const _OutlineKind('TOP_LEVEL_V ARIABLE');
319 static const _OutlineKind UNKNOWN = const _OutlineKind('UNKNOWN');
320 static const _OutlineKind UNIT_TEST_CASE = const _OutlineKind('UNIT_TEST_CASE' );
321 static const _OutlineKind UNIT_TEST_GROUP = const _OutlineKind('UNIT_TEST_GROU P');
322
323 final String name;
324
325 const _OutlineKind(this.name);
326 }
327
328
329 class _Outline {
330 static const List<_Outline> EMPTY_ARRAY = const <_Outline>[];
331
332 _Outline parent;
333 final _OutlineKind kind;
334 final String name;
335 final int nameOffset;
336 final int nameLength;
337 final int elementOffset;
338 final int elementLength;
339 final bool isAbstract;
340 final bool isStatic;
341 final String arguments;
342 final String returnType;
343 final List<_Outline> children = <_Outline>[];
344
345 _Outline(this.kind, this.name,
346 this.nameOffset, this.nameLength,
347 this.elementOffset, this.elementLength,
348 this.isAbstract, this.isStatic,
349 this.arguments, this.returnType);
350
351 Map<String, Object> toJson() {
352 return {
353 KIND: kind.name,
354 NAME: name,
355 NAME_OFFSET: nameOffset,
356 NAME_LENGTH: nameLength,
357 ELEMENT_OFFSET: elementOffset,
358 ELEMENT_LENGTH: elementLength,
359 IS_ABSTRACT: isAbstract,
360 IS_STATIC: isStatic,
361 ARGUMENTS: arguments,
362 RETURN_TYPE: returnType,
363 CHILDREN: children.map((child) => child.toJson()).toList(growable: false)
364 };
365 }
366 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698