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 services.completion.computer.dart.local; | |
6 | |
7 import 'dart:async'; | |
8 | |
9 import 'package:analysis_services/completion/completion_suggestion.dart'; | |
10 import 'package:analysis_services/src/completion/dart_completion_manager.dart'; | |
11 import 'package:analyzer/src/generated/ast.dart'; | |
12 | |
13 /** | |
14 * A computer for calculating `completion.getSuggestions` request results | |
15 * for the local library in which the completion is requested. | |
16 */ | |
17 class LocalComputer extends DartCompletionComputer { | |
18 | |
19 @override | |
20 bool computeFast(DartCompletionRequest request) { | |
21 | |
22 // Find the specific child [AstNode] that contains the completion offset | |
23 // and collect suggestions starting with that node | |
24 request.node.accept(new _LocalVisitor(request)); | |
25 | |
26 // If the unit is not a part and does not reference any parts | |
27 // then work is complete | |
28 return !request.unit.directives.any( | |
29 (Directive directive) => | |
30 directive is PartOfDirective || directive is PartDirective); | |
31 } | |
32 | |
33 @override | |
34 Future<bool> computeFull(DartCompletionRequest request) { | |
35 // TODO: implement computeFull | |
36 // include results from part files that are included in the library | |
37 return new Future.value(false); | |
38 } | |
39 } | |
40 | |
41 /** | |
42 * A visitor for collecting suggestions from the most specific child [AstNode] | |
43 * that contains the completion offset to the [CompilationUnit]. | |
44 */ | |
45 class _LocalVisitor extends GeneralizingAstVisitor<dynamic> { | |
46 final DartCompletionRequest request; | |
47 | |
48 _LocalVisitor(this.request); | |
49 | |
50 @override | |
51 visitBlock(Block node) { | |
52 node.statements.forEach((Statement stmt) { | |
53 if (stmt.offset < request.offset) { | |
54 if (stmt is LabeledStatement) { | |
55 stmt.labels.forEach((Label label) { | |
56 // _addSuggestion(label.label, CompletionSuggestionKind.LABEL); | |
57 }); | |
58 } else if (stmt is VariableDeclarationStatement) { | |
59 stmt.variables.variables.forEach((VariableDeclaration varDecl) { | |
60 if (varDecl.end < request.offset) { | |
61 _addSuggestion( | |
62 varDecl.name, | |
63 CompletionSuggestionKind.LOCAL_VARIABLE); | |
64 } | |
65 }); | |
66 } | |
67 } | |
68 }); | |
69 visitNode(node); | |
70 } | |
71 | |
72 @override | |
73 visitCatchClause(CatchClause node) { | |
74 _addSuggestion(node.exceptionParameter, CompletionSuggestionKind.PARAMETER); | |
75 _addSuggestion(node.stackTraceParameter, CompletionSuggestionKind.PARAMETER)
; | |
76 visitNode(node); | |
77 } | |
78 | |
79 @override | |
80 visitClassDeclaration(ClassDeclaration node) { | |
81 node.members.forEach((ClassMember classMbr) { | |
82 if (classMbr is FieldDeclaration) { | |
83 _addSuggestions(classMbr.fields, CompletionSuggestionKind.FIELD); | |
84 } else if (classMbr is MethodDeclaration) { | |
85 _addSuggestion(classMbr.name, CompletionSuggestionKind.METHOD_NAME); | |
86 } | |
87 }); | |
88 visitNode(node); | |
89 } | |
90 | |
91 @override | |
92 visitCompilationUnit(CompilationUnit node) { | |
93 node.directives.forEach((Directive directive) { | |
94 if (directive is ImportDirective) { | |
95 _addSuggestion( | |
96 directive.prefix, | |
97 CompletionSuggestionKind.LIBRARY_PREFIX); | |
98 } | |
99 }); | |
100 node.declarations.forEach((Declaration declaration) { | |
101 if (declaration is ClassDeclaration) { | |
102 _addSuggestion(declaration.name, CompletionSuggestionKind.CLASS); | |
103 } else if (declaration is EnumDeclaration) { | |
104 // _addSuggestion(d.name, CompletionSuggestionKind.ENUM); | |
105 } else if (declaration is FunctionDeclaration) { | |
106 _addSuggestion(declaration.name, CompletionSuggestionKind.FUNCTION); | |
107 } else if (declaration is TopLevelVariableDeclaration) { | |
108 _addSuggestions( | |
109 declaration.variables, | |
110 CompletionSuggestionKind.TOP_LEVEL_VARIABLE); | |
111 } else if (declaration is ClassTypeAlias) { | |
112 _addSuggestion(declaration.name, CompletionSuggestionKind.CLASS_ALIAS); | |
113 } else if (declaration is FunctionTypeAlias) { | |
114 _addSuggestion( | |
115 declaration.name, | |
116 CompletionSuggestionKind.FUNCTION_TYPE_ALIAS); | |
117 } | |
118 }); | |
119 } | |
120 | |
121 @override | |
122 visitForEachStatement(ForEachStatement node) { | |
123 _addSuggestion(node.identifier, CompletionSuggestionKind.LOCAL_VARIABLE); | |
124 visitNode(node); | |
125 } | |
126 | |
127 @override | |
128 visitForStatement(ForStatement node) { | |
129 _addSuggestions(node.variables, CompletionSuggestionKind.LOCAL_VARIABLE); | |
130 visitNode(node); | |
131 } | |
132 | |
133 @override | |
134 visitFunctionDeclaration(FunctionDeclaration node) { | |
135 // This is added by the compilation unit containing it | |
136 //_addSuggestion(node.name, CompletionSuggestionKind.FUNCTION); | |
137 visitNode(node); | |
138 } | |
139 | |
140 @override | |
141 visitFunctionExpression(FunctionExpression node) { | |
142 node.parameters.parameters.forEach((FormalParameter param) { | |
143 _addSuggestion(param.identifier, CompletionSuggestionKind.PARAMETER); | |
144 }); | |
145 visitNode(node); | |
146 } | |
147 | |
148 @override | |
149 visitMethodDeclaration(MethodDeclaration node) { | |
150 node.parameters.parameters.forEach((FormalParameter param) { | |
151 if (param.identifier != null) { | |
152 _addSuggestion(param.identifier, CompletionSuggestionKind.PARAMETER); | |
153 } | |
154 }); | |
155 visitNode(node); | |
156 } | |
157 | |
158 @override | |
159 visitNode(AstNode node) { | |
160 node.parent.accept(this); | |
161 } | |
162 | |
163 @override | |
164 visitVariableDeclaration(VariableDeclaration node) { | |
165 // Do not add suggestions if editing the name in a var declaration | |
166 SimpleIdentifier name = node.name; | |
167 if (name == null || | |
168 name.offset < request.offset || | |
169 request.offset > name.end) { | |
170 visitNode(node); | |
171 } | |
172 } | |
173 | |
174 void _addSuggestion(SimpleIdentifier id, CompletionSuggestionKind kind) { | |
175 if (id != null) { | |
176 String completion = id.name; | |
177 if (completion != null && completion.length > 0) { | |
178 request.suggestions.add( | |
179 new CompletionSuggestion( | |
180 kind, | |
181 CompletionRelevance.DEFAULT, | |
182 completion, | |
183 completion.length, | |
184 0, | |
185 false, | |
186 false)); | |
187 } | |
188 } | |
189 } | |
190 | |
191 void _addSuggestions(VariableDeclarationList variables, | |
192 CompletionSuggestionKind kind) { | |
193 variables.variables.forEach((VariableDeclaration varDecl) { | |
194 _addSuggestion(varDecl.name, kind); | |
195 }); | |
196 } | |
197 } | |
OLD | NEW |