Skip to content
This repository was archived by the owner on Apr 8, 2025. It is now read-only.

Beta release fixes and feature. #149

Merged
merged 2 commits into from
Oct 24, 2017
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 2.0.0-beta

* Added `lazySpec` and `lazyCode` to lazily create code on visit [#145](https://github.com/dart-lang/code_builder/issues/145).

* **BUG FIX**: `equalsDart` emits the failing source code [#147](https://github.com/dart-lang/code_builder/issues/147).
* **BUG FIX**: Top-level `lambda` `Method`s no longer emit invalid code [#146](https://github.com/dart-lang/code_builder/issues/146).

## 2.0.0-alpha+3

* Added `Expression.annotation` and `Expression.annotationNamed`.
Expand Down
4 changes: 2 additions & 2 deletions lib/code_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
// BSD-style license that can be found in the LICENSE file.

export 'src/allocator.dart' show Allocator;
export 'src/base.dart' show Spec;
export 'src/base.dart' show lazySpec, Spec;
export 'src/emitter.dart' show DartEmitter;
export 'src/matchers.dart' show equalsDart;
export 'src/specs/annotation.dart' show Annotation, AnnotationBuilder;
export 'src/specs/class.dart' show Class, ClassBuilder;
export 'src/specs/code.dart'
show Block, BlockBuilder, Code, StaticCode, ScopedCode;
show lazyCode, Block, BlockBuilder, Code, StaticCode, ScopedCode;
export 'src/specs/constructor.dart' show Constructor, ConstructorBuilder;
export 'src/specs/directive.dart'
show Directive, DirectiveType, DirectiveBuilder;
Expand Down
2 changes: 2 additions & 0 deletions lib/src/allocator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// 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:path/path.dart' as p;

import 'specs/directive.dart';
import 'specs/reference.dart';

Expand Down
14 changes: 14 additions & 0 deletions lib/src/base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,17 @@ import 'visitors.dart';
abstract class Spec {
R accept<R>(SpecVisitor<R> visitor, [R context]);
}

/// Returns a generic [Spec] that is lazily generated when visited.
Spec lazySpec(Spec Function() generate) => new _LazySpec(generate);

class _LazySpec implements Spec {
final Spec Function() generate;

const _LazySpec(this.generate);

@override
R accept<R>(SpecVisitor<R> visitor, [R context]) {
return generate().accept(visitor, context);
Copy link
Contributor

Choose a reason for hiding this comment

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

This not only generates lazily, but also generates every time it's visited. Is it intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah. We could cache it, but we wouldn't know if the function is stateless or not.

}
}
2 changes: 1 addition & 1 deletion lib/src/emitter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ class DartEmitter extends Object
for (final spec in spec.body) {
body.write(visitSpec(spec));
if (spec is Method && spec.lambda) {
output.write(';');
body.write(';');
}
}
// TODO: Allow some sort of logical ordering.
Expand Down
3 changes: 1 addition & 2 deletions lib/src/matchers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ String _dartfmt(String source) {
source = _formatter.formatStatement(source);
} catch (_) {
// Ignored on purpose, probably not exactly valid Dart code.
} finally {
source = collapseWhitespace(source);
}
return source;
Expand Down Expand Up @@ -54,7 +53,7 @@ class _EqualsDart extends Matcher {
final result = _dart(item, _emitter);
return equals(result).describeMismatch(
_source,
mismatchDescription,
mismatchDescription.add(result),
state,
verbose,
);
Expand Down
36 changes: 33 additions & 3 deletions lib/src/specs/code.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ abstract class Code implements Spec {
abstract class Block implements Built<Block, BlockBuilder>, Code, Spec {
factory Block([void updates(BlockBuilder b)]) = _$Block;

factory Block.of(Iterable<Code> statements) {
return new Block((b) => b..statements.addAll(statements));
}

Block._();

@override
Expand Down Expand Up @@ -111,7 +115,33 @@ abstract class CodeEmitter implements CodeVisitor<StringSink> {
}
}

/// Represents a simple, literal [code] block to be inserted as-is.
/// Represents a code block that requires lazy visiting.
class LazyCode implements Code {
final Spec Function(SpecVisitor) generate;

const LazyCode._(this.generate);

@override
R accept<R>(CodeVisitor<R> visitor, [R context]) {
return generate(visitor).accept(visitor, context);
Copy link
Contributor

Choose a reason for hiding this comment

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

same here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ditto.

}
}

/// Returns a generic [Code] that is lazily generated when visited.
Code lazyCode(Code Function() generate) => new _LazyCode(generate);

class _LazyCode implements Code {
final Code Function() generate;

const _LazyCode(this.generate);

@override
R accept<R>(CodeVisitor<R> visitor, [R context]) {
return generate().accept(visitor, context);
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ditto.

}
}

/// Represents a simple, literal code block to be inserted as-is.
class StaticCode implements Code {
final String code;

Expand All @@ -126,9 +156,9 @@ class StaticCode implements Code {
String toString() => code;
}

/// Represents a [code] block that may require scoping.
/// Represents a code block that may require scoping.
class ScopedCode implements Code {
final String Function(Allocate allocate) code;
final String Function(Allocate) code;

const ScopedCode._(this.code);

Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: code_builder
version: 2.0.0-alpha+3
version: 2.0.0-beta
description: A fluent API for generating Dart code
author: Dart Team <misc@dartlang.org>
homepage: https://github.com/dart-lang/code_builder
Expand Down
41 changes: 31 additions & 10 deletions test/specs/code/statement_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import 'package:test/test.dart';
void main() {
test('should emit a block of code', () {
expect(
new Block((b) => b.statements.addAll([
const Code('if (foo) {'),
const Code(' print(true);'),
const Code('}'),
])),
new Block.of([
const Code('if (foo) {'),
const Code(' print(true);'),
const Code('}'),
]),
equalsDart(r'''
if (foo) {
print(true);
Expand All @@ -23,16 +23,37 @@ void main() {

test('should emit a block of code including expressions', () {
expect(
new Block((b) => b.statements.addAll([
const Code('if (foo) {'),
refer('print')([literalTrue]).statement,
const Code('}'),
])),
new Block.of([
const Code('if (foo) {'),
refer('print')([literalTrue]).statement,
const Code('}'),
]),
equalsDart(r'''
if (foo) {
print(true);
}
'''),
);
});

test('should emit a block of code with lazyily invoked generators', () {
expect(
new Method((b) => b
..name = 'main'
..body = new Block.of([
const Code('if ('),
lazyCode(() => refer('foo').code),
const Code(') {'),
refer('print')([literalTrue]).statement,
const Code('}'),
])),
equalsDart(r'''
main() {
if (foo) {
print(true);
}
}
'''),
);
});
}