| # Code completion |
| |
| LSP: [textDocument/completion][] request |
| Legacy: `completion.getSuggestions2` request |
| |
| Code completion supports two significant functions. The first is to make it |
| faster and easier for the user to enter code by predicting the code they might |
| be trying to type and suggesting the possibilities. The second is to help the |
| user understand the API of the objects referenced in their code. |
| |
| The design of the feature is largely dictated by the need to support both of |
| these functions as well as by the protocol. |
| |
| The quality of the completion suggestions is dependent on two factors: |
| |
| - The choice of identifiers being suggested |
| - The order in which the suggestions are presented |
| |
| ## The process |
| |
| TBD (how the protocol works) |
| |
| ## Choosing what to suggest |
| |
| This section describes the choices we make when deciding what to suggest. |
| |
| ### What we suggest |
| |
| We generally suggest every identifier that is in scope and every keyword that is |
| valid at the point where completion was requested. |
| |
| As a result, we often suggest identifiers that are not particularly likely to be |
| the one the user is trying to type. Several ideas have been proposed for ways to |
| reduce the number of suggestions. The most common proposal is to only suggest |
| identifiers that are valid initial tokens for the static type of the expression |
| being completed. That's an attractive idea, but we don't have an efficient way |
| to determine the set of types that could be returned by an expression starting |
| with a given token, so the proposal isn't practical. |
| |
| If time allows, we also suggest identifiers that are not in scope but could be |
| added to the scope by adding an import. |
| |
| ### What we don't suggest |
| |
| There are a couple of things that we don't suggest. Each is discussed in a |
| section below. |
| |
| #### Operators |
| |
| We generally don't suggest operators for the following reasons: |
| |
| - Most operators are a single character, so it doesn't really save time to find |
| and insert them via completion. |
| |
| - There's no automatic trigger for completions where an operator would be valid, |
| and we suspect that most users don't think to request completion when they want |
| an operator (in part because doing so wouldn't buy them much, and in part |
| because users are probably trained to expect completion to be triggered |
| automatically). |
| |
| Not suggesting operators does impact the ability of users to find operators |
| defined in the API, but most of the operators should only be included in an API |
| when it's already obvious that they should exist. |
| |
| #### Multi-token completions |
| |
| There are a couple of exceptions, but we generally don't suggest multi-token |
| completions. We prefer to leave that to AI. |
| |
| If we're going to suggest a name that is imported using a prefix, then we will |
| include the prefix and period in the completion. |
| |
| If we're going to suggest a static member, then we will include the name of the |
| class and the period in the completion. |
| |
| ### Filtering |
| |
| As the completion suggestions are computed, they are filtered based on the |
| prefix of the identifier being completed that has already been typed. The |
| filtering is done in the analysis server in order to reduce the number of |
| suggestions sent to the client, and it is done on the client when the client has |
| a complete set of suggestions. |
| |
| ### Phases |
| |
| The process of generating completion suggestions is divided into two phases. The |
| first phase computes the identifiers that are in scope and the keywords. The |
| second phase computes identifiers that are not in scope but could be added to |
| the scope by adding an import. |
| |
| The primary reason for having two phases is to allow the completion engine to |
| more easily return earlier if it's necessary to do so in order to meet the |
| response time goal. |
| |
| ## Ordering the suggestions |
| |
| The goal of ordering the suggestions is to move the suggestion for the thing the |
| user is trying to type to the top of the list. Of course, there's no way to know |
| what the user is trying to type, but we can use some heuristics to improve the |
| quality of the ordering. |
| |
| ### An important limitation |
| |
| There is one significant limitation that we face: clients often re-order the |
| suggestions returned by the server before displaying them to the user. That |
| re-ordering is often only partial, so we still make an effort to optimize the |
| order of the suggestions, but there's a limit to the amount of value we can |
| bring in some cases. |
| |
| ### The relevance score |
| |
| The order of suggestions is based on a _relevance_ score, which is computed for |
| each suggestion. The relevance score is computed as a weighted average of |
| several _feature_ scores. The features are intended to capture the most |
| important factors that influence the user's choice of suggestion. The use of |
| these features is designed to make the ordering more comprehensible (to us) and |
| maintainable by making it more deterministic. |
| |
| The set of features used for a given suggestion is dependent on the kind of |
| suggestion. For example, one of the features is only used for local variables. |
| |
| The feature scores are combined by the `[RelevanceComputer][]`. |
| |
| ### The features |
| |
| While the features themselves are heuristic in nature, the set of features that |
| are used isn't. The features are evaluated independently to determine whether |
| their inclusion improves the ranking of the suggestions. This evaluation is done |
| during the development of a new feature, not in the deployed server. The |
| evaluation is done using the [Completion Metrics tool][]. |
| |
| The feature scores are computed by the `[FeatureComputer][]`. |
| |
| [textDocument/completion]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_completion |
| [FeatureComputer]: https://github.com/dart-lang/sdk/blob/main/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart#L131 |
| [RelevanceComputer]: https://github.com/dart-lang/sdk/blob/main/pkg/analysis_server/lib/src/services/completion/dart/relevance_computer.dart#L18 |
| [Completion Metrics tool]: https://github.com/dart-lang/sdk/blob/main/pkg/analysis_server/tool/code_completion/completion_metrics.dart |