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

Side by Side Diff: pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart

Issue 1303033010: Navigation extension point. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: tweaks Created 5 years, 3 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
OLDNEW
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.navigation; 5 library domains.analysis.navigation_dart;
6 6
7 import 'dart:collection'; 7 import 'package:analysis_server/analysis/navigation/navigation_core.dart';
8
9 import 'package:analysis_server/src/protocol_server.dart' as protocol; 8 import 'package:analysis_server/src/protocol_server.dart' as protocol;
10 import 'package:analyzer/src/generated/ast.dart'; 9 import 'package:analyzer/src/generated/ast.dart';
11 import 'package:analyzer/src/generated/element.dart'; 10 import 'package:analyzer/src/generated/element.dart';
11 import 'package:analyzer/src/generated/engine.dart';
12 import 'package:analyzer/src/generated/scanner.dart'; 12 import 'package:analyzer/src/generated/scanner.dart';
13 import 'package:analyzer/src/generated/source.dart'; 13 import 'package:analyzer/src/generated/source.dart';
14 14
15 /** 15 /**
16 * A computer for navigation regions in a Dart [CompilationUnit]. 16 * A computer for navigation regions in a Dart [CompilationUnit].
17 */ 17 */
18 class DartUnitNavigationComputer { 18 class DartNavigationComputer implements NavigationContributor {
19 final List<String> files = <String>[]; 19 @override
20 final Map<String, int> fileMap = new HashMap<String, int>(); 20 void computeNavigation(NavigationHolder holder, AnalysisContext context,
21 final List<protocol.NavigationTarget> targets = <protocol.NavigationTarget>[]; 21 Source source, int offset, int length) {
22 final Map<Element, int> targetMap = new HashMap<Element, int>(); 22 List<Source> libraries = context.getLibrariesContaining(source);
23 final List<protocol.NavigationRegion> regions = <protocol.NavigationRegion>[]; 23 if (libraries.isNotEmpty) {
24 24 CompilationUnit unit =
25 /** 25 context.getResolvedCompilationUnit2(source, libraries.first);
26 * Computes [regions], [targets] and [files]. 26 if (unit != null) {
27 */ 27 _DartNavigationHolder dartHolder = new _DartNavigationHolder(holder);
28 void compute(AstNode node) { 28 _DartNavigationComputerVisitor visitor =
29 node.accept(new _DartUnitNavigationComputerVisitor(this)); 29 new _DartNavigationComputerVisitor(dartHolder);
30 } 30 if (offset == null || length == null) {
31 31 unit.accept(visitor);
32 int _addFile(String file) { 32 } else {
33 int index = fileMap[file]; 33 _DartRangeAstVisitor partVisitor =
34 if (index == null) { 34 new _DartRangeAstVisitor(offset, offset + length, visitor);
35 index = files.length; 35 unit.accept(partVisitor);
36 files.add(file); 36 }
37 fileMap[file] = index; 37 }
38 } 38 }
39 return index;
40 }
41
42 void _addRegion(int offset, int length, Element element) {
43 if (element is FieldFormalParameterElement) {
44 element = (element as FieldFormalParameterElement).field;
45 }
46 if (element == null || element == DynamicElementImpl.instance) {
47 return;
48 }
49 if (element.location == null) {
50 return;
51 }
52 int targetIndex = _addTarget(element);
53 regions
54 .add(new protocol.NavigationRegion(offset, length, <int>[targetIndex]));
55 }
56
57 void _addRegion_nodeStart_nodeEnd(AstNode a, AstNode b, Element element) {
58 int offset = a.offset;
59 int length = b.end - offset;
60 _addRegion(offset, length, element);
61 }
62
63 void _addRegion_tokenStart_nodeEnd(Token a, AstNode b, Element element) {
64 int offset = a.offset;
65 int length = b.end - offset;
66 _addRegion(offset, length, element);
67 }
68
69 void _addRegionForNode(AstNode node, Element element) {
70 int offset = node.offset;
71 int length = node.length;
72 _addRegion(offset, length, element);
73 }
74
75 void _addRegionForToken(Token token, Element element) {
76 int offset = token.offset;
77 int length = token.length;
78 _addRegion(offset, length, element);
79 }
80
81 int _addTarget(Element element) {
82 int index = targetMap[element];
83 if (index == null) {
84 index = targets.length;
85 protocol.NavigationTarget target =
86 protocol.newNavigationTarget_fromElement(element, _addFile);
87 targets.add(target);
88 targetMap[element] = index;
89 }
90 return index;
91 } 39 }
92 } 40 }
93 41
94 class _DartUnitNavigationComputerVisitor extends RecursiveAstVisitor { 42 class _DartNavigationComputerVisitor extends RecursiveAstVisitor {
95 final DartUnitNavigationComputer computer; 43 final _DartNavigationHolder computer;
96 44
97 _DartUnitNavigationComputerVisitor(this.computer); 45 _DartNavigationComputerVisitor(this.computer);
98 46
99 @override 47 @override
100 visitAssignmentExpression(AssignmentExpression node) { 48 visitAssignmentExpression(AssignmentExpression node) {
101 _safelyVisit(node.leftHandSide); 49 _safelyVisit(node.leftHandSide);
102 computer._addRegionForToken(node.operator, node.bestElement); 50 computer._addRegionForToken(node.operator, node.bestElement);
103 _safelyVisit(node.rightHandSide); 51 _safelyVisit(node.rightHandSide);
104 } 52 }
105 53
106 @override 54 @override
107 visitBinaryExpression(BinaryExpression node) { 55 visitBinaryExpression(BinaryExpression node) {
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 } 214 }
267 } 215 }
268 } 216 }
269 217
270 void _safelyVisit(AstNode node) { 218 void _safelyVisit(AstNode node) {
271 if (node != null) { 219 if (node != null) {
272 node.accept(this); 220 node.accept(this);
273 } 221 }
274 } 222 }
275 } 223 }
224
225 /**
226 * A Dart specific wrapper around [NavigationHolder].
227 */
228 class _DartNavigationHolder {
229 final NavigationHolder holder;
230
231 _DartNavigationHolder(this.holder);
232
233 void _addRegion(int offset, int length, Element element) {
234 if (element is FieldFormalParameterElement) {
235 element = (element as FieldFormalParameterElement).field;
236 }
237 if (element == null || element == DynamicElementImpl.instance) {
238 return;
239 }
240 if (element.location == null) {
241 return;
242 }
243 protocol.ElementKind kind =
244 protocol.newElementKind_fromEngine(element.kind);
245 protocol.Location location = protocol.newLocation_fromElement(element);
246 if (location == null) {
247 return;
248 }
249 holder.addRegion(offset, length, kind, location);
250 }
251
252 void _addRegion_nodeStart_nodeEnd(AstNode a, AstNode b, Element element) {
253 int offset = a.offset;
254 int length = b.end - offset;
255 _addRegion(offset, length, element);
256 }
257
258 void _addRegion_tokenStart_nodeEnd(Token a, AstNode b, Element element) {
259 int offset = a.offset;
260 int length = b.end - offset;
261 _addRegion(offset, length, element);
262 }
263
264 void _addRegionForNode(AstNode node, Element element) {
265 int offset = node.offset;
266 int length = node.length;
267 _addRegion(offset, length, element);
268 }
269
270 void _addRegionForToken(Token token, Element element) {
271 int offset = token.offset;
272 int length = token.length;
273 _addRegion(offset, length, element);
274 }
275 }
276
277 /**
278 * An AST visitor that forwards nodes intersecting with the range from
279 * [start] to [end] to the given [visitor].
280 */
281 class _DartRangeAstVisitor extends UnifyingAstVisitor {
282 final int start;
283 final int end;
284 final AstVisitor visitor;
285
286 _DartRangeAstVisitor(this.start, this.end, this.visitor);
287
288 bool isInRange(int offset) {
289 return start <= offset && offset <= end;
290 }
291
292 @override
293 visitNode(AstNode node) {
294 // The node ends before the range starts.
295 if (node.end < start) {
296 return;
297 }
298 // The node starts after the range ends.
299 if (node.offset > end) {
300 return;
301 }
302 // The node starts or ends in the range.
303 if (isInRange(node.offset) || isInRange(node.end)) {
304 node.accept(visitor);
305 return;
306 }
307 // Go deeper.
308 super.visitNode(node);
309 }
310 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698