### Typical Setup with SharedPartBuilder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/combining-builder.md Demonstrates a typical setup in build.yaml integrating SharedPartBuilder with CombiningBuilder, showing how different builders generate .g.part files that are then combined. ```yaml targets: $default: builders: # First builder generates .package1.g.part files package1:builder: import: 'package:package1/builder.dart' builder_factories: ['builder1'] build_extensions: {'.dart': ['.package1.g.part']} build_to: cache applies_builders: ['source_gen:combining_builder'] # Second builder generates .package2.g.part files package2:builder: import: 'package:package2/builder.dart' builder_factories: ['builder2'] build_extensions: {'.dart': ['.package2.g.part']} build_to: cache applies_builders: ['source_gen:combining_builder'] # Combining builder merges all .g.part files into .g.dart source_gen:combining_builder: options: header: '// GENERATED CODE - DO NOT MODIFY BY HAND' ignore_for_file: - lines_longer_than_80_chars ``` -------------------------------- ### Include Part Name Example Output Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/combining-builder.md Example of generated output when 'include_part_name' is set to true, showing source filenames before each content section. ```dart // Part: input.package1.g.part // Content from package1 // Part: input.package2.g.part // Content from package2 ``` -------------------------------- ### SharedPartBuilder Configuration Example Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/shared-part-builder.md Shows how to configure SharedPartBuilder and the combining_builder post-processor in a build.yaml file. ```yaml targets: $default: builders: my_package:shared_builder: import: 'package:my_package/builder.dart' builder_factories: ['mySharedBuilder'] build_extensions: {'.dart': ['.my_package.g.part']} auto_apply: dependents build_to: cache # Important: build to cache applies_builders: ['source_gen:combining_builder'] # Apply combining builder source_gen:combining_builder: options: # Optional: customize the combining builder header: '// Custom header' ignore_for_file: - lines_longer_than_80_chars preamble: | // Additional preamble ``` -------------------------------- ### Simple Docstring Generator Example Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/generator.md An example implementation of a Generator that creates comments for elements with documentation. ```dart import 'package:build/build.dart'; import 'package:source_gen/source_gen.dart'; class SimpleDocstringGenerator extends Generator { @override String generate(LibraryReader library, BuildStep buildStep) { final buffer = StringBuffer(); for (final element in library.allElements) { if (element.documentationComment?.isNotEmpty ?? false) { buffer.writeln('// Generated summary for ${element.name}'); } } return buffer.toString(); } } ``` -------------------------------- ### PartBuilder Configuration Example Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/configuration.md Configures a custom PartBuilder with options for header and writeDescriptions. ```dart Builder myBuilder(BuilderOptions options) { return PartBuilder( [MyGenerator()], '.custom.dart', header: options.config['header'] as String? ?? defaultFileHeader, writeDescriptions: options.config['write_descriptions'] as bool? ?? true, ); } ``` -------------------------------- ### SharedPartBuilder Configuration Example Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/configuration.md Configures a custom SharedPartBuilder with options for writeDescriptions. ```dart Builder mySharedBuilder(BuilderOptions options) { return SharedPartBuilder( [MyGenerator()], 'my_package', writeDescriptions: options.config['write_descriptions'] as bool? ?? true, ); } ``` -------------------------------- ### Usage Example for PartBuilder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/part-builder.md Demonstrates how to create and configure a PartBuilder instance. This includes defining a custom generator and setting the generated file extension. ```dart import 'package:build/build.dart'; import 'package:source_gen/source_gen.dart'; // Example generator class MyGenerator extends GeneratorForAnnotation { @override String generateForAnnotatedElement( Element element, ConstantReader annotation, BuildStep buildStep, ) { return '// Generated code for ${element.name}'; } } // Create the builder Builder myBuilder(BuilderOptions options) { return PartBuilder( [MyGenerator()], '.my.dart', writeDescriptions: true, ); } ``` -------------------------------- ### build.yaml Configuration for LibraryBuilder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/library-builder.md Example configuration for a custom builder factory in build.yaml, specifying the import, factory, and build extensions. ```yaml builders: my_library_builder: import: 'package:my_package/builder.dart' builder_factories: ['myLibraryBuilder'] build_extensions: {'.dart': ['.info.dart']} auto_apply: dependents ``` -------------------------------- ### Configuration in build.yaml Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/combining-builder.md Example of how to configure the source_gen:combining_builder target in a build.yaml file, specifying options like header, ignore_for_file, preamble, and include_part_name. ```yaml targets: $default: builders: source_gen:combining_builder: options: header: '// My Custom Header' ignore_for_file: - lines_longer_than_80_chars preamble: | // Generated code include_part_name: true ``` -------------------------------- ### SharedPartBuilder Usage Example Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/shared-part-builder.md Demonstrates how to create a custom generator and use it with SharedPartBuilder in a Dart file. ```dart import 'package:build/build.dart'; import 'package:source_gen/source_gen.dart'; class MySharedGenerator extends GeneratorForAnnotation { @override String generateForAnnotatedElement( Element element, ConstantReader annotation, BuildStep buildStep, ) { return '// Generated: ${element.name}'; } } Builder mySharedBuilder(BuilderOptions options) { return SharedPartBuilder( [MySharedGenerator()], 'my_package', // This becomes: .my_package.g.part ); } ``` -------------------------------- ### Example: Finding a Class Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/library-reader.md Demonstrates how to use findType to locate a specific class like 'List'. ```dart final listType = libraryReader.findType('List'); if (listType != null) { // Found the List class } ``` -------------------------------- ### Output File Structure Example Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/library-builder.md Illustrates the typical structure of a file generated by LibraryBuilder, including generated code comments and imports. ```dart // GENERATED CODE - DO NOT MODIFY BY HAND // dart format width=80 import 'package:...'; // Content generated by the single Generator class GeneratedCode { } ``` -------------------------------- ### Combining Builder Options: build_extensions Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/shared-part-builder.md Example of customizing the output location for generated files using the combining_builder options. ```yaml source_gen:combining_builder: options: build_extensions: '^lib/{{}}.dart': 'lib/generated/{{}}.g.dart' ``` -------------------------------- ### Example: Converting URIs to Relative URLs Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/library-reader.md Shows how to convert 'dart:core' and a package URI to relative URLs using pathToUrl. ```dart final toCore = libraryReader.pathToUrl('dart:core'); // Returns Uri final toOther = libraryReader.pathToUrl('package:other_lib/models.dart'); ``` -------------------------------- ### Example: Finding Directives with SourceGenTest Annotation Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/library-reader.md Iterates through library directives annotated with SourceGenTest. ```dart final sourceGen = TypeChecker.typeNamed(SourceGenTest); for (var annotatedDirective in libraryReader.libraryDirectivesAnnotatedWith(sourceGen)) { final directive = annotatedDirective.directive; // Handle import/export/part } ``` -------------------------------- ### Example Output Format Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/combining-builder.md Illustrates the typical output format generated by the combining builder, including header, ignore directives, preamble, part statement, and combined content from .g.part files. ```dart // GENERATED CODE - DO NOT MODIFY BY HAND // ignore_for_file: lines_longer_than_80_chars // Custom preamble here part of 'input.dart'; // Part: input.builder1.g.part // Content from builder1... // Part: input.builder2.g.part // Content from builder2... ``` -------------------------------- ### Combining Builder Options: header Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/shared-part-builder.md Example of customizing the header comment in the generated file using the combining_builder options. ```yaml source_gen:combining_builder: options: header: '// Custom header text' ``` -------------------------------- ### Combining Builder Options: preamble Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/shared-part-builder.md Example of adding custom preamble content after the header in the generated file using the combining_builder options. ```yaml source_gen:combining_builder: options: preamble: | // This file is auto-generated. // Do not edit manually. ``` -------------------------------- ### AnnotatedElement Usage Example Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/types.md Demonstrates how to iterate through library elements and access their annotations and the elements themselves using AnnotatedElement. ```dart final jsonChecker = TypeChecker.typeNamed(JsonSerializable); for (var annotated in library.annotatedWith(jsonChecker)) { final element = annotated.element; final annotation = annotated.annotation; } ``` -------------------------------- ### Getting All Library Elements Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/library-reader.md Retrieves all declarations within the library, including the library itself and its children. ```dart Iterable get allElements => [element, ...element.children]; ``` -------------------------------- ### Custom Generator for LibraryBuilder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/library-builder.md Example of a custom Generator that produces standalone library content, including necessary import statements. ```dart import 'package:build/build.dart'; import 'package:source_gen/source_gen.dart'; import 'package:analyzer/dart/element/element.dart'; class MyLibraryGenerator extends Generator { @override String generate(LibraryReader library, BuildStep buildStep) { final buffer = StringBuffer(); // Add import statements that the standalone library needs buffer.writeln("import 'package:mylib/models.dart';"); buffer.writeln(); // Generate library content for (final element in library.classes) { buffer.writeln('// Generated for ${element.name}'); buffer.writeln('class ${element.name}Generated {}'); } return buffer.toString(); } } Builder myLibraryBuilder(BuilderOptions options) { return LibraryBuilder( MyLibraryGenerator(), generatedExtension: '.info.dart', ); } ``` -------------------------------- ### Getting All Class Declarations Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/library-reader.md Retrieves all class declarations present in the library. ```dart Iterable get classes => element.classes; ``` -------------------------------- ### Combining Builder Options: ignore_for_file Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/shared-part-builder.md Example of adding lints to ignore in the generated file using the combining_builder options. ```yaml source_gen:combining_builder: options: ignore_for_file: - lines_longer_than_80_chars - unnecessary_getters_setters ``` -------------------------------- ### FormatException Examples Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/errors.md Illustrates how to handle FormatException when reading incompatible types from ConstantReader in Dart. Shows methods for checking types, using optional access, and handling exceptions. ```dart final reader = ConstantReader(annotation); // Check type before accessing if (reader.isString) { final value = reader.stringValue; } // Or use optional access final name = reader.peek('name')?.stringValue ?? 'default'; // Or handle exception try { final value = reader.intValue; } on FormatException catch (e) { // Not an int } ``` -------------------------------- ### ArgumentError Examples Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/errors.md Demonstrates common scenarios where ArgumentError is thrown due to invalid configuration or arguments in Dart builders. Shows correct usage for valid configurations. ```dart // Invalid extension (must start with .) PartBuilder([gen], 'bad') // → ArgumentError PartBuilder([gen], '.g.dart') // OK // Invalid partId (must be alphanumeric + _ and .) SharedPartBuilder([gen], '.bad-id') // → ArgumentError SharedPartBuilder([gen], 'my.pkg') // OK // Multiple generators in LibraryBuilder LibraryBuilder([gen1, gen2]) // → ArgumentError LibraryBuilder(gen1) // OK // build_extensions validation validatedBuildExtensionsFrom( {'invalid': ['output']}, {}, ) // → ArgumentError ``` -------------------------------- ### Example: Finding Elements with JsonSerializable Annotation Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/library-reader.md Iterates through elements annotated with JsonSerializable using TypeChecker.typeNamed. ```dart final jsonSerializable = TypeChecker.typeNamed(JsonSerializable); for (var annotated in libraryReader.annotatedWith(jsonSerializable)) { final element = annotated.element; final annotation = annotated.annotation; // Process annotated element } ``` -------------------------------- ### Source Code Organization Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/INDEX.md Illustrates the directory structure of the source_gen package, including the location of API references, topic guides, and the main documentation files. ```plaintext output/ ├── README.md # Start here ├── QUICK-REFERENCE.md # Common snippets ├── INDEX.md # This file ├── types.md # Type definitions ├── errors.md # Exception reference ├── configuration.md # Build configuration └── api-reference/ # Detailed API docs ├── generator.md ├── generator-for-annotation.md ├── library-builder.md ├── part-builder.md ├── shared-part-builder.md ├── combining-builder.md ├── library-reader.md ├── constant-reader.md ├── type-checker.md ├── revivable.md ├── span-utilities.md └── utility-functions.md ``` -------------------------------- ### AnnotationScanner Usage Example Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/type-checker.md Demonstrates how to use `TypeChecker` to scan for specific annotations and check type relationships within an `Element`. This is commonly used in code generation. ```dart import 'package:source_gen/source_gen.dart'; import 'package:analyzer/dart/element/element.dart'; class AnnotationScanner { static const jsonSerializable = TypeChecker.typeNamed(JsonSerializable); static const override = TypeChecker.typeNamed(Override, inSdk: true); static const iterableType = TypeChecker.typeNamed(Iterable); void scan(Element element) { // Check for specific annotation if (jsonSerializable.hasAnnotationOf(element)) { final annotation = jsonSerializable.firstAnnotationOf(element); // Process annotation } // Check type relationship if (iterableType.isAssignableFrom(element)) { // element is Iterable or a subtype } // Check inheritance if (objectChecker.isSuperOf(element)) { // element's class extends something } } } ``` -------------------------------- ### Get Source Span for Element Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/span-utilities.md Retrieves a SourceSpan for an element's definition. If the SourceFile is not provided, it will be loaded automatically. ```dart import 'package:source_gen/source_gen.dart'; void reportError(ClassElement element, String message) { final span = spanForElement(element); log.warning(span.message(message)); // Output: path/to/file.dart 10:5 // class MyClass { } // ^^^^^ // MyClass does not implement Interface } ``` -------------------------------- ### Revivable Usage Example: Generating Runtime Instances Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/revivable.md Demonstrates how to use the Revivable class to generate Dart code for instantiating constants at runtime. Includes logic for handling top-level functions, classes, and arguments. ```dart import 'package:source_gen/source_gen.dart'; import 'package:analyzer/dart/constant/value.dart'; String generateFromRevivable(Revivable revivable) { final buffer = StringBuffer(); // Generate const instantiation buffer.write('const '); if (revivable.source.fragment.isEmpty) { // Top-level function/field buffer.write('${revivable.source}::${revivable.accessor}'); } else { // Class constructor final className = revivable.source.fragment; buffer.write(className); if (revivable.accessor.isNotEmpty && revivable.accessor != '') { buffer.write('.${revivable.accessor}'); } } // Generate arguments buffer.write('('); for (var i = 0; i < revivable.positionalArguments.length; i++) { if (i > 0) buffer.write(', '); buffer.write(reviveArgument(revivable.positionalArguments[i])); } for (var entry in revivable.namedArguments.entries) { if (revivable.positionalArguments.isNotEmpty || revivable.namedArguments.keys.toList().indexOf(entry.key) > 0) { buffer.write(', '); } buffer.write('${entry.key}: ${reviveArgument(entry.value)}'); } buffer.write(')'); return buffer.toString(); } String reviveArgument(DartObject arg) { // Recursively revive nested arguments final string = arg.toStringValue(); if (string != null) return "'$string'"; final int = arg.toIntValue(); if (int != null) return '$int'; // Handle other types... return 'null'; } ``` -------------------------------- ### AnnotatedDirective Usage Example Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/types.md Shows how to find and process library directives that have specific annotations, differentiating between import, export, and part directives. ```dart final checker = TypeChecker.typeNamed(SomeAnnotation); for (var dir in library.libraryDirectivesAnnotatedWith(checker)) { if (dir.directive is LibraryImport) { // Handle import } } ``` -------------------------------- ### Convert Asset URL to Package URL Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/utility-functions.md Converts a URI from the `asset:` scheme to the `package:` scheme. For example, `asset:my_lib/lib/foo.dart` becomes `package:my_lib/foo.dart`. Primarily for internal use. ```dart Uri assetToPackageUrl(Uri url) ``` -------------------------------- ### Generator Error Reporting Example Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/span-utilities.md Demonstrates how a generator can throw InvalidGenerationSource with an element, automatically including source location information in the error message. ```dart import 'package:build/build.dart'; import 'package:source_gen/source_gen.dart'; class MyGenerator extends GeneratorForAnnotation { @override String generateForAnnotatedElement( Element element, ConstantReader annotation, BuildStep buildStep, ) { // Validate element if (element is! ClassElement) { throw InvalidGenerationSource( 'MyAnnotation can only be applied to classes', todo: 'Move the annotation to a class', element: element, ); } return '// Generated code'; } } ``` -------------------------------- ### Get Source Span for Fragment Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/span-utilities.md Retrieves a SourceSpan for a fragment, which is part of an element declaration. This span points to the start of the fragment or its name. ```dart SourceSpan spanForFragment(Fragment fragment) ``` -------------------------------- ### Custom Generator with Library Reader Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/library-reader.md Example of creating a custom generator using LibraryReader to find annotated elements, specific types, and iterate through classes within a Dart library. ```dart import 'package:analyzer/dart/element/element.dart'; import 'package:build/build.dart'; import 'package:source_gen/source_gen.dart'; class MyGenerator extends GeneratorForAnnotation { @override String generateForAnnotatedElement( Element element, ConstantReader annotation, BuildStep buildStep, ) { return 'Generated code'; } @override FutureOr generate(LibraryReader library, BuildStep buildStep) { // Find all annotated elements final jsonSerializable = TypeChecker.typeNamed(SerializeMe); final annotated = library.annotatedWith(jsonSerializable); // Find specific type final myClass = library.findType('MyClass'); // Get all classes for (final cls in library.classes) { // Process each class } return 'output'; } } ``` -------------------------------- ### Get All Exact Annotations Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/type-checker.md Use `annotationsOfExact` to get all annotations that exactly match the checker's type, excluding subtypes. This method can be configured to throw on unresolved annotations. ```dart Iterable annotationsOfExact( Element element, { bool throwOnUnresolved = true, }) ``` -------------------------------- ### Usage Example: ComputedGenerator Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/generator-for-annotation.md Demonstrates how to extend GeneratorForAnnotation to generate code for fields annotated with a custom @Computed annotation. This example generates a getter for a computed property based on an expression. ```dart import 'package:analyzer/dart/element/element.dart'; import 'package:build/build.dart'; import 'package:source_gen/source_gen.dart'; @Target({ElementType.field}) class Computed { final String expression; const Computed(this.expression); } class ComputedGenerator extends GeneratorForAnnotation { @override String generateForAnnotatedElement( Element element, ConstantReader annotation, BuildStep buildStep, ) { final fieldName = element.name; final expression = annotation.read('expression').stringValue; return ''' num get computed_$fieldName => $expression; '''; } @override dynamic generateForAnnotatedDirective( ElementDirective directive, ConstantReader annotation, BuildStep buildStep, ) { // Handle directives if needed, otherwise do nothing } } ``` -------------------------------- ### Getting All Enum Declarations Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/library-reader.md Retrieves all enum declarations present in the library. ```dart Iterable get enums => element.enums; ``` -------------------------------- ### build.yaml Configuration for Output Directory Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/library-builder.md Shows how to configure build_extensions in build.yaml to specify custom output directories for generated files. ```yaml builders: my_library_builder: options: build_extensions: '^lib/{{}}.dart': 'lib/generated/{{}}.info.dart' ``` -------------------------------- ### Preamble Option Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/combining-builder.md YAML configuration for adding custom content that is prepended after the header in the generated file. ```yaml options: preamble: | // This file contains auto-generated code. // DO NOT edit manually! // Last generated: 2024-01-01 ``` -------------------------------- ### Create a Shared Part File Builder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/QUICK-REFERENCE.md Set up a shared part file builder, recommended for better build performance. ```dart Builder myBuilder(BuilderOptions options) { return SharedPartBuilder([MyGenerator()], 'my_package'); } ``` -------------------------------- ### Build Extensions Configuration for Different Directories Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/part-builder.md Demonstrates how to configure `build_extensions` in `build.yaml` to output generated files to different directories. This requires updating the `part` statement in the input file accordingly. ```yaml builders: my_builder: build_extensions: '^lib/{{}}.dart': 'lib/generated/{{}}.my.dart' ``` -------------------------------- ### Execute build_runner commands Source: https://github.com/dart-lang/source_gen/blob/master/example_usage/README.md Run these commands in the project root to fetch dependencies and trigger the build process. ```console $ dart pub get ... $ dart run build_runner build ``` -------------------------------- ### Get Type Name from DartType Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/QUICK-REFERENCE.md Retrieve the string name of a DartType using the typeNameOf function. ```dart final typeName = typeNameOf(dartType); ``` -------------------------------- ### Configure preamble in build.yaml Source: https://github.com/dart-lang/source_gen/blob/master/README.md Use the `preamble` option to prepend custom content to all generated libraries, after the default header. This allows for adding custom comments or directives. ```yaml targets: $default: builders: source_gen:combining_builder: options: preamble: | // Foo // Bar ``` -------------------------------- ### build.yaml Configuration for PartBuilder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/part-builder.md Shows how to configure a PartBuilder within a `build.yaml` file. This specifies the import path, builder factory, output extensions, and application behavior. ```yaml builders: my_builder: import: 'package:my_package/builder.dart' builder_factories: ['myBuilder'] build_extensions: {'.dart': ['.my.dart']} auto_apply: dependents ``` -------------------------------- ### Minimal build.yaml Configuration Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/QUICK-REFERENCE.md Configure a builder in build.yaml with essential settings for integration into the build system. ```yaml builders: my_builder: import: 'package:my_package/builder.dart' builder_factories: ['myBuilder'] build_extensions: {'.dart': ['.my_package.g.part']} build_to: cache applies_builders: ['source_gen:combining_builder'] ``` -------------------------------- ### Get Source Span for Errors Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/QUICK-REFERENCE.md Generate a source span for a Dart element to provide precise error location information. ```dart final span = spanForElement(element); log.warning(span.message('Error message')); ``` -------------------------------- ### Run the Build Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/README.md Executes the Dart build system to generate code using configured builders. ```bash dart run build_runner build ``` -------------------------------- ### Configure Source Gen Builder Options Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/QUICK-REFERENCE.md Configure header, ignore_for_file directives, and custom preambles for the source_gen builder in build.yaml. ```yaml targets: $default: builders: source_gen:combining_builder: options: header: '// My header' ignore_for_file: - lines_longer_than_80_chars preamble: 'Custom preamble' ``` -------------------------------- ### Preamble Option for Combining Builder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/configuration.md Adds custom content after the header but before the 'part of' statement in generated files. ```yaml source_gen:combining_builder: options: preamble: | // This file is automatically generated. // Do not modify manually. // Generated: {timestamp} ``` -------------------------------- ### Create a Part File Builder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/QUICK-REFERENCE.md Configure a builder to generate code into a part file with a custom extension. ```dart Builder myBuilder(BuilderOptions options) { return PartBuilder([MyGenerator()], '.custom.dart'); } ``` -------------------------------- ### Basic Combining Builder Configuration Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/configuration.md Enables the source_gen combining_builder in build.yaml. ```yaml targets: $default: builders: source_gen:combining_builder: enabled: true ``` -------------------------------- ### Build Extensions Option Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/combining-builder.md YAML configuration to customize the output location and naming pattern for generated files using build_extensions. ```yaml options: build_extensions: '^lib/{{}}.dart': 'lib/generated/{{}}.g.dart' '^test/{{}}.dart': 'test/generated/{{}}.g.dart' ``` -------------------------------- ### Get Source Span for AST Node Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/span-utilities.md Retrieves a SourceSpan for an AST node. Useful for pinpointing specific parts of the code structure for diagnostics. ```dart import 'package:analyzer/dart/ast/ast.dart'; void checkAnnotation(Annotation annotation) { final span = spanForNode(annotation); log.warning(span.message('Unknown annotation type')); } ``` -------------------------------- ### Combining Builder Entry Point Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/configuration.md The entry point for the combining builder and part file cleanup builder are defined in lib/builder.dart. ```dart import 'package:source_gen/builder.dart'; // Entry point for combining builder Builder combiningBuilder([BuilderOptions options = BuilderOptions.empty]) // Entry point for part file cleanup PostProcessBuilder partCleanup(BuilderOptions options) ``` -------------------------------- ### Get Source Span for Directive Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/span-utilities.md Retrieves a SourceSpan for a directive (import, export, part) at the keyword. Used for reporting issues with library directives. ```dart for (var directive in library.libraryImports) { final span = spanForElementDirective(directive); log.warning(span.message('Invalid import configuration')); } ``` -------------------------------- ### SharedPartBuilder Output File Format Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/shared-part-builder.md Illustrates the intermediate .g.part file generation and subsequent combination into a final .g.dart file. ```text filename.input.dart → filename.partId.g.part → filename.g.dart Each .g.part file contains: // Part content from this generator // Additional parts from other generators get combined here ``` -------------------------------- ### Validation in Generators Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/errors.md Example of a Dart generator that performs strict validation on the annotated element, annotation fields, and internal state, throwing InvalidGenerationSource for issues. ```dart class StrictGenerator extends GeneratorForAnnotation { @override String generateForAnnotatedElement( Element element, ConstantReader annotation, BuildStep buildStep, ) { // Validate element type if (element is! ClassElement) { throw InvalidGenerationSource( 'Config can only be applied to classes', todo: 'Move annotation to a class', element: element, ); } // Validate annotation fields final name = annotation.peek('name'); if (name == null || !name.isString) { throw InvalidGenerationSource( 'Config requires a "name" String field', todo: '@Config(name: "value")', element: element, ); } // Validate state if (!element.fields.any((f) => f.name == 'data')) { throw InvalidGenerationSource( 'Config requires a "data" field', todo: 'Add: final String data;', element: element, ); } return 'valid code'; } } ``` -------------------------------- ### Revivable Example: Extracting Annotation Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/revivable.md Illustrates how to obtain a Revivable object from an annotation on a Dart element and check if it's private before using its string representation. ```dart final annotation = typeChecker.firstAnnotationOf(element); final revivable = reviveInstance(annotation); if (!revivable.isPrivate) { // Safe to use in generated code final code = revivable.toString(); } ``` -------------------------------- ### Full Combining Builder Configuration with Options Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/configuration.md Configures the combining_builder with various options including header, ignore_for_file, preamble, include_part_name, and build_extensions. ```yaml targets: $default: builders: source_gen:combining_builder: options: header: '// Custom header' ignore_for_file: - lines_longer_than_80_chars - prefer_const_constructors preamble: | // Generated file // Do not edit manually include_part_name: true build_extensions: '^lib/{{}}.dart': 'lib/generated/{{}}.g.dart' ``` -------------------------------- ### Get All Annotations of Type Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/type-checker.md Use `annotationsOf` to retrieve all annotations on an element that are assignable to the checker's type. The method can optionally throw if annotations are unresolved. ```dart Iterable annotationsOf( Object element, { bool throwOnUnresolved = true, }) ``` -------------------------------- ### spanForFragment Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/span-utilities.md Gets a source span for a fragment's location within an element declaration. This is useful for pinpointing specific parts of an element's definition. ```APIDOC ## spanForFragment ### Description Get a source span for a fragment's location. ### Method Signature ```dart SourceSpan spanForFragment(Fragment fragment) ``` ### Parameters #### Path Parameters - **fragment** (Fragment) - Required - An analyzer fragment (part of element declaration) ### Returns `SourceSpan` at the start of the fragment (or name if available). ``` -------------------------------- ### Build Extensions Option for Combining Builder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/configuration.md Configures output file locations and naming conventions for generated files. ```yaml source_gen:combining_builder: options: build_extensions: '^lib/{{}}.dart': 'lib/generated/{{}}.g.dart' '^test/{{}}.dart': 'test/generated/{{}}.g.dart' ``` -------------------------------- ### Define a Post-Process Builder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/configuration.md Configure a builder that runs after other builders, often for cleanup or merging. Specify input extensions for files to process. ```yaml post_process_builders: cleanup: import: 'package:my_generator/builder.dart' builder_factory: 'cleanup' input_extensions: ['.g.part'] ``` -------------------------------- ### Include Part Name Option Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/combining-builder.md YAML configuration to enable including the source filename as a comment before each section in the generated output. ```yaml options: include_part_name: true ``` -------------------------------- ### Get Dart Type Name Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/utility-functions.md Retrieves the name of a Dart type, correctly handling type aliases. This is useful when the analyzer might not preserve the alias name. ```dart String typeNameOf(DartType type) ``` ```dart typedef VoidFunc = void Function(); // Without typeNameOf: type.element?.name // Returns null in newer versions // With typeNameOf: typeNameOf(type) // Returns 'VoidFunc' ``` ```dart import 'package:source_gen/source_gen.dart'; import 'package:analyzer/dart/element/type.dart'; String generateFieldGetter(DartType fieldType) { final typeName = typeNameOf(fieldType); return ''' $typeName get field => _field; '''; } ``` -------------------------------- ### Import necessary packages for source_gen Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/QUICK-REFERENCE.md Import the build, source_gen, and analyzer packages for generator development. ```dart import 'package:build/build.dart'; import 'package:source_gen/source_gen.dart'; import 'package:analyzer/dart/element/element.dart'; ``` -------------------------------- ### spanForElementDirective Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/span-utilities.md Gets a source span for a directive's location (import, export, part). This is useful for pinpointing the exact keyword in the source code where a directive is declared. ```APIDOC ## spanForElementDirective ### Description Get a source span for a directive's location. ### Method Signature ```dart SourceSpan spanForElementDirective(ElementDirective elementDirective) ``` ### Parameters #### Path Parameters - **elementDirective** (ElementDirective) - Required - The directive (import, export, part) ### Returns `SourceSpan` at the directive keyword (import, export, part). ### Supported Directives - `LibraryImport` — import statements - `LibraryExport` — export statements - `PartInclude` — part statements ### Usage Example ```dart for (var directive in library.libraryImports) { final span = spanForElementDirective(directive); log.warning(span.message('Invalid import configuration')); } ``` ``` -------------------------------- ### Output File Structure for PartBuilder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/part-builder.md Illustrates the standard structure of files generated by PartBuilder. It includes a header, a 'part of' directive, and the generated code content. ```dart // GENERATED CODE - DO NOT MODIFY BY HAND part of 'input_file.dart'; // Generator description and content... ``` -------------------------------- ### Test Dart Generators with build_test Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/QUICK-REFERENCE.md Set up and run tests for Dart code generators using the build_test package, defining input assets and expected outputs. ```dart import 'package:build_test/build_test.dart'; Future main() async { final testAssets = { 'my_package|lib/input.dart': ''' library input; import 'package:my_package/annotations.dart'; @MyAnnotation() class MyClass {} ''', }; final builder = MyBuilder(BuilderOptions({})); await testBuilder( builder, testAssets, expectedOutputs: { 'my_package|lib/input.g.dart': 'expected output here', }, ); } ``` -------------------------------- ### Get First Exact Annotation Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/type-checker.md Use `firstAnnotationOfExact` to find the first annotation that exactly matches the checker's type, excluding subtypes. It can optionally throw on unresolved annotations. ```dart DartObject? firstAnnotationOfExact( Element element, { bool throwOnUnresolved = true, }) ``` -------------------------------- ### Create a Standalone Library Builder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/QUICK-REFERENCE.md Define a builder that generates a standalone library file. ```dart Builder myBuilder(BuilderOptions options) { return LibraryBuilder(MyGenerator()); } ``` -------------------------------- ### Get Element URL Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/utility-functions.md Retrieves a full URL string for a given Dart element, formatted as `package:name/path#ElementName` or `dart:core#ElementName`. Primarily for internal use. ```dart String urlOfElement(Element element) ``` -------------------------------- ### Include Part Name Option for Combining Builder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/configuration.md Includes the source .g.part filename as a comment before each section in the generated output. Useful for debugging. ```yaml source_gen:combining_builder: options: include_part_name: true ``` -------------------------------- ### Get First Annotation of Type Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/type-checker.md Use `firstAnnotationOf` to retrieve the first annotation on an element that matches the checker's type. Optionally, configure whether to throw an error if annotations are unresolved. ```dart DartObject? firstAnnotationOf( Object element, { bool throwOnUnresolved = true, }) ``` ```dart final checker = TypeChecker.typeNamed(JsonSerializable); final annotation = checker.firstAnnotationOf(classElement); if (annotation != null) { final reader = ConstantReader(annotation); } ``` -------------------------------- ### spanForElement Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/span-utilities.md Gets a source span for an element's definition location. This function is useful for generating error messages that reference the exact location of an element's name in the source code. ```APIDOC ## spanForElement ### Description Get a source span for an element's definition location. ### Method Signature ```dart SourceSpan spanForElement(Element element, [SourceFile? file]) ``` ### Parameters #### Path Parameters - **element** (Element) - Required - The analyzer element to locate - **file** (SourceFile?) - Optional - Pre-loaded source file. If omitted, loaded automatically ### Returns `SourceSpan` covering the element's name in source code. ### Usage Example ```dart import 'package:source_gen/source_gen.dart'; void reportError(ClassElement element, String message) { final span = spanForElement(element); log.warning(span.message(message)); } ``` ``` -------------------------------- ### Accessing Source Location Components Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/revivable.md Demonstrates how to extract and use components of a Revivable object's source location, such as scheme, path, and fragment. Includes checks for SDK classes and top-level members. ```dart final revivable = ...; // Source URL components print(revivable.source.scheme); // 'dart', 'package', 'asset' print(revivable.source.path); // 'collection', 'my_lib/models.dart' print(revivable.source.fragment); // 'LinkedHashMap', 'MyClass' // Check if in SDK if (revivable.source.scheme == 'dart') { // SDK class } // Check if top-level if (revivable.source.fragment.isEmpty) { // Top-level function or field } ``` -------------------------------- ### typeNameOf Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/utility-functions.md Get the name of a Dart type, handling type aliases correctly. This function is useful for accurately retrieving type names, especially with type aliases in newer Dart analyzer versions. ```APIDOC ## typeNameOf ### Description Get the name of a Dart type, handling type aliases correctly. ### Signature ```dart String typeNameOf(DartType type) ``` ### Parameters #### Path Parameters - **type** (DartType) - Required - The analyzer type to get a name for ### Returns String name of the type. ### Purpose In newer Dart analyzer versions, type aliases don't preserve their name through `DartType.element.name`. This function works around that limitation. ### Example ```dart typedef VoidFunc = void Function(); // Without typeNameOf: type.element?.name // Returns null in newer versions // With typeNameOf: typeNameOf(type) // Returns 'VoidFunc' ``` ### Handles - Type aliases (typedef) — returns alias name - Interface types (classes) — returns class name - Type parameters — returns parameter name - Dynamic type — returns 'dynamic' ### Throws `UnimplementedError` for unsupported type kinds. ### Usage ```dart import 'package:source_gen/source_gen.dart'; import 'package:analyzer/dart/element/type.dart'; String generateFieldGetter(DartType fieldType) { final typeName = typeNameOf(fieldType); return ''' $typeName get field => _field; '''; } ``` ``` -------------------------------- ### Configure Combining Builder Options Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/configuration.md Set options for the combining_builder, such as a header, ignore directives, or a preamble for generated files. ```yaml targets: $default: builders: source_gen:combining_builder: options: header: '// Generated by my_generator' ignore_for_file: - lines_longer_than_80_chars preamble: | // This file was automatically generated ``` -------------------------------- ### spanForNode Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/span-utilities.md Gets a source span for an Abstract Syntax Tree (AST) node's location. This function is valuable for detailed analysis and reporting on specific parts of the Dart code's structure. ```APIDOC ## spanForNode ### Description Get a source span for an AST node's location. ### Method Signature ```dart SourceSpan spanForNode(AstNode node) ``` ### Parameters #### Path Parameters - **node** (AstNode) - Required - An analyzer AST node ### Returns `SourceSpan` covering the node. ### Usage Example ```dart import 'package:analyzer/dart/ast/ast.dart'; void checkAnnotation(Annotation annotation) { final span = spanForNode(annotation); log.warning(span.message('Unknown annotation type')); } ``` ``` -------------------------------- ### Define a Standalone Library Builder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/configuration.md Configure a builder for generating standalone library files. This builder has specific build extensions for its output. ```yaml library_builder: import: 'package:my_generator/builder.dart' builder_factories: ['myLibraryBuilder'] build_extensions: {'.dart': ['.info.dart']} auto_apply: dependents ``` -------------------------------- ### Create a Builder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/README.md Defines a builder using `SharedPartBuilder`, which takes a list of generators and a package name. This is used to configure how generators are applied within the build system. ```dart Builder myBuilder(BuilderOptions options) { return SharedPartBuilder( [MyGenerator()], 'my_package', ); } ``` -------------------------------- ### Create a Basic Generator Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/QUICK-REFERENCE.md Implement a simple generator by extending the Generator class and overriding the generate method. ```dart class MyGenerator extends Generator { @override String generate(LibraryReader library, BuildStep buildStep) { return 'generated code'; } } ``` -------------------------------- ### Combining Builder Configuration Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/README.md Configuration options for the source_gen combining_builder, including header customization, ignored lints, preamble content, and output file extensions. ```yaml source_gen:combining_builder: options: header: '// Custom header' # Default: GENERATED CODE comment ignore_for_file: [lint1, lint2] # Lints to ignore preamble: 'Custom content...' # Content after header include_part_name: true # Show source filenames build_extensions: # Output location '^lib/{{}}.dart': 'lib/generated/{{}}.g.dart' ``` -------------------------------- ### Custom Header Option for Combining Builder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/configuration.md Replaces the default header comment with a custom one. ```yaml source_gen:combining_builder: options: header: '// Copyright 2024 // Licensed under MIT License' ``` -------------------------------- ### Logging in Builders Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/QUICK-REFERENCE.md Utilize the build_log package to output informational, warning, and severe messages during the build process. ```dart import 'package:build/build.dart'; // In builder log.info('Info message'); log.warning('Warning: $element'); log.severe('Error: ${e}'); ``` -------------------------------- ### Create Part Cleanup Builder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/utility-functions.md Factory function to create a post-processor that cleans up temporary `.g.part` files. This is typically configured automatically in `build.yaml`. ```dart PostProcessBuilder partCleanup(BuilderOptions options) ``` ```yaml post_process_builders: source_gen:part_cleanup: import: 'package:source_gen/builder.dart' builder_factory: 'partCleanup' ``` -------------------------------- ### Configure build_extensions for output directories Source: https://github.com/dart-lang/source_gen/blob/master/README.md Customize output file locations using `build_extensions`. This option maps input file patterns to output file patterns, allowing generation of files in different directories or with different names. ```yaml targets: $default: builders: source_gen:combining_builder: options: build_extensions: '^lib/{{}}.dart': 'lib/generated/{{}}.g.dart' some_cool_builder: options: build_extensions: '^lib/models/{{}}.dart': 'lib/models/generated/{{}}.foo.dart' ``` -------------------------------- ### Configure builder in build.yaml Source: https://github.com/dart-lang/source_gen/blob/master/README.md Define a builder in your build.yaml file to integrate with build_runner. ```yaml builders: some_cool_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"] ``` -------------------------------- ### Initialize CombiningBuilder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/types.md Initializes a CombiningBuilder, which is responsible for merging .g.part files into .g.dart files. It accepts optional parameters for including part names, ignoring files, and setting a preamble or header. ```dart class CombiningBuilder implements Builder { final Map> buildExtensions; final String? header; const CombiningBuilder({ bool? includePartName, Set? ignoreForFile, String? preamble, Map> buildExtensions = _defaultExtensions, String? header, }); } ``` -------------------------------- ### Create CombiningBuilder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/utility-functions.md Factory function to create a `CombiningBuilder` configured with options from build configuration. Use this to combine `.g.part` files during the build process. ```dart Builder combiningBuilder([BuilderOptions options = BuilderOptions.empty]) ``` ```yaml # In build.yaml targets: $default: builders: source_gen:combining_builder: options: header: '// Generated code' ignore_for_file: - lines_longer_than_80_chars preamble: | // Custom preamble ``` -------------------------------- ### Configure in build.yaml Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/README.md Configures a custom builder in `build.yaml`. This includes specifying the import path, builder factory, build extensions, and build target options. ```yaml builders: my_builder: import: 'package:my_package/builder.dart' builder_factories: ['myBuilder'] build_extensions: {'.dart': ['.my_package.g.part']} build_to: cache applies_builders: ['source_gen:combining_builder'] targets: $default: builders: source_gen:combining_builder: options: header: '// Generated code' ``` -------------------------------- ### Configure combining_builder header Source: https://github.com/dart-lang/source_gen/blob/master/README.md Customize the header of generated files in build.yaml. ```yaml targets: $default: builders: source_gen:combining_builder: options: header: |- // Copyright 2026 // Licensed under the Apache License, Version 2.0 // Code generated by robots ``` -------------------------------- ### TypeChecker.fromUrl Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/api-reference/type-checker.md Creates a TypeChecker from a URL string, enabling matching of types based on their fully qualified URL, including package and fragment information. ```APIDOC ## TypeChecker.fromUrl ### Description Creates a checker from a URL string. This method allows you to match types using their full URL, which can include the package and fragment, providing a precise way to identify types. ### Method `TypeChecker.fromUrl(dynamic url)` ### Parameters #### Path Parameters * **url** (String or Uri) - Required - Full URL including package/fragment, e.g., 'dart:collection#LinkedHashMap'. ### Request Example ```dart const mapChecker = TypeChecker.fromUrl('dart:core#Map'); const customChecker = TypeChecker.fromUrl('package:my_lib/models.dart#MyClass'); ``` ``` -------------------------------- ### Use Unique Extension or SharedPartBuilder Source: https://github.com/dart-lang/source_gen/blob/master/_autodocs/QUICK-REFERENCE.md When using PartBuilder, specify a unique file extension (e.g., '.custom.dart') or use SharedPartBuilder for managing generated files. ```dart // Right PartBuilder([gen], '.custom.dart') // Or SharedPartBuilder([gen], 'my_package') ```