Skip to content

Migrating to 0.7.x

Nate Bosch edited this page Jul 25, 2017 · 5 revisions

source_gen 0.7.0 introduced some breaking changes to how Generators are run, use this guide to upgrade your usage.

When extending GeneratorForAnnotation

The method signature has changed, and behavior is otherwise not impacted. Your GeneratorForAnnotation will behave as before - generateForAnnotation will continue to be called once per annotated element in the source library.

Changes to make

  • Change the annotation argument to generateForAnnotation from an instance of the annotation to an instance of ConstantReader. Pull fields from the reader rather than

For example:

class SomeGenerator extends GeneratorForAnnotation<SomeAnnotation> {
  @override
  Future<String> generateForAnnotation(
      Element element, SomeAnnotation annotation, BuildStep buildStep) {
    //...
    var someField = annotation.someField;
    //...
  }
}
class SomeGenerator extends GeneratorForAnnotation<SomeAnnotation> {
  @override
  Future<String> generateForAnnotation(
      Element element, SomeAnnotation annotation, BuildStep buildStep) {
    //...
    var someField = annotation.read('someField').stringValue;
    //...
  }
}

Behavior Differences

These will most likely only impact tests.

  • The output will look a little different - blocks will no longer be commented with which which element causes a snippet of code to get generated
  • Exceptions thrown will cause no code to get generated at all rather than insert comments in the generated output with the error message
  • The generate method, if called manually in a test, should only be called for an entire library at a time.

When extending Generator

The generate method is now called once per library rather than once per element within a library. Iterating over elements, if required, is now the responsibility of the generator.

Changes to make

  • Change the signature to take a LibraryReader as the first argument.
  • If required to visit every element within a library iterate over them with LibraryReader.allElements.

For example

class SomeGenerator extends Generator {
  @override
  Future<String> generate(Element element, BuildStep buildStep) {
    if (element is LibraryElement) {
      // Do library stuff
      return result;
    } else {
      // Do non-library stuff
      return result;
    }
  }
}
class SomeGenerator extends Generator {
  @override
  Future<String> generate(LibraryReader library, BuildStep buildStep) {
    var generated = new StringBuffer();
    var libraryElement = library.element
    // Do library stuff
    generated.writeln(result);
    for(var element in library.allElements.skip(1)) {
      // Do non-library stuff
      generated.writeln(result);
    }
    return '$generated';
  }
}

Behavior Differences

  • The output will look a little different - blocks will no longer be commented with which which element causes a snippet of code to get generated unless you add the comment manually
  • Exceptions thrown will cause no code to get generated at all rather than insert comments in the generated output with the error message - if these comments are needed (usually for backwards compatibility in tests) catch exceptions manually to write these comments and be sure to log.severe so that the build can be marked as a failure overall
  • The generate method, if called manually in a test, should only be called for an entire library at a time.

When using as a Builder

Depending on whether the isStandalone argument was passed as true, construct either a PartBuilder (no isStandalone argument, or passing false) or a LibraryBuilder ('isStandalone: true`).

Clone this wiki locally