Skip to content

Commit

Permalink
Rewrite: 1.0.0-alpha, with full statement support, fluid syntax (#15)
Browse files Browse the repository at this point in the history
* Branch to start v1, a partial rewrite.

* Incremental work.

* Start on new v1

* .

* .

* .

* .

* .

* .

* Another checkpoint.

* Another checkpoint with if statements.

* Next large incremental work.

* Fix docs, more dart core types.

* Add scoping back.

* Add e2e test.

* Update docs, pubspec.

* Address comments.

Address comments and presubmit script.

.

* .

* .
  • Loading branch information
matanlurey committed Oct 27, 2016
1 parent e2c28f2 commit 62d8db1
Show file tree
Hide file tree
Showing 64 changed files with 4,013 additions and 2,578 deletions.
16 changes: 0 additions & 16 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# See https://www.dartlang.org/tools/private-files.html

# Files and directories created by pub
.buildlog
.packages
Expand All @@ -8,23 +6,9 @@
**/build
**/packages

# Files created by dart2js
# (Most Dart developers will use pub build to compile Dart, use/modify these
# rules if you intend to use dart2js directly
# Convention is to use extension '.dart.js' for Dart compiled to Javascript to
# differentiate from explicit Javascript files)
*.dart.js
*.part.js
*.js.deps
*.js.map
*.info.json

# Directory created by dartdoc
doc/api/

# Don't commit pubspec lock file
# (Library packages only! Remove pattern if developing an application package)
pubspec.lock

*.iml
.idea
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ dart:
- dev
- stable

script: ./tool/travis.sh
script: ./tool/presubmit.sh
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 1.0.0-alpha

- Large refactor that makes the library more feature complete.

## 0.1.1

- Add concept of `Scope` and change `toAst` to support it
Expand Down
47 changes: 21 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# code_builder

[![pub package](https://img.shields.io/pub/v/code_builder.svg)](https://pub.dartlang.org/packages/code_builder)
[![Build Status](https://travis-ci.org/dart-lang/code_builder.svg)](https://travis-ci.org/dart-lang/code_builder)
[![Coverage Status](https://coveralls.io/repos/dart-lang/code_builder/badge.svg)](https://coveralls.io/r/dart-lang/code_builder)
[![Coverage Status](https://coveralls.io/repos/github/dart-lang/code_builder/badge.svg?branch=master)](https://coveralls.io/github/dart-lang/code_builder?branch=master)

`code_builder` is a fluent Dart API for generating valid Dart source code.

Expand Down Expand Up @@ -34,10 +35,14 @@ Code builder has a narrow and user-friendly API.
For example creating a class with a method:

```dart
new ClassBuilder('Animal', extends: 'Organism')
..addMethod(new MethodBuilder.returnVoid('eat')
..setExpression(new ExpressionBuilder.invoke('print',
positional: [new LiteralString('Yum!')])));
var base = reference('Organism');
var clazz = new ClassBuilder('Animal', asExtends: base);
clazz.addMethod(
new MethodBuilder.returnVoid(
'eat',
returns: reference('print').call([literal('Yum')]),
),
);
```

Outputs:
Expand All @@ -53,26 +58,16 @@ use prefixes to avoid symbol conflicts:

```dart
var lib = new LibraryBuilder.scope()
..addDeclaration(new MethodBuilder(
name: 'doThing',
returns: new TypeBuilder(
'Thing',
importFrom: 'package:thing/thing.dart',
),
))
..addDeclaration(new MethodBuilder(
name: 'doOtherThing',
returns: new TypeBuilder(
'Thing',
importFrom: 'package:thing/alternative.dart',
))
..addParameter(new ParameterBuilder(
'thing',
type: new TypeBuilder(
'Thing',
importFrom: 'package:thing/thing.dart',
),
)));
..addMembers([
new MethodBuilder(
'doThing',
returnType: reference('Thing', 'package:thing/thing.dart'),
),
new MethodBuilder(
'doOtherThing',
returnType: reference('Thing', 'package:thing/alternative.dart'),
),
]);
```

Outputs:
Expand All @@ -81,5 +76,5 @@ import 'package:thing/thing.dart' as _i1;
import 'package:thing/alternative.dart' as _i2;
_i1.Thing doThing() {}
_i2.Thing doOtherThing(_i1.Thing thing) {}
_i2.Thing doOtherThing() {}
```
8 changes: 0 additions & 8 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ linter:
- valid_regexps
- always_declare_return_types
- annotate_overrides
- avoid_as
- avoid_init_to_null
- avoid_return_types_on_setters
- await_only_futures
Expand All @@ -25,17 +24,10 @@ linter:
- empty_constructor_bodies
- library_names
- library_prefixes
- non_constant_identifier_names
- only_throw_errors
- overridden_fields
- package_api_docs
- package_prefixed_library_names
- prefer_is_not_empty
- public_member_api_docs
- slash_for_doc_comments
- sort_constructors_first
- sort_unnamed_constructors_first
- type_init_formals
- unnecessary_brace_in_string_interp
- unnecessary_getters_setters
- package_names
10 changes: 10 additions & 0 deletions doc/SHORT_LINKS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
When using `goo.gl` links in the library, please re-use the following:

- References to the Dart Library
- `dart:async`: https://goo.gl/Ulqbfz
- `dart:core`: https://goo.gl/XbSfmT

- References to Github
- CONTRIBUTING.md: https://goo.gl/2LvV7f
- File an issue to update `dart/*.dart`: https://goo.gl/Xc6xAz

95 changes: 29 additions & 66 deletions lib/code_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,69 +2,32 @@
// 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.

/// Code builder is a fluent Dart API for generating valid Dart source code.
///
/// Generally speaking, code generation usually is done through a series of
/// string concatenation which results in messy and sometimes invalid code that
/// is not easily readable.
///
/// Code builder uses the `analyzer` package to create real Dart language ASTs,
/// which, while not guaranteed to be correct, always follows the analyzer's
/// own understood format.
///
/// Code builder also adds a more narrow and user-friendly API. For example
/// creating a class with a method is an easy affair:
/// new ClassBuilder('Animal', extends: 'Organism')
/// ..addMethod(new MethodBuilder.returnVoid('eat')
/// ..setExpression(new ExpressionBuilder.invoke('print',
/// positional: [new LiteralString('Yum!')])));
///
/// Outputs:
/// class Animal extends Organism {
/// void eat() => print('Yum!');
/// }
///
/// This package is in development and APIs are subject to frequent change. See
/// the `README.md` and `CONTRIBUTING.md` for more information.
library code_builder;

import 'package:analyzer/analyzer.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:dart_style/dart_style.dart';
import 'package:meta/meta.dart';

import 'src/analyzer_patch.dart';
import 'src/tokens.dart';

part 'src/builders/annotation_builder.dart';
part 'src/builders/class_builder.dart';
part 'src/builders/constructor_builder.dart';
part 'src/builders/expression_builder.dart';
part 'src/builders/field_builder.dart';
part 'src/builders/file_builder.dart';
part 'src/builders/method_builder.dart';
part 'src/builders/parameter_builder.dart';
part 'src/builders/statement_builder.dart';
part 'src/builders/type_builder.dart';
part 'src/pretty_printer.dart';
part 'src/scope.dart';

final DartFormatter _dartfmt = new DartFormatter();

// Simplifies some of the builders by having a mutable node we clone from.
/// Returns [source] formatted by `dartfmt`.
@visibleForTesting
String dartfmt(String source) => _dartfmt.format(source);

SimpleIdentifier _stringIdentifier(String s) =>
new SimpleIdentifier(stringToken(s));

Literal _stringLiteral(String s) => new SimpleStringLiteral(stringToken(s), s);

/// Base class for building and emitting a Dart language [AstNode].
abstract class CodeBuilder<A extends AstNode> {
/// Returns a copy-safe [AstNode] representing the current builder state.
///
/// Uses [scope] to output an AST re-written to use appropriate prefixes.
A toAst([Scope scope = const Scope.identity()]);
}
export 'src/builders/annotation.dart' show AnnotationBuilder;
export 'src/builders/class.dart'
show asStatic, clazz, extend, implement, mixin, ClassBuilder;
export 'src/builders/expression.dart'
show literal, ExpressionBuilder, InvocationBuilder;
export 'src/builders/field.dart'
show varConst, varField, varFinal, FieldBuilder;
export 'src/builders/file.dart' show ImportBuilder, LibraryBuilder, PartBuilder;
export 'src/builders/method.dart'
show
constructor,
constructorNamed,
getter,
setter,
thisField,
lambda,
method,
named,
ConstructorBuilder,
MethodBuilder,
ValidMethodMember;
export 'src/builders/parameter.dart' show parameter, ParameterBuilder;
export 'src/pretty_printer.dart' show prettyToSource;
export 'src/builders/reference.dart'
show explicitThis, reference, ReferenceBuilder;
export 'src/builders/shared.dart' show AstBuilder, Scope;
export 'src/builders/statement.dart'
show ifThen, elseIf, elseThen, IfStatementBuilder, StatementBuilder;
export 'src/builders/type.dart' show NewInstanceBuilder, TypeBuilder;
41 changes: 41 additions & 0 deletions lib/dart/async.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) 2016, 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.

/// Contains references to the `dart:async` SDK for use in code generation.
///
/// This library is currently *experimental*, and is subject to change; it is
/// currently manually maintained but there might be a strong use case for this
/// to be automatically generated (at least partially) in the near future.
///
/// ## Usage
///
/// First import the library:
/// import 'package:code_builder/code_builder.dart';
/// import 'package:code_builder/dart/async.dart';
///
/// All references are _namespaced_ under [lib$async]. Try it:
/// // Outputs: new Future.value('Hello')
/// async.Future.newInstanceNamed('value', [literal('Hello')]);
///
/// If you are [missing a symbol from `dart:async`](https://goo.gl/XbSfmT)
/// please send us a [pull request](https://goo.gl/2LvV7f) or
/// [file an issue](https://goo.gl/IooPfl).
library code_builder.dart.async;

import 'dart:async' as dart_async;

import 'package:code_builder/code_builder.dart';

/// References to `dart:async`.
final DartAsync lib$async = new DartAsync._();

/// References to the `dart:async` library for code generation. See [lib$async].
class DartAsync {
/// References [dart_async.Future].
final ReferenceBuilder Future = _ref('Future');

DartAsync._();

static ReferenceBuilder _ref(String name) => reference(name, 'dart:async');
}
Loading

0 comments on commit 62d8db1

Please sign in to comment.