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/code_builder.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest]
sdk: [3.6.0, dev]
sdk: [3.7.0, dev]
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c
Expand Down
12 changes: 9 additions & 3 deletions pkgs/code_builder/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
## 4.10.2-wip
## 4.11.0

* Export `SpecVisitor`, `ClosureExpression`, `LiteralMapExpression`
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI (@devoncarew) exporting "leaked" types.

`LiteralRecordExpression`, `LiteralSetExpression` types.
* Support `Expression.newInstanceNamed` with empty name
* Consistently add blank lines between `=>` in class-like definitions.
* Fixed bug: Fields declared with `static` and `external` now produce code with
correct order
* Upgrade `dart_style` and `source_gen` to remove `package:macros` dependency.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to document updates to dev dependencies

* Require Dart `^3.6.0` due to the upgrades.
* Require `built_collection: ^5.1.1`
* Require `built_value: ^8.10.1`
* Require `collection: ^1.19.0`
* Require `matcher: ^0.12.16+1`
* Require `meta: ^1.16.0`
* Require `sdk: ^3.7.0`

## 4.10.1

Expand Down
1 change: 1 addition & 0 deletions pkgs/code_builder/analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ linter:
- prefer_expression_function_bodies
- prefer_final_locals
- unnecessary_await_in_return
- unnecessary_ignore
- use_string_buffers
77 changes: 50 additions & 27 deletions pkgs/code_builder/example/example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,20 @@ void main() {
/// }
/// ```
String animalClass() {
final animal = Class((b) => b
..name = 'Animal'
..extend = refer('Organism')
..methods.add(Method.returnsVoid((b) => b
..name = 'eat'
..body = refer('print').call([literalString('Yum!')]).code)));
final animal = Class(
(b) =>
b
..name = 'Animal'
..extend = refer('Organism')
..methods.add(
Method.returnsVoid(
(b) =>
b
..name = 'eat'
..body = refer('print').call([literalString('Yum!')]).code,
),
),
);
return _dartfmt.format('${animal.accept(DartEmitter())}');
}

Expand All @@ -43,14 +51,20 @@ String animalClass() {
/// ```
String scopedLibrary() {
final methods = [
Method((b) => b
..body = const Code('')
..name = 'doThing'
..returns = refer('Thing', 'package:a/a.dart')),
Method((b) => b
..body = const Code('')
..name = 'doOther'
..returns = refer('Other', 'package:b/b.dart')),
Method(
(b) =>
b
..body = const Code('')
..name = 'doThing'
..returns = refer('Thing', 'package:a/a.dart'),
),
Method(
(b) =>
b
..body = const Code('')
..name = 'doOther'
..returns = refer('Other', 'package:b/b.dart'),
),
];
final library = Library((b) => b.body.addAll(methods));
return _dartfmt.format('${library.accept(DartEmitter.scoped())}');
Expand All @@ -68,19 +82,28 @@ String scopedLibrary() {
/// ```
String jsonEnum() {
final values = <EnumValue>[
EnumValue((b) => b
..name = 'metric'
..annotations.addAll([
refer('JsonKey').call([literalString('m')])
])),
EnumValue((b) => b
..name = 'imperial'
..annotations.addAll([
refer('JsonKey').call([literalString('i')])
])),
EnumValue(
(b) =>
b
..name = 'metric'
..annotations.addAll([
refer('JsonKey').call([literalString('m')]),
]),
),
EnumValue(
(b) =>
b
..name = 'imperial'
..annotations.addAll([
refer('JsonKey').call([literalString('i')]),
]),
),
];
final e = Enum((b) => b
..name = 'Unit'
..values.addAll(values));
final e = Enum(
(b) =>
b
..name = 'Unit'
..values.addAll(values),
);
return _dartfmt.format('${e.accept(DartEmitter())}');
}
5 changes: 5 additions & 0 deletions pkgs/code_builder/lib/code_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export 'src/specs/enum.dart'
export 'src/specs/expression.dart'
show
BinaryExpression,
ClosureExpression,
CodeExpression,
Expression,
ExpressionEmitter,
Expand All @@ -25,6 +26,9 @@ export 'src/specs/expression.dart'
InvokeExpressionType,
LiteralExpression,
LiteralListExpression,
LiteralMapExpression,
LiteralRecordExpression,
LiteralSetExpression,
ParenthesizedExpression,
ToCodeExpression,
declareConst,
Expand Down Expand Up @@ -70,3 +74,4 @@ export 'src/specs/type_function.dart' show FunctionType, FunctionTypeBuilder;
export 'src/specs/type_record.dart' show RecordType, RecordTypeBuilder;
export 'src/specs/type_reference.dart' show TypeReference, TypeReferenceBuilder;
export 'src/specs/typedef.dart' show TypeDef, TypeDefBuilder;
export 'src/visitors.dart' show SpecVisitor;
5 changes: 2 additions & 3 deletions pkgs/code_builder/lib/src/allocator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ class _PrefixedAllocator implements Allocator {
int _nextKey() => _keys++;

@override
Iterable<Directive> get imports => _imports.keys.map(
(u) => Directive.import(u, as: '_i${_imports[u]}'),
);
Iterable<Directive> get imports =>
_imports.keys.map((u) => Directive.import(u, as: '_i${_imports[u]}'));
}
86 changes: 57 additions & 29 deletions pkgs/code_builder/lib/src/emitter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,21 @@ class DartEmitter extends Object
/// May specify an [Allocator] to use for references and imports,
/// otherwise uses [Allocator.none] which never prefixes references and will
/// not automatically emit import directives.
DartEmitter(
{this.allocator = Allocator.none,
this.orderDirectives = false,
bool useNullSafetySyntax = false})
: _useNullSafetySyntax = useNullSafetySyntax;
DartEmitter({
this.allocator = Allocator.none,
this.orderDirectives = false,
bool useNullSafetySyntax = false,
}) : _useNullSafetySyntax = useNullSafetySyntax;

/// Creates a new instance of [DartEmitter] with simple automatic imports.
factory DartEmitter.scoped(
{bool orderDirectives = false, bool useNullSafetySyntax = false}) =>
DartEmitter(
allocator: Allocator.simplePrefixing(),
orderDirectives: orderDirectives,
useNullSafetySyntax: useNullSafetySyntax);
factory DartEmitter.scoped({
bool orderDirectives = false,
bool useNullSafetySyntax = false,
}) => DartEmitter(
allocator: Allocator.simplePrefixing(),
orderDirectives: orderDirectives,
useNullSafetySyntax: useNullSafetySyntax,
);

static bool _isLambdaBody(Code? code) =>
code is ToCodeExpression && !code.isStatement;
Expand Down Expand Up @@ -145,13 +147,17 @@ class DartEmitter extends Object
out
..write(' with ')
..writeAll(
spec.mixins.map<StringSink>((m) => m.type.accept(this)), ',');
spec.mixins.map<StringSink>((m) => m.type.accept(this)),
',',
);
}
if (spec.implements.isNotEmpty) {
out
..write(' implements ')
..writeAll(
spec.implements.map<StringSink>((m) => m.type.accept(this)), ',');
spec.implements.map<StringSink>((m) => m.type.accept(this)),
',',
);
}
out.write(' {');
for (var c in spec.constructors) {
Expand Down Expand Up @@ -188,7 +194,9 @@ class DartEmitter extends Object
out
..write(' implements ')
..writeAll(
spec.implements.map<StringSink>((m) => m.type.accept(this)), ',');
spec.implements.map<StringSink>((m) => m.type.accept(this)),
',',
);
}
out.write(' {');
for (var f in spec.fields) {
Expand All @@ -201,8 +209,11 @@ class DartEmitter extends Object
}

@override
StringSink visitConstructor(Constructor spec, String clazz,
[StringSink? output]) {
StringSink visitConstructor(
Constructor spec,
String clazz, [
StringSink? output,
]) {
output ??= StringBuffer();
spec.docs.forEach(output.writeln);
for (var a in spec.annotations) {
Expand Down Expand Up @@ -342,7 +353,9 @@ class DartEmitter extends Object
out
..write(' implements ')
..writeAll(
spec.implements.map<StringSink>((m) => m.type.accept(this)), ',');
spec.implements.map<StringSink>((m) => m.type.accept(this)),
',',
);
}

out.writeln(' {');
Expand All @@ -360,7 +373,9 @@ class DartEmitter extends Object
}

void _visitRepresentationDeclaration(
RepresentationDeclaration spec, StringSink out) {
RepresentationDeclaration spec,
StringSink out,
) {
spec.docs.forEach(out.writeln);
for (var a in spec.annotations) {
visitAnnotation(a, out);
Expand Down Expand Up @@ -509,7 +524,8 @@ class DartEmitter extends Object
Directive? previous;
if (directives.any((d) => d.as?.startsWith('_') ?? false)) {
output.writeln(
'// ignore_for_file: no_leading_underscores_for_library_prefixes');
'// ignore_for_file: no_leading_underscores_for_library_prefixes',
);
}
for (final directive in directives) {
if (_newLineBetween(orderDirectives, previous, directive)) {
Expand Down Expand Up @@ -543,15 +559,17 @@ class DartEmitter extends Object
out.write('>');
}
out.write('(');
final needsTrailingComma = spec.requiredParameters.length +
final needsTrailingComma =
spec.requiredParameters.length +
spec.optionalParameters.length +
spec.namedRequiredParameters.length +
spec.namedParameters.length >
1;
visitAll<Reference>(spec.requiredParameters, out, (spec) {
spec.accept(this, out);
});
final hasNamedParameters = spec.namedRequiredParameters.isNotEmpty ||
final hasNamedParameters =
spec.namedRequiredParameters.isNotEmpty ||
spec.namedParameters.isNotEmpty;
if (spec.requiredParameters.isNotEmpty &&
(needsTrailingComma ||
Expand Down Expand Up @@ -610,8 +628,9 @@ class DartEmitter extends Object
out.write(', ');
}
out.write('{');
visitAll<MapEntry<String, Reference>>(spec.namedFieldTypes.entries, out,
(entry) {
visitAll<MapEntry<String, Reference>>(spec.namedFieldTypes.entries, out, (
entry,
) {
entry.value.accept(this, out);
out.write(' ${entry.key}');
});
Expand Down Expand Up @@ -811,8 +830,10 @@ class DartEmitter extends Object
}

@override
StringSink visitTypeParameters(Iterable<Reference> specs,
[StringSink? output]) {
StringSink visitTypeParameters(
Iterable<Reference> specs, [
StringSink? output,
]) {
output ??= StringBuffer();
if (specs.isNotEmpty) {
output
Expand All @@ -836,13 +857,17 @@ class DartEmitter extends Object
out
..write(' with ')
..writeAll(
spec.mixins.map<StringSink>((m) => m.type.accept(this)), ', ');
spec.mixins.map<StringSink>((m) => m.type.accept(this)),
', ',
);
}
if (spec.implements.isNotEmpty) {
out
..write(' implements ')
..writeAll(
spec.implements.map<StringSink>((m) => m.type.accept(this)), ', ');
spec.implements.map<StringSink>((m) => m.type.accept(this)),
', ',
);
}
out.write(' { ');
for (var v in spec.values) {
Expand All @@ -855,15 +880,18 @@ class DartEmitter extends Object
out.write('.${v.constructorName}');
}
visitTypeParameters(v.types.map((r) => r.type), out);
final takesArguments = v.constructorName != null ||
final takesArguments =
v.constructorName != null ||
v.arguments.isNotEmpty ||
v.namedArguments.isNotEmpty;
if (takesArguments) {
out.write('(');
}
if (v.arguments.isNotEmpty) {
out.writeAll(
v.arguments.map<StringSink>((arg) => arg.accept(this)), ', ');
v.arguments.map<StringSink>((arg) => arg.accept(this)),
', ',
);
}
if (v.arguments.isNotEmpty && v.namedArguments.isNotEmpty) {
out.write(', ');
Expand Down
14 changes: 4 additions & 10 deletions pkgs/code_builder/lib/src/matchers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ String _dart(Spec spec, DartEmitter emitter) =>
/// Both [source] and the result emitted from the compared [Spec] are formatted
/// with [EqualsDart.format]. A plain [DartEmitter] is used by default and may
/// be overridden with [emitter].
Matcher equalsDart(
String source, [
DartEmitter? emitter,
]) =>
Matcher equalsDart(String source, [DartEmitter? emitter]) =>
EqualsDart._(EqualsDart._format(source), emitter ?? DartEmitter());

/// Implementation detail of using the [equalsDart] matcher.
Expand Down Expand Up @@ -59,12 +56,9 @@ class EqualsDart extends Matcher {
bool verbose,
) {
final actualSource = _dart(item, _emitter);
return equals(_expectedSource).describeMismatch(
actualSource,
mismatchDescription,
matchState,
verbose,
);
return equals(
_expectedSource,
).describeMismatch(actualSource, mismatchDescription, matchState, verbose);
}

@override
Expand Down
Loading