# 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 =
      new AssistKind('wrapInIf', 100, "Wrap in an 'if' statement");

  DartAssistRequest request;

  AssistCollector collector;

  AnalysisSession get session => request.result.session;

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

  void _wrapInIf() {
    ChangeBuilder builder = new ChangeBuilder(session: session);
    // TODO Build the edit to wrap the selection in a 'if' statement.
    addAssist(wrapInIf, builder);
  }

  void _wrapInWhile() {
    // ...
  }
}
```

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(AnalysisDriver driver) {
    return <AssistContributor>[new MyAssistContributor()];
  }
}
```

[creatingEdits]: creating_edits.md
