SpecVisitor, ClosureExpression, LiteralMapExpression LiteralRecordExpression, LiteralSetExpression types.Expression.newInstanceNamed with empty name=> in class-like definitions.static and external now produce code with correct orderbuilt_collection: ^5.1.1built_value: ^8.10.1collection: ^1.19.0matcher: ^0.12.16+1meta: ^1.16.0sdk: ^3.7.0^3.5.0dart_style 2.3.7.dart-lang/tools monorepo.Library.docs to support emitting doc comments on libraries.RepresentationDeclaration and RepresentationDeclarationBuilder so they can be used when generating extension types.dart_style 2.3.4.Library.generatedByComment to support emitting ‘generated by’ comments.Expression.operatorSubtractExpression.operatorSubstractExpression.operatorIntDivideExpression.operatorUnaryPrefixIncrementExpression.operatorUnaryPostfixIncrementExpression.operatorUnaryMinusExpression.operatorUnaryPrefixDecrementExpression.operatorUnaryPostfixDecrementExpression.operatorBitwiseAndExpression.operatorBitwiseOrExpression.operatorBitwiseXorExpression.operatorUnaryBitwiseComplementExpression.operatorShiftLeftExpression.operatorShiftRightExpression.operatorShiftRightUnsignedExpression.addAssignExpression.subtractAssignExpression.multiplyAssignExpression.divideAssignExpression.intDivideAssignExpression.euclideanModuloAssignExpression.shiftLeftAssignExpression.shiftRightAssignExpression.shiftRightUnsignedAssignExpression.bitwiseAndAssignExpression.bitwiseXorAssignExpression.bitwiseOrAssignExpression through literal without an exception.>=3.0.0.enum classesExpression.parenthesized to manually wrap an expression in parenthesis.literalSpread and literalNullSafeSpread to support adding spreads to literalMap.void main() { // Creates a map // { // ...one, // 2: two, // ...?three, // } final map = literalMap({ literalSpread(): refer('one'), 2: refer('two'), literalNullSafeSpread(): refer('three'), }); }
allocator argument relates to imports in the DartEmitter constructor doc.ignore_for_file analyzer directive comments.enum classes.late keyword when using null safety syntax.const when assigning to a declareConst variable.assignVar, assignConst, and assignFinal.package:lints recommended set. The lint, no_leading_underscores_for_library_prefixes is most useful for hand edited code where the appearance of a private name that is already not visible outside the library is confusing.Expression.assign, ifNullThen, and assignNullAware which had the argument and receiver flipped.declareConst, declareFinal, and declareVar to replace Expression.assignConst, assignFinal, and assignVar. Add support for late variables with the declare* utilities.ParameterBuilder.toSuper so support super formal parameters language feature.Expression.spread for the spread operator ....Expression.nullChecked to add a null assertion operator.mixins.Expression.nullSafeSpread for the null aware spread operator ...?.Library can now be annotated.DartEmitter constructor to use named optional parameters.ParenthesizedExpression and ExpressionVisitor.visitParenthesizedExpression.Method.genericClosure.extension methods.built_value to allow null safe migrated version.const factory constructors.equalsDart. https://github.com/dart-lang/code_builder/issues/293Expression.thrown for throwing an expression.FunctionType.isNullable.>=2.7.0 <3.0.0.?? null-aware operator... cascade assignment operator.part directive.TypeReference.isNullable.DartEmitter to emit nullable types with trailing ? characters.2.6.0.Expression.or for boolean OR.Expression.negate for boolean NOT.,s in FunctionTypes.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 Methods 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 codeasStatement() to statementtoExpression() to expressionMoved {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:
ExpressionLiteralExpressionliteralliteralNullliteralBoolliteralTrueliteralFalseliteralNumliteralStringliteralList and literalConstListliteralMap and literalConstMapconst 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.
StringBuffers.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 backward 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.asAsyncMethodModifier.asyncStar -> MethodModifier.asAsyncStarMethodModifier.syncStar -> MethodModifier.asSyncStarswitch 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, asYieldStartoExportBuilder and toImportBuilder to types and referencesreturn statements and named constructor invocations.while and do {} while loop supportfor and for-in supportname getter for ParameterBuilderMethodBuilder.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 a 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 ImportBuilderdeferred support to ImportBuilderExportBuilderlist 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.