# Providing Quick Assists

A quick assist is used by clients to provide a set of possible changes to code
that are based on the structure of the code. Quick assists are intended to help
users safely make local changes to code when those changes do not require any
user interaction. (Modifications that require interaction with users or that
touch multiple files are usually implemented as refactorings.)

For example, if the user has a function whose body consists of a single return
statement in a block, server will provide an assist to convert the function body
from a block to an expression (`=>`).

Assists have a priority associated with them. The priority allows the client to
display the assists that are most likely to be of use closer to the top of the
list when there are multiple assists available.

## Implementation details

When appropriate, the analysis server will send your plugin an `edit.getAssists`
request. The request includes the `file`, `offset` and `length` associated with
the selected region of code.

When an `edit.getAssists` request is received, the method `handleEditGetAssists`
will be invoked. This method is responsible for returning a response that
contains the available assists.

The easiest way to implement this method is by adding the classes `AssistsMixin`
and `DartAssistsMixin` (from `package:analyzer_plugin/plugin/assist_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: `getAssistContributors`.
That method is responsible for returning a list of `AssistContributor`s. It is
the assist contributors that produce the actual assists. (Most plugins will only
need a single assist contributor.)

To write an assist contributor, create a class that implements
`AssistContributor`. The interface defines a single method named
`computeAssists`. The method has two arguments: an `AssistRequest` that
describes the location at which assists were requested and an `AssistCollector`
through which assists are to be added.

If you mix in the class `DartAssistsMixin`, then the request will be an instance
of `DartAssistRequest`, which also has analysis results.

The class `AssistContributorMixin` defines a support method that makes it easier
to implement `computeAssists`.

## Example

Start by creating a class that implements `AssistContributor` and that mixes in
the class `AssistContributorMixin`, then implement the method `computeAssists`.
This method is typically implemented as a sequence of invocations of methods
that check to see whether a given assist is appropriate in the context of the
request 

To learn about the support available for creating the edits, see
[Creating Edits][creatingEdits].

For example, your contributor might look something like the following:

```dart
class MyAssistContributor extends Object
    with AssistContributorMixin
    implements AssistContributor {
  static AssistKind wrapInIf =
      AssistKind('wrapInIf', 100, "Wrap in an 'if' statement");

  DartAssistRequest request;

  AssistCollector collector;

  AnalysisSession get session => request.result.session;

  @override
  Future<void> computeAssists(DartAssistRequest request, AssistCollector collector) async {
    this.request = request;
    this.collector = collector;
    await _wrapInIf();
    await _wrapInWhile();
    // ...
  }

  Future<void> _wrapInIf() async {
    ChangeBuilder builder = ChangeBuilder(session: session);
    await changeBuilder.addDartFileEdit(path,
        (DartFileEditBuilder fileEditBuilder) {
      // TODO Build the edit to wrap the selection in a 'if' statement.
    });
    addAssist(wrapInIf, builder);
  }

  Future<void> _wrapInWhile() async {
    // ...
  }
}
```

Given a contributor like the one above, you can implement your plugin similar to
the following:

```dart
class MyPlugin extends ServerPlugin with AssistsMixin, DartAssistsMixin {
  // ...

  @override
  List<AssistContributor> getAssistContributors(String path) {
    return <AssistContributor>[MyAssistContributor()];
  }
}
```

[creatingEdits]: creating_edits.md
