Expression.or
for boolean OR.Expression.negate
for boolean NOT.,
s in FunctionType
s.literalSet
and literalConstSet
.package:built_value
.=
instead of :
for named parameter default values.new
keyword will not be used in generated code.const
keyword will be omitted when it can be inferred.DartEmitter
to order directives.DartEmitter
added a startConstCode
function to track the creation of constant expression trees.BinaryExpression
added the final bool isConst
field.<3.0.0
.Expression.asA
is now wrapped with parenthesis so that further calls may be made on it as an expression.Expression.asA
for creating explicit casts:void main() { test('should emit an explicit cast', () { expect( refer('foo').asA(refer('String')), equalsDart('foo as String'), ); }); }
code_builder
to crash due to build_runner
trying to import our private builder (in tool/
). Sorry for the inconvenience.source_gen: ^0.7.5
.built_value
5.1.0.literalNum
function.literal
supports a Map
.Constructor.lambda
for factory
constructors.Using equalsDart
no longer formats automatically with dartfmt
.
Removed deprecated Annotation
and File
classes.
Method.lambda
is inferred based on Method.body
where possible and now defaults to null
.
equalTo
, notEqualTo
, greaterThan
, lessThan
, greateOrEqualTo
, and lessOrEqualTo
to Expression
.equalsDart
and expecting dartfmt
by default is deprecated. This requires this package to have a direct dependency on specific versions of dart_style
(and transitively analyzer
), which is problematic just for testing infrastructure. To future proof, we've exposed the EqualsDart
class with a format
override:// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; final DartFormatter _dartfmt = new DartFormatter(); String _format(String source) { try { return _dartfmt.format(source); } on FormatException catch (_) { return _dartfmt.formatStatement(source); } } /// Should be invoked in `main()` of every test in `test/**_test.dart`. void useDartfmt() => EqualsDart.format = _format;
Expression.isA
and Expression.isNotA
:void main() { test('should emit an is check', () { expect( refer('foo').isA(refer('String')), equalsDart('foo is String'), ); }); }
Annotation
. It is now legal to simply pass any Expression
as a metadata annotation to Class
, Method
, Field,
and Parameter
. In 3.0.0
, the Annotation
class will be completely removed:void main() { test('should create a class with a annotated constructor', () { expect( new Class((b) => b ..name = 'Foo' ..constructors.add( new Constructor((b) => b..annotations.add(refer('deprecated'))))), equalsDart(r''' class Foo { @deprecated Foo(); } '''), ); }); }
Method.lambda
and Constructor.lambda
. If not explicitly provided and the body of the function originated from an Expression
then lambda
is inferred to be true. This is not a breaking change yet, as it requires an explicit null
value. In 3.0.0
this will be the default:void main() { final animal = new Class((b) => b ..name = 'Animal' ..extend = refer('Organism') ..methods.add(new Method.returnsVoid((b) => b ..name = 'eat' // In 3.0.0, this may be omitted and still is inferred. ..lambda = null ..body = refer('print').call([literalString('Yum!')]).code))); final emitter = new DartEmitter(); print(new DartFormatter().format('${animal.accept(emitter)}')); }
nullSafeProperty
to Expression
to access properties with ?.
conditional
to Expression
to use the ternary operator ? :
positionalArguments
accept Iterable<Expression>
FunctionType
as a type
. Reference.type
now returns a Reference
. Note that this change is technically breaking but should not impacts most clients.Imports are prefixed with _i1
rather than _1
which satisfies the lint lowercase_with_underscores
. While not a strictly breaking change you may have to fix/regenerate golden file-like tests. We added documentation that the specific prefix is not considered stable.
Added Expression.index
for accessing the []
operator:
void main() { test('should emit an index operator', () { expect( refer('bar').index(literalTrue).assignVar('foo').statement, equalsDart('var foo = bar[true];'), ); }); test('should emit an index operator set', () { expect( refer('bar') .index(literalTrue) .assign(literalFalse) .assignVar('foo') .statement, equalsDart('var foo = bar[true] = false;'), ); }); }
literalList
accepts an Iterable
argument.
Fixed an NPE when a method had a return type of a FunctionType
:
void main() { test('should create a method with a function type return type', () { expect( new Method((b) => b ..name = 'foo' ..returns = new FunctionType((b) => b ..returnType = refer('String') ..requiredParameters.addAll([ refer('int'), ]))), equalsDart(r''' String Function(int) foo(); '''), ); }); }
We now require the Dart 2.0-dev branch SDK (>= 2.0.0-dev
).
String
literals.String
literals.File
, which is now a redirect to the preferred class, Library
.This helps avoid symbol clashes when used with dart:io
, a popular library. It is now safe to do the following and get full access to the code_builder
API:
import 'dart:io'; import 'package:code_builder/code_builder.dart' hide File;
We will remove File
in 3.0.0
, so use Library
instead.
Re-released without a direct dependency on package:analyzer
!
For users of the 1.x
branch of code_builder
, this is a pretty big breaking change but ultimately is for the better - it's easier to evolve this library now and even add your own builders on top of the library.
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; void main() { final animal = new Class((b) => b ..name = 'Animal' ..extend = refer('Organism') ..methods.add(new Method.returnsVoid((b) => b ..name = 'eat' ..lambda = true ..body = const Code('print(\'Yum\')')))); final emitter = new DartEmitter(); print(new DartFormatter().format('${animal.accept(emitter)}')); }
...outputs...
class Animal extends Organism { void eat() => print('Yum!'); }
Major changes:
built_value
, and have a more consistent, friendly API.DartEmitter
as an example of the built-in visitor/emitter.Code
example below:void main() { var code = new Code('x + y = z'); code.expression; code.statement; }
See the commit log, examples, and tests for full details. While we want to try and avoid breaking changes, suggestions, new features, and incremental updates are welcome!
Added lazySpec
and lazyCode
to lazily create code on visit #145.
BUG FIX: equalsDart
emits the failing source code #147.
BUG FIX: Top-level lambda
Method
s no longer emit invalid code #146.
Added Expression.annotation
and Expression.annotationNamed
.
Added Method.closure
to create an Expression
.
Added FunctionType
.
Added {new|const}InstanceNamed
to Expression
#135.
typeArguments
option to all invocations.Added assign{...}
variants to Expression
#137.
Added .awaited
and .returned
to Expression
#138.
BUG FIX: Block
now implements Code
#136.
BUG FIX: new DartEmitter.scoped()
applies prefixing #139.
Renamed many of the .asFoo(...)
and .toFoo(...)
methods to single getter:
asCode()
to code
asStatement()
to statement
toExpression()
to expression
Moved {new|const}Instance{[Named]}
from Expression
to Reference
.
Upgraded build_runner
from ^0.3.0
to >=0.4.0 <0.6.0
.
Upgraded build_value{_generator}
from ^1.0.0
to >=2.0.0 <5.0.0
.
Upgraded source_gen
from >=0.5.0 <0.7.0
to ^0.7.0
.
Added MethodModifier
to allow emit a Method
with async|async*|sync*
.
Added show|hide
to Directive
.
Added Directive.importDeferredAs
.
Added a new line character after emitting some types (class, method, etc).
Added refer
as a short-hand for new Reference(...)
.
Reference
now implements Expression
.Added many classes/methods for writing bodies of Code
fluently:
Expression
LiteralExpression
literal
literalNull
literalBool
literalTrue
literalFalse
literalNum
literalString
literalList
and literalConstList
literalMap
and literalConstMap
const Code(staticString)
const Code.scope((allocate) => '')
Removed SimpleSpecVisitor
(it was unused).
Removed implements Reference
from Method
and Field
; not a lot of value.
SpecVisitor<T>
's methods all have an optional [T context]
parameter now.
StringBuffer
s.equalsDart
removes insignificant white space before comparing results.
Reference.localScope
. Just use Reference(symbol)
now.Reference
instead of an explicit TypeReference
in most APIs.toType()
is performed for you as part the emitter processfinal animal = new Class((b) => b ..name = 'Animal' // Used to need a suffix of .toType(). ..extend = const Reference('Organism') ..methods.add(new Method.returnsVoid((b) => b ..name = 'eat' ..lambda = true ..body = new Code((b) => b..code = 'print(\'Yum\')'))));
<2.0.0-dev.infinity
)Class
as a TypeReference
.dart2js
, which is now tested on travis.package:analyzer
.built_value
).isInstanceOf
to ExpressionBuilder
, which performs an is
check:expect( reference('foo').isInstanceOf(_barType), equalsSource('foo is Bar'), );
pkg/analyzer
and pkg/func
.package:dart_style
.First full release. At this point all changes until 2.0.0
will be backwards compatible (new features) or bug fixes that are not breaking. This doesn't mean that the entire Dart language is buildable with our API, though.
Contributions are welcome.
uri
in ImportBuilder
, ExportBuilder
, and Part[Of]Builder
.ExpressionBuilder#ternary
.TypeDefBuilder
.FunctionParameterBuilder
.asAbstract
to various MethodBuilder
constructors.PartBuilder
to PartOfBuilder
.PartBuilder
, to represent part '...dart'
directives.HasAnnotations
interface to all library/part/directive builders.asFactory
and asConst
to ConstructorBuilder
.ConstructorBuilder.redirectTo
for a redirecting factory constructor.name
getter to ReferenceBuilder
.''
) is equivalent to null
(default).'''
.asThrow
to ExpressionBuilder
.FieldBuilder
from being used at the top-level.genericTypes
parameter for ExpressionBuilder#invoke
:expect( explicitThis.invoke('doThing', [literal(true)], genericTypes: [ lib$core.bool, ]), equalsSource(r''' this.doThing<bool>(true) '''), );
castAs
method to ExpressionBuilder
:expect( literal(1.0).castAs(lib$core.num), equalsSource(r''' 1.0 as num '''), );
namedNewInstance
and namedConstInstance
, replaced with constructor:
:expect( reference('Foo').newInstance([], constructor: 'other'), equalsSource(r''' new Foo.other() '''), );
named
parameter to namedArguments
:expect( reference('doThing').call( [literal(true)], namedArguments: { 'otherFlag': literal(false), }, ), equalsSource(r''' doThing(true, otherFlag: false) '''), );
Avoid creating symbols that can collide with the Dart language:
MethodModifier.async
-> MethodModifier.asAsync
MethodModifier.asyncStar
-> MethodModifier.asAsyncStar
MethodModifier.syncStar
-> MethodModifier.asSyncStar
switch
statementsnew ExpressionBuilder.raw(...)
new StatemnetBuilder.raw(...)
This should help cover any cases not covered with builders today.
ClassBuilder
and TypeBuilder
as an expression[]
operator on an expressionExpressionBuilder.asAssign
to always take an ExpressionBuilder
as target and removed the value
property. Most changes are pretty simple, and involve just using reference(...)
. For example:literal(true).asAssign(reference('flag'))
... emits flag = true
.
async
, sync
, sync*
functionsasAwait
, asYield
, asYieldStar
toExportBuilder
and toImportBuilder
to types and referencesreturn
statements and named constructor invocations.while
and do {} while
loop supportfor
and for-in
supportname
getter for ParameterBuilder
MethodBuilder.closure
emits properly as a top-level function// main() {} method('main')
// () => false new MethodBuilder.closure(returns: literal(false));
pkg/analyzer
.TypeBuilder
:importFrom
becomes a named, not positional argument, and the named argument genericTypes
is added (Iterable<TypeBuilder>
).
// List<String> new TypeBuilder('List', genericTypes: [reference('String')])
ReferenceBuilder
:// List<String> reference('List').toTyped([reference('String')])
ReferenceBuilder.buildAst
was not implementedand
and or
methods to ExpressionBuilder
:// true || false literal(true).or(literal(false)); // true && false literal(true).and(literal(false));
MethodBuilder.closure
:// () => true new MethodBuilder.closure( returns: literal(true), returnType: lib$core.bool, )
returnVoid
to well, return;
new LibraryBuilder()..addMember(literal(false).asConst('foo'))
target
when using asAssign
:// Outputs bank.bar = goldBar reference('goldBar').asAssign('bar', target: reference('bank'))
// Outputs foo..doThis()..doThat() reference('foo').cascade((c) => <ExpressionBuilder> [ c.invoke('doThis', []), c.invoke('doThat', []), ]);
// foo.bar reference('foo').property('bar');
show
and hide
support to ImportBuilder
deferred
support to ImportBuilder
ExportBuilder
list
and map
literals that support generic typesScope
and change toAst
to support itNow your entire AST tree can be scoped and import directives automatically added to a LibraryBuilder
for you if you use LibraryBuilder.scope
.