decorator_gen 0.5.0 copy "decorator_gen: ^0.5.0" to clipboard
decorator_gen: ^0.5.0 copied to clipboard

Automatically generates code for the decorator pattern in Dart by annotating classes.

Pub Package Coverage Status

Decorator Gen #

A Dart code generator that automatically creates the decorator pattern for your Dart code.

The builder generates code if it finds classes with annotations from the decorator_annotation package.

Features #

  • Generate complete decorator classes with a single @Decorator() annotation
    • Forward all public members of the source class
    • Works with generics, records, nested types, etc.
    • Object methods can be forwarded globally or per class

Installation #

Add the following to your pubspec.yaml:

dependencies:
  decorator_annotation: ^latest

dev_dependencies:
  decorator_gen: ^latest
  build_runner: any

Usage #

1. Annotate Your Class And Include The Part Directive #

import 'package:decorator_annotation/decorator_annotation.dart';

part 'example.g.dart'; // This part directive is necessary for code generation

@Decorator() // Add this annotation to generate a decorator for this class
class MyService {
  final String name;
  
  MyService(this.name);
  
  String greet(String message) => 'Hello $message from $name';
  
  Future<String> asyncOperation() async {
    await Future.delayed(const Duration(seconds: 1));
    return 'Completed';
  }
}

// Generates: MyServiceDecorator in example.g.dart
class MyServiceDecorator implements MyService {
  final MyService myService;

  MyServiceDecorator({required this.myService});

  @override
  String greet(String message) {
    return myService.greet(message);
  }

  @override
  Future<String> asyncOperation() {
    return myService.asyncOperation();
  }

  @override
  String get name => myService.name;
}

2. Run Code Generation #

dart run build_runner build

3. Use Your Generated Decorator #

// Generated: MyServiceDecorator
class LoggingServiceDecorator extends MyServiceDecorator {
  LoggingServiceDecorator({required super.myService});

  @override
  String greet(String message) {
    print('Calling greet with: $message');
    final result = super.greet(message);
    print('greet returned: $result');
    return result;
  }

  @override
  Future<String> asyncOperation() async {
    print('Starting async operation');
    final result = await super.asyncOperation();
    print('Async operation completed');
    return result;
  }
}

// Usage
final service = MyService('TestService');
final decorator = LoggingServiceDecorator(myService: service);
print(decorator.greet('World')); // Logs and returns result

Supported Features #

Generics (with Bounds) #

@Decorator()
class GenericService<T extends Comparable<T>> {
  T process(T value) => /* implementation */
}
// Generates: GenericServiceDecorator<T extends Comparable<T>>

Mixins #

mixin SimpleMixin {
  void mixinMethod() => /* implementation */
}

@Decorator()
class MixinService with SimpleMixin {
  void ownMethod() => /* implementation */
}
// Generates: MixinServiceDecorator having mixinMethod and ownMethod 

Object methods and Annotation-level Forwarding #

You can control which Object methods are forwarded per class using parameters on the @Decorator() annotation:

@Decorator(
  forwardToString: true,         // forward toString (default: true)
  forwardEquals: false,          // do NOT forward == (default: true)
  forwardHashCode: true,         // forward hashCode (default: true)
  forwardRuntimeType: true,      // forward runtimeType (default: false)
  forwardNoSuchMethod: false,    // do NOT forward noSuchMethod (default: false)
)
class CustomService {
  final String name;
  CustomService(this.name);

  @override
  String toString() => 'CustomService($name)';
  @override
  bool operator ==(Object other) => other is CustomService && other.name == name;
  @override
  int get hashCode => name.hashCode;
  @override
  Type get runtimeType => super.runtimeType;
  @override
  dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
  String processData(String data) => 'Processing: $data';
}

// Only toString, hashCode, and runtimeType will be forwarded in the generated decorator.

Operators #

@Decorator()
class OperatorService {
  int operator +(int other) => /* implementation */
  bool operator ==(Object other) => /* implementation */
  int operator [](int index) => /* implementation */
}
// Generates: OperatorServiceDecorator with forwarded operators

Parameters (positional, named, optional, combined) #

@Decorator()
class ParameterService {
  void positionalNamed(int a, {String? b, double c = 0.0}) => /* implementation */
  void positionalOptional(int a, [String? b, double c = 0.0]) => /* implementation */
}
// Generates: ParameterServiceDecorator with all parameter types handled

Records #

@Decorator()
class RecordService {
  (int, String) getTuple() => (42, 'Hello World!');
  
  // With named fields
  void setRecord(({int foo, String bar}) record) => /* implementation */
}
// Generates: RecordServiceDecorator with tuple handling

Forwarding Object Methods: Global Defaults #

The generator can generate code that forwards the Object methods.

The following Object methods are included by default:

  • toString
  • ==
  • hashCode

The following Object methods are excluded by default:

  • runtimeType
  • noSuchMethod

You can customize the global default behavior in your build.yaml file:

targets:
  $default:
    builders:
      decorator_gen:
        enabled: true
        options:
          forward_object_method:
            toString: true # Defaults to true
            "==": true # Defaults to true
            hashCode: true # Defaults to true
            runtimeType: false # Defaults to false
            noSuchMethod: false # Defaults to false

FAQ #

Private members #

Private members (those starting with _) are included in the generated decorators. This is required by the Dart compiler. All accessible members must be implemented.

Static members #

Static members are not included in the generated decorators.

Contributing #

Contributions are welcome! Please feel free to submit a Pull Request.

License #

This project is licensed under the MIT License.

0
likes
150
points
66
downloads

Publisher

unverified uploader

Weekly Downloads

Automatically generates code for the decorator pattern in Dart by annotating classes.

Repository (GitHub)
View/report issues

Topics

#build-runner #codegen #decorator #design-pattern

Documentation

API reference

License

MIT (license)

Dependencies

analyzer, build, decorator_annotation, source_gen

More

Packages that depend on decorator_gen