Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/draft-builder-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
- name: Set up Dart
uses: dart-lang/setup-dart@v1
with:
sdk: 3.7.0
sdk: 3.10.1

- name: Install dependencies
working-directory: ${{ env.PACKAGE_PATH }}
Expand Down
64 changes: 64 additions & 0 deletions .github/workflows/draft-builder-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Test draft_builder

on:
pull_request:
branches:
- main
paths:
- packages/draft_builder/**
- .github/workflows/draft-builder-test.yml

permissions:
contents: read

jobs:
tests:
name: Run tests
runs-on: ubuntu-latest
defaults:
run:
working-directory: packages/draft_builder
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Dart
uses: dart-lang/setup-dart@v1
with:
sdk: 3.10.1

- name: Install dependencies
run: dart pub get

- name: Run generator
run: dart run build_runner build --delete-conflicting-outputs

- name: Run tests
run: dart test

lint:
name: Run lint checks
runs-on: ubuntu-latest
defaults:
run:
working-directory: packages/draft_builder
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Dart
uses: dart-lang/setup-dart@v1
with:
sdk: 3.10.1

- name: Install dependencies
run: dart pub get

- name: Run generator
run: dart run build_runner build --delete-conflicting-outputs

- name: Verify formatting
run: dart format --output none --set-exit-if-changed .

- name: Run analyzer
run: dart analyze .
55 changes: 39 additions & 16 deletions packages/draft_builder/lib/src/generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,9 @@ String _generateParameterSignature(List<FormalParameterElement> parameters) {

final parts = <String>[];
if (positionalRequired.isNotEmpty) parts.add(positionalRequired.join(', '));
if (positionalOptional.isNotEmpty) parts.add('[${positionalOptional.join(', ')}]');
if (positionalOptional.isNotEmpty) {
parts.add('[${positionalOptional.join(', ')}]');
}
if (named.isNotEmpty) parts.add('{${named.join(', ')}}');

return parts.join(', ');
Expand All @@ -366,11 +368,16 @@ String _generateArgumentList(List<FormalParameterElement> parameters) {
}

/// Helper to generate constructor parameter signature for draft class based on original constructor.
String _generateDraftConstructorSignature(ConstructorElement? constructor, List<FieldElement> fields) {
String _generateDraftConstructorSignature(
ConstructorElement? constructor,
List<FieldElement> fields,
) {
if (constructor == null) {
// Fallback to named parameters if no constructor found
final processors = fields.map(_processorFor).toList();
final params = processors.map((p) => p.generateConstructorParameter()).join(', ');
final params = processors
.map((p) => p.generateConstructorParameter())
.join(', ');
return params.isNotEmpty ? '{$params}' : '';
}

Expand All @@ -382,10 +389,10 @@ String _generateDraftConstructorSignature(ConstructorElement? constructor, List<
// Only include parameters that correspond to fields we're processing
final field = fields.where((f) => f.name == p.name).firstOrNull;
if (field == null) continue;

final processor = _processorFor(field);
final paramDecl = processor.generateConstructorParameter();

if (p.isNamed) {
named.add(paramDecl);
} else if (p.isOptionalPositional) {
Expand All @@ -407,14 +414,19 @@ String _generateDraftConstructorSignature(ConstructorElement? constructor, List<

final parts = <String>[];
if (positional.isNotEmpty) parts.add(positional.join(', '));
if (optionalPositional.isNotEmpty) parts.add('[${optionalPositional.join(', ')}]');
if (optionalPositional.isNotEmpty) {
parts.add('[${optionalPositional.join(', ')}]');
}
if (named.isNotEmpty) parts.add('{${named.join(', ')}}');

return parts.join(', ');
}

/// Helper to generate argument list for save() method based on original constructor.
String _generateSaveArgumentList(ConstructorElement? constructor, List<FieldElement> fields) {
String _generateSaveArgumentList(
ConstructorElement? constructor,
List<FieldElement> fields,
) {
if (constructor == null) {
// Fallback to named arguments
return fields.map((f) => '${f.name}: ${f.name}').join(', ');
Expand All @@ -426,7 +438,7 @@ String _generateSaveArgumentList(ConstructorElement? constructor, List<FieldElem
for (final p in constructor.formalParameters) {
final field = fields.where((f) => f.name == p.name).firstOrNull;
if (field == null) continue;

if (p.isNamed) {
named.add('${p.name}: ${field.name}');
} else {
Expand All @@ -442,7 +454,10 @@ String _generateSaveArgumentList(ConstructorElement? constructor, List<FieldElem
}

/// Helper to generate argument list for draft() method based on original constructor.
String _generateDraftArgumentList(ConstructorElement? constructor, List<FieldElement> fields) {
String _generateDraftArgumentList(
ConstructorElement? constructor,
List<FieldElement> fields,
) {
if (constructor == null) {
// Fallback to named arguments
return fields.map((f) => '${f.name}: this.${f.name}').join(', ');
Expand All @@ -454,7 +469,7 @@ String _generateDraftArgumentList(ConstructorElement? constructor, List<FieldEle
for (final p in constructor.formalParameters) {
final field = fields.where((f) => f.name == p.name).firstOrNull;
if (field == null) continue;

if (p.isNamed) {
named.add('${p.name}: this.${field.name}');
} else {
Expand Down Expand Up @@ -522,14 +537,22 @@ class DraftGenerator extends GeneratorForAnnotation<Draft> {
.join('\n');

// Find the original constructor to get parameter structure
final originalConstructor = classElement.constructors
.where((c) => constructorName == null
? (c.name?.isEmpty ?? true)
: c.name == constructorName)
.firstOrNull ?? classElement.unnamedConstructor;
final originalConstructor =
classElement.constructors
.where(
(c) =>
constructorName == null
? (c.name?.isEmpty ?? true)
: c.name == constructorName,
)
.firstOrNull ??
classElement.unnamedConstructor;

// Constructor parameters and initializers.
final constructorParams = _generateDraftConstructorSignature(originalConstructor, fields);
final constructorParams = _generateDraftConstructorSignature(
originalConstructor,
fields,
);
final initializerList = processors
.map((p) => p.generateConstructorInitializer())
.where((init) => init.trim().isNotEmpty)
Expand Down