| # 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()]; |
| } |
| } |
| ``` |