source_gen 0.9.5

  • Readme
  • Changelog
  • Installing
  • 93

Build Status Pub Package Version Join the chat on Gitter

Overview #

source_gen provides utilities for automated source code generation for Dart:

  • A framework for writing Builders that consume and produce Dart code.
  • A convention for human and tool generated Dart code to coexist with clean separation, and for multiple code generators to integrate in the same project.

It's main purpose is to expose a developer-friendly API on top of lower-level packages like the analyzer or build. You don't have to use source_gen in order to generate source code; we also expose a set of library APIs that might be useful in your generators.

Quick Start Guide for writing a Generator #

Add a dependency on source_gen in your pubspec.


If you're only using source_gen in your own project to generate code and you won't publish your Generator for others to use, it can be a dev_dependency:


Once you have source_gen setup, you should reference the examples below.

Writing a generator to output Dart source code #

Extend the Generator or GeneratorForAnnotation class and source_gen will call your generator for a Dart library or for each element within a library tagged with the annotation you are interested in.

Configuring and Running generators #

source_gen is based on the build package and exposes options for using your Generator in a Builder. Choose a Builder based on where you want the generated code to end up:

  • If you want to write to .g.dart files which are referenced as a part in the original source file, use SharedPartBuilder. This is the convention for generated code in part files, and this file may also contain code from Generators provided by other packages.
  • If you want to write to .some_name.dart files which are referenced as a part in the original source file, use PartBuilder. You should choose an extension unique to your package. Multiple Generators may output to this file, but they will all come from your package and you will set up the entire list when constructing the builder.
  • If you want to write standalone Dart library which can be imported use LibraryBuilder. Only a single Generator may be used as a LibraryBuilder.

In order to get the Builder used with build_runner it must be configured in a build.yaml file. See build_config for more details. Whenever you are publishing a package that includes a build.yaml file you should include a dependency on build_config in your pubspec.

When using SharedPartBuilder it should always be configured to build_to: cache (hidden files) and apply the combining_builder from this package. The combining builder reads in all the pieces written by different shared part builders and writes them to the final .g.dart output in the user's source directory. You should never use the .g.dart extension for any other Builder.

    import: "package:this_package/builder.dart"
    builder_factories: ["someCoolBuilder"]
    # The `partId` argument to `SharedPartBuilder` is "some_cool_builder"
    build_extensions: {".dart": [".some_cool_builder.g.part"]}
    auto_apply: dependents
    build_to: cache
    # To copy the `.g.part` content into `.g.dart` in the source tree
    applies_builders: ["source_gen|combining_builder"]

Configuring combining_builder ignore_for_file #

Sometimes generated code does not support all of the lints specified in the target package. When using a Builder based on package:source_gen which applies combining_builder, set the ignore_for_file option to a list of lints you wish to be ignored in all generated libraries.

Example build.yaml configuration:

          - lint_alpha
          - lint_beta

If you provide a builder that uses SharedPartBuilder and combining_builder, you should document this feature for your users.


What is the difference between source_gen and build? #

Build is a platform-agnostic framework for Dart asset or code generation that is pluggable into build systems including bazel, and standalone tools like build_runner. You could also build your own.

Meanwhile, source_gen provides an API and tooling that is easily usable on top of build to make common tasks easier and more developer friendly. For example the PartBuilder class wraps one or more Generator instances to make a Builder which creates part of files, while the LibraryBuilder class wraps a single Generator to make a Builder which creates Dart library files.

0.9.5 #

  • Add support for an ignore_for_file option to combining_builder.

  • Expand documentation for GeneratorForAnnotation to make it clear that it only targets elements at the top level of a library.

0.9.4+7 #

  • Fix an exception during error reporting when the Element reported is in a summary file rather than a source file.

0.9.4+6 #

  • Allow package:analyzer version 0.39.x.

0.9.4+5 #

  • Fix a bug for finding the element for a function with recent versions of analyzer.

0.9.4+4 #

  • Allow pkg:analyzer version 0.38.x.

0.9.4+3 #

  • Allow pkg:analyzer version 0.37.x.

0.9.4+2 #

  • Allow pkg:analyzer version 0.36.x.

0.9.4+1 #

  • Support the latest pkg:analyzer.

0.9.4 #

  • Use ParsedLibraryResult to find source spans for unresolvable annotations.

0.9.3 #

  • Rename LibraryReader.classElements to LibraryReader.classes to better reflect the behavior. Deprecate the old name.
  • Add LibraryReader.enums.

0.9.2 #

  • Avoid using the AST analyzer model from LibraryReader.
  • Don't create part files with no corresponding library.
  • Update analyzer constraint to allow 0.34.x.

0.9.1+3 #

  • Support the latest pkg:analyzer.

0.9.1+2 #

  • Correctly handle properties in spanForElement.

0.9.1+1 #

  • Allow package:build version 1.0.0.

0.9.1 #

  • The result of ConstantReader.revive() now returns a Revivable that assumes access to a private class, constructor, or function instead of null where possible. This allows generators that use part files to still use this functionality and allows generators that use separate libraries to emit more actionable error messages (i.e. "cannot use private class _X").

  • Revivable.isPrivate now returns true when the underlying class was public but the constructor was private, or the Revivable was pointing to a top-level or static private field or method. Previously it was only true when referencing a private class.

0.9.0+1 #

  • Fix LibraryReader.classElements to return classes from parts, if they exist, as well as from the defining library file.

0.9.0 #

  • Introduce SharedPartBuilder for creating part files that can be merged with a new CombiningBuilder. Note that CombiningBuilder only outputs .g.dart files.
  • Breaking PartBuilder now requires a generatedExtensions argument. The value should not be .g.dart. To produce .g.dart files please use the SharedPartBuilder.

0.8.3+1 #

  • Allow using non-dev Dart 2 SDK.

0.8.3 #

  • GeneratorForAnnotation
    • generateForAnnotatedElement now allow multiple return values when implementations return an Iterable or Stream.
    • Values from generateForAnnotatedElement have whitespace trimmed. null and empty values are ignored.
    • Duplicate values are collapsed into a single values. This allows emitting shared, top-level members without naming collisions.

0.8.2 #

  • Simplification to the output of generator names in header sections.

  • Update handling of whitespace in generator outputs.

    • If the output from a generator has wrapping whitespace, it is trimmed.
    • If the output from a generator is empty or whitespace-only, it is ignored.
    • These changes will likely have no effect on output, unless you customize the code formatter.

0.8.1+3 #

  • More redundant new lines elimination.

0.8.1+2 #

  • Eliminate redundant new lines in the core builder. These were almost removed by running the default formatter. Now the unformatted code more closely matches the default output.

0.8.1+1 #

  • Support package:analyzer 0.32.0.

0.8.1 #

  • Cleanup logging output that duplicates headers provided by package:build_runner.

  • InvalidGenerationSourceError added an optional element parameter to support more helpful error messages.

0.8.0 #

  • BREAKING removed the deprecated requireLibraryDirective parameter in PartBuilder.

  • Revivable no longer throws a type error when attempting to revive a reference to a top-level function or static-class method. Now is returns a reference to that function or method, as expected.

0.7.6 #

  • TypeChecker now throws an UnresolvedAnnotationException with a more detailed exception body (and properties useful for further debugging) instead of Could not resolve @null.

0.7.5+1 #

  • LibraryBuilder and PartBuilder now have a more readable toString(), which is useful when emitting a warning or error in a build system. For example you may see Generating .g.dart: MyBuilder instead of Instance of LibraryBuilder in your build logs.

0.7.5 #

  • The PartBuilder constructor parameter requireLibraryDirective now defaults to false. It will be removed in 0.8.0.

  • Require at least Dart 2.0.0-dev.19.0.

0.7.4+3 #

  • Support the latest analyzer package.

0.7.4+2 #

  • BUG FIX: ConstantReader.revive() now properly returns no URL fragment when the constant expression is resolved from a top-level or static-field. The documentation had said otherwise, and it was impossible to tell the difference between a constructor and a field. Now, fields are always in the form of accessor = {clazz}.{field} or {topLevelField}.

  • Fix file URIs on windows.

0.7.4+1 #

  • Removed a log.finest with the output source of each generator. This allows a verbose option (-v) for tools like bazel or build_runner to be much more readable and debuggable. Files are emitted to disk for inspection in any case.

0.7.4 #

  • Added typeNameOf, which is a safe way to get the name of a DartType, even when the type is a FunctionType, which has a null name in newer versions of the Dart analyzer.

  • Added LibraryReader.pathToUrl(Uri|String), which computes the import or export path necessary to reach the provided URL from the current library. Also added pathToAsset and pathToElement as convenience functions.

  • Expanded package:build support to allow version 0.12.0.

0.7.3 #

  • Allow null and empty outputs form GeneratorForAnnotation.

0.7.2+1 #

  • Allow package:build version 0.11.0

0.7.2 #

  • Support an optional header argument to PartBuilder and LibraryBuilder.

0.7.1 #

Generator{ForAnnotation} #

  • Return type of generate{ForAnnotatedElement} is now FutureOr<String>.

LibraryReader #

  • Added annotatedElements to return all elements annotated with something.
  • Added classElements getter for returning all class-es in a library.

TypeChecker #

  • Added hasAnnotationOf and hasAnnotationOfExact.

ConstantReader #

  • Added isAny (for consistency, but deprecated) and isLiteral.
  • Added literalValue as an alias for the now deprecated anyValue.
  • Allow literalValue to return null if the value is actually null.
  • Fixed a bug where a Symbol would return as a String for anyValue.
  • Fixed a bug where a List and Map were not considered literals.

0.7.0 #

  • Breaking changes: See the wiki for help upgrading.

    • Generator.generate now operates on a LibraryReader rather than being called for every Element within a library. Generators can iterate over elements using LibraryReader.allElements. GeneratorForAnnotation will continue to call generateForAnnotatedElement repeatedly for each element.
    • GeneratorForAnnotation passes in a ConstantReader for the annotation instance rather than re-creating it using mirrors.
    • GeneratorBuilder is replaced with PartBuilder and LibraryBuilder depending on whether the output is meant to be included in a part file.
    • Removed JsonSerializable and related classes. These are moved to package:json_serializable.
    • Removed lib/builder.dart. Import through source_gen.dart instead.
    • Removed OutputFormatter typedef.
  • Add LibraryReader.allElements - a utility to iterate across all Element instances contained in Dart library.

  • Add LibraryReader.element to get back to the LibraryElement instance.

  • Add ConstantReader.objectValue to get back to the DartObject instance.

  • Add ConstantReader.peek to read a value that returns null if not found:

// Tries to read the field "token" first, then "_token".
findTokenField(DartObject o) {
  final reader = new ConstantReader(o);
  final token = o.peek('token') ??'_token');
  • Add throwOnUnresolved optional parameter to TypeChecker.annotationsOf, TypeChecker.annotationsOfExact, TypeChecker.firstAnnotationOf, and TypeChecker.firstAnnotationOfExact. Setting this to false will enable you to check for matching annotations with incomplete type information (at your own risk).
  • Builder logs now log the primary inputs AssetId instead of the library, which is more useful for tracking down the actual files.

0.6.1+1 #

  • Tighten constraint on source_span.

0.6.1 #

  • Added spanForElement; returns a SourceSpan for an analyzer Element.
  • Logs a warning to the console when a GeneratorBuilder outputs a part file for a given input, but that input does not define part 'name.g.dart';.

0.6.0 #

  • Breaking change: TypeChecker#annotationsOf|firstAnnotationOf now returns annotations that are assignable to the TypeChecker's type. As a result we've added #annotationsOfExact|firstAnnotationOfExact which has the old behavior for precise checks.
  • TypeChecker#annotations...-methods now throw a StateError if one or more annotations on an element are not resolvable. This is usually a sign of a misspelling, missing import, or missing dependency.
  • Added TypeChecker.any, which delegates to multiple other TypeChecker implementations when making a type check.

0.5.10+1 #

  • Update minimum analyzer package to 0.29.10.

0.5.10 #

  • Bug fixes:
    • Do not fail when "library" is omitted but nothing would be output.
    • Do not fail on extensions that don't end in ".dart" (valid use case).

0.5.9 #

  • Update the minimum Dart SDK to 1.22.1.

  • Deprecated builder.dart: import source_gen.dart instead.

  • Added TypeChecker, a high-level API for performing static type checks:

    import 'package:analyzer/dart/element/type.dart';
    import 'package:source_gen/source_gen.dart';
    void checkType(DartType dartType) {
      // Checks compared to runtime type `SomeClass`.
      print(const TypeChecker.forRuntime(SomeClass).isExactlyType(dartType));
      // Checks compared to a known Url/Symbol:
      const TypeChecker.forUrl('package:foo/foo.dart#SomeClass');
      // Checks compared to another resolved `DartType`:
      const TypeChecker.forStatic(anotherDartType);
  • Failing to add a library directive to a library that is being used as a generator target that generates partial files (part of) is now an explicit error that gives a hint on how to name and fix your library:

    > Could not find library identifier so a "part of" cannot be built.
    > Consider adding the following to your source file:
    > "library;"

    In Dart SDK >=1.25.0 this can be relaxed as part of can refer to a path. To opt-in, GeneratorBuilder now has a new flag, requireLibraryDirective. Set it to false, and also set your sdk constraint appropriately:

      sdk: '>=1.25.0 <2.0.0'
  • Added LibraryReader, a utility class for LibraryElement that exposes high-level APIs, including findType, which traverses export directives for publicly exported types. For example, to find Generator from package:source_gen/source_gen.dart:

    void example(LibraryElement pkgSourceGen) {
      var library = new LibraryReader(pkgSourceGen);
      // Instead of pkgSourceGen.getType('Generator'), which is null.
  • Added ConstantReader, a high-level API for reading from constant (static) values from Dart source code (usually represented by DartObject from the analyzer package):

    abstract class ConstantReader {
      factory ConstantReader(DartObject object) => ...
      // Other methods and properties also exist.
      /// Reads[ field] from the constant as another constant value.
      ConstantReader read(String field);
      /// Reads [field] from the constant as a boolean.
      /// If the resulting value is `null`, uses [defaultTo] if defined.
      bool readBool(String field, {bool defaultTo()});
      /// Reads [field] from the constant as an int.
      /// If the resulting value is `null`, uses [defaultTo] if defined.
      int readInt(String field, {int defaultTo()});
      /// Reads [field] from the constant as a string.
      /// If the resulting value is `null`, uses [defaultTo] if defined.
      String readString(String field, {String defaultTo()});

0.5.8 #

  • Add formatOutput optional parameter to the GeneratorBuilder constructor. This is a lambda of the form String formatOutput(String originalCode) which allows you do do custom formatting.

0.5.7 #

  • Support for package:analyzer 0.30.0

0.5.6 #

  • Support for package:build 0.9.0

0.5.5 #

  • Support package:build 0.8.x
  • Less verbose errors when analyzer fails to resolve the input.

0.5.4+3 #

  • Support the latest release of pkg/dart_style.

0.5.4+2 #

  • Use the new log field instead of the deprecated buildStep.logger

0.5.4+1 #

  • Give more information when dartfmt fails.

0.5.4 #

  • Update to latest build, build_runner, and build_test releases.

0.5.3+2 #

  • BugFix: Always release the Resolver instance, even when generation does not run

0.5.3+1 #

  • Don't throw when running against a non-library asset and getting no LibraryElement

0.5.3 #

  • Add matchTypes method. As with anything imported from /src/ this is use-at-your-own-risk since it is not guaranteed to be stable
  • Internal cleanup
    • Drop some unused utility methods
    • Move cli_util to dev_dependencies
    • Avoid some deprecated analyzer apis
    • Syntax tweaks
    • Drop results.dart which had no usages

0.5.2 #

  • Use library URIs (not names) to look up annotations in the mirror system.
  • Loosen version constraint to allow package:build version 0.6
  • Fix a bug against the latest SDK checking whether List implements Iterable

0.5.1+7 #

  • Generate valid strong-mode code for typed lists.

0.5.1+6 #

  • Support the latest version of pkg/build.

0.5.1+5 #

  • Remove "experimental" comment in

0.5.1+4 #

  • Support package:analyzer 0.29.0

0.5.1+3 #

  • Upgrade to be compatible with the breaking changes in analyzer 0.28.0

0.5.1+2 #

  • Avoid calling computeNode() while instantiating annotation values

0.5.1+1 #

  • Support the latest version of build package.

0.5.1 #

  • Added GeneratorBuilder option isStandalone to generate files that aren't part of source file.

0.5.0+3 #

  • Fixed multi-line error output.

0.5.0+2 #

  • Remove an outdated work-around.

  • Make strong-mode clean.

0.5.0+1 #

  • Support the latest version of pkg/build.

0.5.0 #

  • Breaking: Switch to the build package for running Generators. This means that the top level build and generate functions are no longer available, and have been replaced by the top level build, watch, and serve functions from the build package, and the GeneratorBuilder class. See tool/build.dart, tool/watch.dart, and tool/phases.dart for usage.

    • Note that the build package is experimental, and likely to change.
  • Breaking: The build package provides an abstraction for reading/writing files via the BuildStep class, and that is now also provided to Generator#generate and GeneratorForAnnotation#generateForAnnotatedElement as a second argument.

  • Timestamps are no longer included in generated code.

  • There is no longer a need to specify the files related to an individual generator via AssociatedFileSet. Simply use the BuildStep instance to read and write files and the build package will track any files you read in and run incremental rebuilds as necessary.

0.4.8 #

  • Added support for Symbol and Type in annotations.

  • Improved error output when unable to create an instance from an annotation.

0.4.7+2 #

  • Upgrade to analyzer '^0.27.1' and removed a work-around for a fixed analyzer issue.

0.4.7+1 #

  • Upgrade to analyzer '^0.27.0'.

0.4.7 #

  • JsonSerializableGenerator now supports classes with read-only properties.

0.4.6 #

  • JsonSerializable: Added JsonKey annotation.

  • Improved output of generation errors and stack traces.

  • Require analyzer '^0.26.2'.

0.4.5+1 #

  • Handle null values for List properties.

0.4.5 #

  • JsonSerializable: add support for List values.

0.4.4+1 #

  • Updated to highlight the build_system package and de-emphasize Dart Editor.

0.4.4 #

  • Added omitGenerateTimestamp and followLinks named args to build.

  • Added followLinks to generate.

0.4.3+1 #

  • Update tests to use a more reliable method to find the current package root.

0.4.3 #

  • Require Dart 1.12.

  • Add implicit support for .packages. If the file exists, it is used. If not, we fall back to using the packages directory.

  • Support the latest releases of analyzer and dart_style packages.

0.4.2 #

  • Use fromJson if it's defined in a child field.

0.4.1 #

  • Match annotations defined in parts. Thanks, Greg!

0.4.0+1 #

  • Support the latest release of analyzer and args.

0.4.0 #

  • Analysis no longer parses function bodies. This greatly speeds up generation, but it could break any usage that needs function bodies.

0.3.0+2 #

  • Fixed

0.3.0+1 #

  • Updates for move to dart-lang org on GitHub.

0.3.0 #

  • BREAKING Returning a descriptive value from generate.

  • BREAKING Fixed incorrectly named argument omitGenerateTimestamp.

  • JsonSerializable: Handle dynamic and var as field types.

0.2.4 #

  • Added associatedFileSet to Generator. Allows a generator to specify that changes to any file in a directory next to a Dart source file can initiate a generation run.

0.2.3 #

  • Use async *. Requires SDK >= 1.9.0-dev.10

  • Protect against crash during code format.

0.2.2 #

  • Added omitGenerateTimestamp (incorrectly spelled) named argument to generate method.

  • Generator.generate is now called with the LibraryElement, too.

0.2.1 #

  • Fixed critical bug affecting annotation matching. #35

  • Started using published dart_style package.

0.2.0+2 #

  • Tweaks to JsonGenerator to address #31 and #32

0.2.0+1 #

  • Updated with new examples.
  • Fixed sub-bullet indenting in

0.2.0 #

  • BREAKING Moved and renamed JSON serialization classes.
  • Added a JsonLiteral generator.
  • Improved handling and reporting of Generator errors.
  • JsonGenerator
    • Learned how to use constructor arguments.
    • Learned how to properly handle DateTime.

0.1.1 #

  • Support for parametrized annotations.
  • Add named arguments to JsonGenerator.

0.1.0+1 #

  • updates.

0.1.0 #

  • BREAKING Generator.generate is now async – returns Future<String>
  • Big update to

0.0.1 #

  • Ready for experimentation.

0.0.0+1 #

  • First play release.

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:

  source_gen: ^0.9.5

2. Install it

You can install packages from the command line:

with pub:

$ pub get

Alternatively, your editor might support pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:source_gen/source_gen.dart';
Describes how popular the package is relative to other packages. [more]
Code health derived from static analysis. [more]
Reflects how tidy and up-to-date the package is. [more]
Weighted score of the above. [more]
Learn more about scoring.

We analyzed this package on May 30, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.2
  • pana: 0.13.8-dev

Maintenance suggestions

The package description is too short. (-18 points)

Add more detail to the description field of pubspec.yaml. Use 60 to 180 characters to describe the package, what it does, and its target use case.

Maintain an example. (-10 points)

Create a short demo in the example/ directory to show how to use this package.

Common filename patterns include main.dart, example.dart, and source_gen.dart. Packages with multiple examples should provide example/

For more information see the pub package layout conventions.


Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.5.0 <3.0.0
analyzer >=0.39.0 <0.40.0 0.39.8
async ^2.0.7 2.4.1
build ^1.0.0 1.3.0
dart_style ^1.0.0 1.3.6
glob ^1.1.0 1.2.0
meta ^1.1.0 1.1.8
path ^1.3.2 1.7.0
pedantic ^1.0.0 1.9.0
source_span ^1.4.0 1.7.0
Transitive dependencies
_fe_analyzer_shared 3.0.0
args 1.6.0
charcode 1.1.3
collection 1.14.12
convert 2.1.1
crypto 2.1.5
csslib 0.16.1
html 0.14.0+3
js 0.6.1+1
logging 0.11.4
node_interop 1.1.1
node_io 1.1.1
package_config 1.9.3
pub_semver 1.4.4
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.1.6
watcher 0.9.7+15
yaml 2.2.1
Dev dependencies
build_runner ^1.0.0
build_test ^0.10.0
build_vm_compilers >=0.1.1 <2.0.0
test ^1.0.0