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

Side by Side Diff: pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart

Issue 1514263004: extract LabelContributor from local reference contributor (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: merge Created 5 years 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
(Empty)
1 // Copyright (c) 2015, 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.contributor.dart.local_ref;
6
7 import 'dart:async';
8
9 import 'package:analysis_server/plugin/protocol/protocol.dart' as protocol
10 show Element, ElementKind;
11 import 'package:analysis_server/src/provisional/completion/dart/completion_dart. dart';
12 import 'package:analysis_server/src/services/completion/dart/completion_manager. dart'
13 show DartCompletionRequestImpl;
14 import 'package:analysis_server/src/services/completion/local_declaration_visito r.dart'
15 show LocalDeclarationVisitor;
16 import 'package:analysis_server/src/services/completion/optype.dart';
17 import 'package:analyzer/src/generated/ast.dart';
18 import 'package:analyzer/src/generated/scanner.dart';
19 import 'package:analyzer/src/generated/source.dart';
20
21 import '../../../protocol_server.dart'
22 show CompletionSuggestion, CompletionSuggestionKind, Location;
23
24 const DYNAMIC = 'dynamic';
25
26 final TypeName NO_RETURN_TYPE = new TypeName(
27 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, '', 0)), null);
28
29 /**
30 * A contributor for calculating label suggestions.
31 */
32 class LabelContributor extends DartCompletionContributor {
33 @override
34 Future<List<CompletionSuggestion>> computeSuggestions(
35 DartCompletionRequest request) async {
36 OpType optype = (request as DartCompletionRequestImpl).opType;
37
38 // Collect suggestions from the specific child [AstNode] that contains
39 // the completion offset and all of its parents recursively.
40 List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
41 if (!optype.isPrefixed) {
42 if (optype.includeStatementLabelSuggestions ||
43 optype.includeCaseLabelSuggestions) {
44 new _LabelVisitor(request, optype.includeStatementLabelSuggestions,
45 optype.includeCaseLabelSuggestions, suggestions)
46 .visit(request.target.containingNode);
47 }
48 }
49 return suggestions;
50 }
51 }
52
53 /**
54 * A visitor for collecting suggestions for break and continue labels.
55 */
56 class _LabelVisitor extends LocalDeclarationVisitor {
57 final DartCompletionRequest request;
58 final List<CompletionSuggestion> suggestions;
59
60 /**
61 * True if statement labels should be included as suggestions.
62 */
63 final bool includeStatementLabels;
64
65 /**
66 * True if case labels should be included as suggestions.
67 */
68 final bool includeCaseLabels;
69
70 _LabelVisitor(DartCompletionRequest request, this.includeStatementLabels,
71 this.includeCaseLabels, this.suggestions)
72 : super(request.offset),
73 request = request;
74
75 @override
76 void declaredClass(ClassDeclaration declaration) {
77 // ignored
78 }
79
80 @override
81 void declaredClassTypeAlias(ClassTypeAlias declaration) {
82 // ignored
83 }
84
85 @override
86 void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
87 // ignored
88 }
89
90 @override
91 void declaredFunction(FunctionDeclaration declaration) {
92 // ignored
93 }
94
95 @override
96 void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {
97 // ignored
98 }
99
100 @override
101 void declaredLabel(Label label, bool isCaseLabel) {
102 if (isCaseLabel ? includeCaseLabels : includeStatementLabels) {
103 CompletionSuggestion suggestion = _addSuggestion(label.label);
104 if (suggestion != null) {
105 suggestion.element = createLocalElement(
106 request.source, protocol.ElementKind.LABEL, label.label,
107 returnType: NO_RETURN_TYPE);
108 }
109 }
110 }
111
112 @override
113 void declaredLocalVar(SimpleIdentifier name, TypeName type) {
114 // ignored
115 }
116
117 @override
118 void declaredMethod(MethodDeclaration declaration) {
119 // ignored
120 }
121
122 @override
123 void declaredParam(SimpleIdentifier name, TypeName type) {
124 // ignored
125 }
126
127 @override
128 void declaredTopLevelVar(
129 VariableDeclarationList varList, VariableDeclaration varDecl) {
130 // ignored
131 }
132
133 @override
134 void visitFunctionExpression(FunctionExpression node) {
135 // Labels are only accessible within the local function, so stop visiting
136 // once we reach a function boundary.
137 finished();
138 }
139
140 @override
141 void visitMethodDeclaration(MethodDeclaration node) {
142 // Labels are only accessible within the local function, so stop visiting
143 // once we reach a function boundary.
144 finished();
145 }
146
147 CompletionSuggestion _addSuggestion(SimpleIdentifier id) {
148 if (id != null) {
149 String completion = id.name;
150 if (completion != null && completion.length > 0 && completion != '_') {
151 CompletionSuggestion suggestion = new CompletionSuggestion(
152 CompletionSuggestionKind.IDENTIFIER,
153 DART_RELEVANCE_DEFAULT,
154 completion,
155 completion.length,
156 0,
157 false,
158 false);
159 suggestions.add(suggestion);
160 return suggestion;
161 }
162 }
163 return null;
164 }
165 }
166
167 /**
168 * Create a new protocol Element for inclusion in a completion suggestion.
169 */
170 protocol.Element createLocalElement(
171 Source source, protocol.ElementKind kind, SimpleIdentifier id,
172 {String parameters,
173 TypeName returnType,
174 bool isAbstract: false,
175 bool isDeprecated: false}) {
176 String name;
177 Location location;
178 if (id != null) {
179 name = id.name;
180 // TODO(danrubel) use lineInfo to determine startLine and startColumn
181 location = new Location(source.fullName, id.offset, id.length, 0, 0);
182 } else {
183 name = '';
184 location = new Location(source.fullName, -1, 0, 1, 0);
185 }
186 int flags = protocol.Element.makeFlags(
187 isAbstract: isAbstract,
188 isDeprecated: isDeprecated,
189 isPrivate: Identifier.isPrivateName(name));
190 return new protocol.Element(kind, name, flags,
191 location: location,
192 parameters: parameters,
193 returnType: nameForType(returnType));
194 }
195
196 /**
197 * Create a new suggestion for the given field.
198 * Return the new suggestion or `null` if it could not be created.
199 */
200 CompletionSuggestion createLocalFieldSuggestion(
201 Source source, FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
202 bool deprecated = isDeprecated(fieldDecl) || isDeprecated(varDecl);
203 TypeName type = fieldDecl.fields.type;
204 return createLocalSuggestion(
205 varDecl.name, deprecated, DART_RELEVANCE_LOCAL_FIELD, type,
206 classDecl: fieldDecl.parent,
207 element: createLocalElement(
208 source, protocol.ElementKind.FIELD, varDecl.name,
209 returnType: type, isDeprecated: deprecated));
210 }
211
212 /**
213 * Create a new suggestion based upon the given information.
214 * Return the new suggestion or `null` if it could not be created.
215 */
216 CompletionSuggestion createLocalSuggestion(SimpleIdentifier id,
217 bool isDeprecated, int defaultRelevance, TypeName returnType,
218 {ClassDeclaration classDecl, protocol.Element element}) {
219 if (id == null) {
220 return null;
221 }
222 String completion = id.name;
223 if (completion == null || completion.length <= 0 || completion == '_') {
224 return null;
225 }
226 CompletionSuggestion suggestion = new CompletionSuggestion(
227 CompletionSuggestionKind.INVOCATION,
228 isDeprecated ? DART_RELEVANCE_LOW : defaultRelevance,
229 completion,
230 completion.length,
231 0,
232 isDeprecated,
233 false,
234 returnType: nameForType(returnType),
235 element: element);
236 if (classDecl != null) {
237 SimpleIdentifier classId = classDecl.name;
238 if (classId != null) {
239 String className = classId.name;
240 if (className != null && className.length > 0) {
241 suggestion.declaringType = className;
242 }
243 }
244 }
245 return suggestion;
246 }
247
248 /**
249 * Return `true` if the @deprecated annotation is present
250 */
251 bool isDeprecated(AnnotatedNode node) {
252 if (node != null) {
253 NodeList<Annotation> metadata = node.metadata;
254 if (metadata != null) {
255 return metadata.any((Annotation a) {
256 return a.name is SimpleIdentifier && a.name.name == 'deprecated';
257 });
258 }
259 }
260 return false;
261 }
262
263 /**
264 * Return the name for the given type.
265 */
266 String nameForType(TypeName type) {
267 if (type == NO_RETURN_TYPE) {
268 return null;
269 }
270 if (type == null) {
271 return DYNAMIC;
272 }
273 Identifier id = type.name;
274 if (id == null) {
275 return DYNAMIC;
276 }
277 String name = id.name;
278 if (name == null || name.length <= 0) {
279 return DYNAMIC;
280 }
281 TypeArgumentList typeArgs = type.typeArguments;
282 if (typeArgs != null) {
283 //TODO (danrubel) include type arguments
284 }
285 return name;
286 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698