blob: 18b1698549d36063cfe8c01bbf03632dd50be32f [file] [log] [blame] [view]
# Providing Code Completions
A code completion is used by clients to provide a set of possible completions to
partially entered code. Completions are intended to address two use cases: to
help users enter code with less effort and to help users discover the behavior
of an object.
For example, if the user has typed `o.toSt` and then requested completions, one
suggestion might be `toString`.
That said, the completion suggestions that your plugin returns should include
all of the options that would be valid if the partial identifier did not exist.
The reason is that most clients are implemented such that they send a single
request for completions when the dialog with the user begins and cannot send any
subsequent requests. If the user presses the backspace key during the dialog the
client needs to have already received the expanded list of options that now
match the prefix (or all options if the prefix has completely been deleted).
Clients will filter the list of suggestions displayed as appropriate.
Hence, in the example above, plugins should return suggestions as if the user
had requested completions after typing `o.`;
## Implementation details
When appropriate, the analysis server will send your plugin a
`completion.getSuggestions` request. The request includes the `file` and
`offset` at which completions are being requested.
When a `completion.getSuggestions` request is received, the method
`handleCompletionGetSuggestions` will be invoked. This method is responsible for
returning a response that contains the available suggestions.
The easiest way to implement this method is by adding the classes
`CompletionMixin` and `DartCompletionMixin` (from
`package:analyzer_plugin/plugin/completion_mixin.dart`) to the list of mixins
for your subclass of `ServerPlugin`. This will leave you with one abstract
method that you need to implement: `getCompletionContributors`. That method is
responsible for returning a list of `CompletionContributor`s. It is the
completion contributors that produce the actual completion suggestions. (Most
plugins will only need a single completion contributor.)
To write a completion contributor, create a class that implements
`CompletionContributor`. The interface defines a single method named
`computeSuggestions`. The method has two arguments: a `CompletionRequest` that
describes the where completions are being requested and a `CompletionCollector`
through which suggestions are to be added.
If you mix in the class `DartCompletionMixin`, then the request will be an
instance of `DartCompletionRequest`, which also has analysis results.
## Example
Start by creating a class that implements `CompletionContributor`, then
implement the method `computeSuggestions`. Your contributor should invoke the
method `checkAborted`, defined on the `CompletionRequest` object, before
starting any slow work. This allows the computation of completion suggestions
to be preempted if the client no longer needs the results.
For example, your contributor might look something like the following:
```dart
class MyCompletionContributor implements CompletionContributor {
@override
Future<void> computeSuggestions(DartCompletionRequest request,
CompletionCollector collector) async {
// ...
}
}
```
Given a contributor like the one above, you can implement your plugin similar to
the following:
```dart
class MyPlugin extends ServerPlugin with CompletionMixin, DartCompletionMixin {
// ...
@override
List<CompletionContributor> getCompletionContributors(
AnalysisDriverGeneric driver) {
return <CompletionContributor>[new MyCompletionContributor()];
}
}
```