Skip to content

Commit 57ece5b

Browse files
bwilkersonCommit Queue
authored and
Commit Queue
committed
Move generation of suggestions for methods and fields
Change-Id: I84b95c465fc11338326f4591aadae9baac6a2779 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/334140 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]>
1 parent 2e7149b commit 57ece5b

File tree

10 files changed

+572
-117
lines changed

10 files changed

+572
-117
lines changed

pkg/analysis_server/lib/src/services/completion/dart/candidate_suggestion.dart

Lines changed: 123 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'package:analysis_server/src/protocol_server.dart'
6+
show CompletionSuggestionKind;
57
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
68
import 'package:analyzer/dart/ast/ast.dart';
79
import 'package:analyzer/dart/ast/token.dart';
@@ -21,6 +23,49 @@ sealed class CandidateSuggestion {
2123
String get completion;
2224
}
2325

26+
/// The information about a candidate suggestion based on a constructor.
27+
final class ConstructorSuggestion extends CandidateSuggestion {
28+
/// The element on which the suggestion is based.
29+
final ConstructorElement element;
30+
31+
/// Initialize a newly created candidate suggestion to suggest the [element].
32+
ConstructorSuggestion(this.element);
33+
34+
@override
35+
String get completion => element.displayName;
36+
}
37+
38+
/// The information about a candidate suggestion based on an executable element,
39+
/// either a method or function.
40+
sealed class ExecutableSuggestion extends CandidateSuggestion {
41+
/// The kind of suggestion to be made, either
42+
/// [CompletionSuggestionKind.IDENTIFIER] or
43+
/// [CompletionSuggestionKind.INVOCATION].
44+
final CompletionSuggestionKind kind;
45+
46+
/// Initialize a newly created suggestion to use the given [kind] of
47+
/// suggestion.
48+
ExecutableSuggestion(this.kind)
49+
: assert(kind == CompletionSuggestionKind.IDENTIFIER ||
50+
kind == CompletionSuggestionKind.INVOCATION);
51+
}
52+
53+
/// The information about a candidate suggestion based on a field.
54+
final class FieldSuggestion extends CandidateSuggestion {
55+
/// The element on which the suggestion is based.
56+
final FieldElement element;
57+
58+
/// The class from which the field is being referenced, or `null` if the class
59+
/// is not being referenced from within a class.
60+
final ClassElement? referencingClass;
61+
62+
/// Initialize a newly created candidate suggestion to suggest the [element].
63+
FieldSuggestion(this.element, this.referencingClass);
64+
65+
@override
66+
String get completion => element.name;
67+
}
68+
2469
/// The information about a candidate suggestion based on a formal parameter.
2570
final class FormalParameterSuggestion extends CandidateSuggestion {
2671
/// The element on which the suggestion is based.
@@ -33,7 +78,8 @@ final class FormalParameterSuggestion extends CandidateSuggestion {
3378
String get completion => element.name;
3479
}
3580

36-
/// The information about a candidate suggestion based on an identifier.
81+
/// The information about a candidate suggestion based on an identifier being
82+
/// guessed for a declaration site.
3783
final class IdentifierSuggestion extends CandidateSuggestion {
3884
/// The identifier to be inserted.
3985
final String identifier;
@@ -118,12 +164,12 @@ final class LabelSuggestion extends CandidateSuggestion {
118164
}
119165

120166
/// The information about a candidate suggestion based on a local function.
121-
final class LocalFunctionSuggestion extends CandidateSuggestion {
167+
final class LocalFunctionSuggestion extends ExecutableSuggestion {
122168
/// The element on which the suggestion is based.
123169
final FunctionElement element;
124170

125171
/// Initialize a newly created candidate suggestion to suggest the [element].
126-
LocalFunctionSuggestion(this.element);
172+
LocalFunctionSuggestion(super.kind, this.element);
127173

128174
@override
129175
String get completion => element.name;
@@ -145,13 +191,50 @@ final class LocalVariableSuggestion extends CandidateSuggestion {
145191
String get completion => element.name;
146192
}
147193

194+
/// The information about a candidate suggestion based on a method.
195+
final class MethodSuggestion extends ExecutableSuggestion {
196+
/// The element on which the suggestion is based.
197+
final MethodElement element;
198+
199+
final ClassElement? referencingClass;
200+
201+
/// Initialize a newly created candidate suggestion to suggest the [element].
202+
MethodSuggestion(super.kind, this.element, this.referencingClass);
203+
204+
@override
205+
String get completion => element.name;
206+
}
207+
208+
/// The information about a candidate suggestion based on a method.
209+
final class PropertyAccessSuggestion extends CandidateSuggestion {
210+
/// The element on which the suggestion is based.
211+
final PropertyAccessorElement element;
212+
213+
final ClassElement? referencingClass;
214+
215+
/// Initialize a newly created candidate suggestion to suggest the [element].
216+
PropertyAccessSuggestion(this.element, this.referencingClass);
217+
218+
@override
219+
String get completion => element.name;
220+
}
221+
148222
extension SuggestionBuilderExtension on SuggestionBuilder {
149223
// TODO(brianwilkerson) Move these to `SuggestionBuilder`, possibly as part
150224
// of splitting it into a legacy builder and an LSP builder.
151225

152226
/// Add a suggestion based on the candidate [suggestion].
153227
void suggestFromCandidate(CandidateSuggestion suggestion) {
154228
switch (suggestion) {
229+
case ConstructorSuggestion():
230+
suggestConstructor(suggestion.element);
231+
case FieldSuggestion():
232+
suggestField(suggestion.element,
233+
inheritanceDistance: _inheritanceDistance(
234+
suggestion.referencingClass,
235+
suggestion.element.enclosingElement));
236+
case FormalParameterSuggestion():
237+
suggestParameter(suggestion.element);
155238
case IdentifierSuggestion():
156239
suggestName(suggestion.identifier);
157240
case KeywordSuggestion():
@@ -165,8 +248,31 @@ extension SuggestionBuilderExtension on SuggestionBuilder {
165248
// TODO(brianwilkerson) Enhance `suggestLocalVariable` to allow the
166249
// distance to be passed in.
167250
suggestLocalVariable(suggestion.element);
168-
case FormalParameterSuggestion():
169-
suggestParameter(suggestion.element);
251+
case MethodSuggestion():
252+
// TODO(brianwilkerson) Correctly set the kind of suggestion in cases
253+
// where `isFunctionalArgument` would return `true` so we can stop
254+
// using the `request.target`.
255+
var kind = request.target.isFunctionalArgument()
256+
? CompletionSuggestionKind.IDENTIFIER
257+
: suggestion.kind;
258+
suggestMethod(
259+
suggestion.element,
260+
kind: kind,
261+
inheritanceDistance: _inheritanceDistance(
262+
suggestion.referencingClass, suggestion.element.enclosingElement),
263+
);
264+
case PropertyAccessSuggestion():
265+
var inheritanceDistance = 0.0;
266+
var referencingClass = suggestion.referencingClass;
267+
var declaringClass = suggestion.element.enclosingElement;
268+
if (referencingClass != null && declaringClass is InterfaceElement) {
269+
inheritanceDistance = request.featureComputer
270+
.inheritanceDistanceFeature(referencingClass, declaringClass);
271+
}
272+
suggestAccessor(
273+
suggestion.element,
274+
inheritanceDistance: inheritanceDistance,
275+
);
170276
}
171277
}
172278

@@ -176,4 +282,16 @@ extension SuggestionBuilderExtension on SuggestionBuilder {
176282
suggestFromCandidate(suggestion);
177283
}
178284
}
285+
286+
/// Returns the inheritance distance from the [referencingClass] to the
287+
/// [declaringClass].
288+
double _inheritanceDistance(
289+
ClassElement? referencingClass, Element? declaringClass) {
290+
var distance = 0.0;
291+
if (referencingClass != null && declaringClass is InterfaceElement) {
292+
distance = request.featureComputer
293+
.inheritanceDistanceFeature(referencingClass, declaringClass);
294+
}
295+
return distance;
296+
}
179297
}

0 commit comments

Comments
 (0)