# Providing Quick Fixes

A quick fix is used by clients to provide a set of possible changes to code that
are based on diagnostics reported against the code. Quick fixes are intended to
help users resolve the issue being reported.

If your plugin generates any diagnostics then you should consider providing
support for automatically fixing those diagnostics. There is often more than one
potential way of fixing a given problem, so it is possible for your plugin to
provide multiple fixes for a single problem.

For example, if an undefined identifier is used in the code, you might return
a fix to create an appropriate definition for the identifier. If there is a
similar identifier that is already defined, you might also return a second fix
to replace the undefined identifier with the defined identifier.

The latter example illustrates that fixes can be conditionally returned. You
will produce a better UX if only those fixes that actually make sense in the
given context are returned. If a lot of work is required to determine which
fixes make sense, it is possible to improve performance by generating different
diagnostics for the same issue, depending on the context in which the issue
occurs.

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

## Implementation details

When appropriate, the analysis server will send your plugin an `edit.getFixes`
request. The request includes the `file` and `offset` associated with the
diagnostics for which fixes should be generated. Fixes are typically produced
for all of the diagnostics on a given line of code. Your plugin should only
return fixes associated with the errors that it produced earlier.

When an `edit.getFixes` request is received, the method `handleEditGetFixes`
will be invoked. This method is responsible for returning a response that
contains the available fixes.

The easiest way to implement this method is by adding the classes `FixesMixin`
and `DartFixesMixin` (from `package:analyzer_plugin/plugin/fix_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: `getFixContributors`. That
method is responsible for returning a list of `FixContributor`s. It is the fix
contributors that produce the actual fixes. (Most plugins will only need a
single fix contributor.)

To write a fix contributor, create a class that implements `FixContributor`. The
interface defines a single method named `computeFixes`. The method has two
arguments: a `FixesRequest` that describes the errors that should be fixed and a
`FixCollector` through which fixes are to be added.

If you mix in the class `DartFixesMixin`, then the list of errors available
through the request object will only include the errors for which fixes should
be returned and the request will be an instance of `DartFixesRequest`, which
also has analysis results.

The class `FixContributorMixin` defines a simple implementation of this method
that captures the two arguments in fields, iterates through the errors, and
invokes a method named `computeFixesForError` for each of the errors for which
fixes are to be computed.

## Example

Start by creating a class that implements `FixContributor` and that mixes in the
class `FixContributorMixin`, then implement the method `computeFixesForError`.
This method is typically implemented by a series of `if` statements that test
the error code and invoke individual methods that compute the actual fixes to be
proposed. (In addition to keeping the method `computeFixesForError` shorter,
this also allows some fixes to be used for multiple error codes.)

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 MyFixContributor extends Object
    with FixContributorMixin
    implements FixContributor {
  static FixKind defineComponent =
      FixKind('defineComponent', 100, "Define a component named {0}");

  AnalysisSession get session => request.result.session;

  @override
  Future<void> computeFixesForError(AnalysisError error) async {
    ErrorCode code = error.errorCode;
    if (code == MyErrorCode.undefinedComponent) {
      await _defineComponent(error);
      await _useExistingComponent(error);
    }
  }

  Future<void> _defineComponent(AnalysisError error) async {
    // TODO Get the name from the source code.
    String componentName = null;
    ChangeBuilder builder = ChangeBuilder(session: session);
    await changeBuilder.addDartFileEdit(path,
        (DartFileEditBuilder fileEditBuilder) {
      // TODO Build the edit to insert the definition of the component.
    });
    addFix(error, defineComponent, builder, args: [componentName]);
  }

  Future<void> _useExistingComponent(AnalysisError error) async {
    // ...
  }
}
```

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

```dart
class MyPlugin extends ServerPlugin with FixesMixin, DartFixesMixin {
  // ...

  @override
  List<FixContributor> getFixContributors(String path) {
    return <FixContributor>[MyFixContributor()];
  }
}
```

[creatingEdits]: creating_edits.md
